/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
import RestrictedEditingModeNavigationCommand from '../src/restrictededitingmodenavigationcommand';
describe( 'RestrictedEditingModeNavigationCommand', () => {
let editor, forwardCommand, backwardCommand, model;
beforeEach( () => {
return ModelTestEditor
.create()
.then( newEditor => {
editor = newEditor;
model = editor.model;
forwardCommand = new RestrictedEditingModeNavigationCommand( editor, 'forward' );
backwardCommand = new RestrictedEditingModeNavigationCommand( editor, 'backward' );
model.schema.register( 'paragraph', { inheritAllFrom: '$block' } );
editor.model.schema.extend( '$text', { allowAttributes: [ 'restrictedEditingException' ] } );
} );
} );
afterEach( () => {
forwardCommand.destroy();
backwardCommand.destroy();
return editor.destroy();
} );
describe( 'forward command', () => {
describe( 'isEnabled', () => {
describe( 'collapsed selection', () => {
it( 'should be true when there is a marker after the selection position', () => {
setModelData( model, '[]foo bar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// []foo bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.true;
} );
it( 'should be false when there is no marker after the selection position', () => {
setModelData( model, 'foo bar baz[]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar baz[]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.false;
} );
it( 'should be false when the selection position is at a marker start and there are no more markers', () => {
setModelData( model, 'foo []bar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo []bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.false;
} );
it( 'should be false when the selection position is in a marker and there are no more markers', () => {
setModelData( model, 'foo b[]ar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo b[]ar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.false;
} );
it( 'should be false when the selection position is at a marker end and there are no more markers', () => {
setModelData( model, 'foo bar[] baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar[] baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.false;
} );
} );
describe( 'expanded selection', () => {
it( 'should be true when there is a marker after the first selection position', () => {
setModelData( model, '[fo]o bar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// [fo]o bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.true;
} );
it( 'should be true when the selection overlaps the marker but the start position is before it', () => {
setModelData( model, '[foo ba]r baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// [foo ba]r baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.true;
} );
it( 'should be false when the selection overlaps the marker but the start position is after it', () => {
setModelData( model, 'foo ba[r baz]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo ba[r baz]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( forwardCommand.isEnabled ).to.be.false;
} );
} );
} );
describe( 'execute()', () => {
describe( 'collapsed selection', () => {
it( 'should move to the next marker', () => {
setModelData( model, '[]foo bar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// []foo bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
// []foo bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo [bar] baz' );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo bar [baz]' );
} );
it( 'should move to the next marker when at the end of adjacent one', () => {
setModelData( model, 'foo[]bar' );
const fiirstParagraph = model.document.getRoot().getChild( 0 );
const secondParagraph = model.document.getRoot().getChild( 1 );
// foo[]bar
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRangeIn( fiirstParagraph ),
usingOperation: true,
affectsData: true
} );
} );
// foo[]bar
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRangeIn( secondParagraph ),
usingOperation: true,
affectsData: true
} );
} );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo[bar]' );
} );
it( 'should move to the closest marker when created in a reverse order', () => {
setModelData( model, '[]foo bar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// []foo bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
// []foo bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo [bar] baz' );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo bar [baz]' );
} );
} );
describe( 'expanded selection', () => {
it( 'should move to the next marker when the selection end overlaps the marker', () => {
setModelData( model, '[foo b]ar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// [foo b]ar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
// [foo b]ar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo [bar] baz' );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo bar [baz]' );
} );
it( 'should move to the next marker when the selection start overlaps the marker', () => {
setModelData( model, 'foo b[ar b]az' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo b[ar b]az
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
// foo b[ar b]az
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
forwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo bar [baz]' );
} );
} );
} );
} );
describe( 'backward command', () => {
describe( 'isEnabled', () => {
describe( 'collapsed selection', () => {
it( 'should be true when there is a marker before the selection position', () => {
setModelData( model, 'foo bar baz[]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.true;
} );
it( 'should be false when there is no marker before the selection position', () => {
setModelData( model, '[]foo bar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// []foo bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.false;
} );
it( 'should be false when the selection position is at a marker end and there are no more markers', () => {
setModelData( model, 'foo bar[] baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar[] baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.false;
} );
it( 'should be false when the selection position is in a marker and there are no more markers', () => {
setModelData( model, 'foo b[]ar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo b[]ar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.false;
} );
it( 'should be false when the selection position is at a marker start and there are no more markers', () => {
setModelData( model, 'foo []bar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo []bar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.false;
} );
} );
describe( 'expanded selection', () => {
it( 'should be true when there is a marker before the first selection position', () => {
setModelData( model, 'foo bar b[az]' );
const paragraph = model.document.getRoot().getChild( 0 );
// [fo]o bar b[az]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.true;
} );
it( 'should be false when the selection overlaps the marker but the start position is after it', () => {
setModelData( model, 'foo b[ar baz]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo b[ar baz]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.false;
} );
it( 'should be false when the selection overlaps the marker but the after position is after it', () => {
setModelData( model, '[foo b]ar baz' );
const paragraph = model.document.getRoot().getChild( 0 );
// [foo b]ar baz
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
expect( backwardCommand.isEnabled ).to.be.false;
} );
} );
} );
describe( 'execute()', () => {
describe( 'collapsed selection', () => {
it( 'should move to the previous marker', () => {
setModelData( model, 'foo bar baz[]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar baz[]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
// foo bar baz[]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
backwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo [bar] baz' );
} );
it( 'should move to the previous marker when at the beginning of adjacent one', () => {
setModelData( model, 'foo[]bar' );
const fiirstParagraph = model.document.getRoot().getChild( 0 );
const secondParagraph = model.document.getRoot().getChild( 1 );
// foo[]bar
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRangeIn( fiirstParagraph ),
usingOperation: true,
affectsData: true
} );
} );
// foo[]bar
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRangeIn( secondParagraph ),
usingOperation: true,
affectsData: true
} );
} );
backwardCommand.execute();
expect( getModelData( model ) ).to.equal( '[foo]bar' );
} );
it( 'should move to the closest previous marker', () => {
setModelData( model, 'foo bar baz qux[]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar baz qux[]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
// foo bar baz qux[]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
backwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo bar [baz] qux' );
backwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo [bar] baz qux' );
} );
it( 'should move to the closest previous marker when created in a reverse order', () => {
setModelData( model, 'foo bar baz qux[]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar baz qux[]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
// foo bar baz qux[]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
backwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo bar [baz] qux' );
backwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo [bar] baz qux' );
} );
} );
describe( 'expanded selection', () => {
it( 'should move to the previous marker when the selection end overlaps the marker', () => {
setModelData( model, 'foo bar b[az]' );
const paragraph = model.document.getRoot().getChild( 0 );
// foo bar b[az]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:1', {
range: writer.createRange( writer.createPositionAt( paragraph, 4 ), writer.createPositionAt( paragraph, 7 ) ),
usingOperation: true,
affectsData: true
} );
} );
// foo bar b[az]
model.change( writer => {
writer.addMarker( 'restrictedEditingException:2', {
range: writer.createRange( writer.createPositionAt( paragraph, 8 ), writer.createPositionAt( paragraph, 11 ) ),
usingOperation: true,
affectsData: true
} );
} );
backwardCommand.execute();
expect( getModelData( model ) ).to.equal( 'foo [bar] baz' );
} );
} );
} );
} );
} );