|
@@ -6,14 +6,10 @@
|
|
|
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
|
|
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
|
|
|
import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
|
|
import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
|
|
|
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
|
|
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
|
|
|
-import Typing from '@ckeditor/ckeditor5-typing/src/typing';
|
|
|
|
|
-import Command from '@ckeditor/ckeditor5-core/src/command';
|
|
|
|
|
-import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
|
|
|
|
|
|
|
+import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
|
|
|
import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
|
|
import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
|
|
|
-import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
|
|
|
|
|
|
|
|
|
|
import RestrictedEditingEditing from './../src/restrictededitingediting';
|
|
import RestrictedEditingEditing from './../src/restrictededitingediting';
|
|
|
-import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting';
|
|
|
|
|
|
|
|
|
|
describe( 'RestrictedEditingEditing', () => {
|
|
describe( 'RestrictedEditingEditing', () => {
|
|
|
let editor;
|
|
let editor;
|
|
@@ -124,759 +120,4 @@ describe( 'RestrictedEditingEditing', () => {
|
|
|
} );
|
|
} );
|
|
|
} );
|
|
} );
|
|
|
} );
|
|
} );
|
|
|
-
|
|
|
|
|
- describe( 'editing behavior', () => {
|
|
|
|
|
- let model;
|
|
|
|
|
-
|
|
|
|
|
- beforeEach( async () => {
|
|
|
|
|
- editor = await VirtualTestEditor.create( { plugins: [ Paragraph, Typing, RestrictedEditingEditing ] } );
|
|
|
|
|
- model = editor.model;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- afterEach( async () => {
|
|
|
|
|
- await editor.destroy();
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should keep markers in the view when editable region is edited', () => {
|
|
|
|
|
- setModelData( model,
|
|
|
|
|
- '<paragraph>foo bar baz</paragraph>' +
|
|
|
|
|
- '<paragraph>xxx y[]yy zzz</paragraph>'
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- const firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
- const secondParagraph = model.document.getRoot().getChild( 1 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange( writer.createPositionAt( firstParagraph, 4 ), writer.createPositionAt( firstParagraph, 7 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:2', {
|
|
|
|
|
- range: writer.createRange(
|
|
|
|
|
- writer.createPositionAt( secondParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( secondParagraph, 7 )
|
|
|
|
|
- ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- model.insertContent( writer.createText( 'R', model.document.selection.getAttributes() ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- const expectedView = '<p>foo <span class="ck-restricted-editing-exception">bar</span> baz</p>' +
|
|
|
|
|
- '<p>xxx <span class="ck-restricted-editing-exception">yRyy</span> zzz</p>';
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.getData() ).to.equal( expectedView );
|
|
|
|
|
- expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal( expectedView );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should block user typing outside exception markers', () => {
|
|
|
|
|
- setModelData( model, '<paragraph>foo []bar baz</paragraph>' );
|
|
|
|
|
-
|
|
|
|
|
- editor.execute( 'input', { text: 'X' } );
|
|
|
|
|
-
|
|
|
|
|
- assertEqualMarkup( getModelData( model ), '<paragraph>foo []bar baz</paragraph>' );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should not block user typing inside exception marker', () => {
|
|
|
|
|
- setModelData( model, '<paragraph>[]foo bar baz</paragraph>' );
|
|
|
|
|
- const firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange( writer.createPositionAt( firstParagraph, 4 ), writer.createPositionAt( firstParagraph, 7 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
- editor.execute( 'input', { text: 'X' } );
|
|
|
|
|
-
|
|
|
|
|
- assertEqualMarkup( getModelData( model ), '<paragraph>foo bX[]ar baz</paragraph>' );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should extend maker when typing on the marker boundary (end)', () => {
|
|
|
|
|
- setModelData( model, '<paragraph>foo bar[] baz</paragraph>' );
|
|
|
|
|
- const firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange( writer.createPositionAt( firstParagraph, 4 ), writer.createPositionAt( firstParagraph, 7 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- editor.execute( 'input', { text: 'X' } );
|
|
|
|
|
-
|
|
|
|
|
- assertEqualMarkup( getModelData( model ), '<paragraph>foo barX[] baz</paragraph>' );
|
|
|
|
|
- const markerRange = editor.model.markers.get( 'restricted-editing-exception:1' ).getRange();
|
|
|
|
|
- const expectedRange = model.createRange(
|
|
|
|
|
- model.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- model.createPositionAt( firstParagraph, 8 )
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- expect( markerRange.isEqual( expectedRange ) ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should extend marker when typing on the marker boundary (start)', () => {
|
|
|
|
|
- setModelData( model, '<paragraph>foo []bar baz</paragraph>' );
|
|
|
|
|
- const firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange( writer.createPositionAt( firstParagraph, 4 ), writer.createPositionAt( firstParagraph, 7 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- editor.execute( 'input', { text: 'X' } );
|
|
|
|
|
-
|
|
|
|
|
- assertEqualMarkup( getModelData( model ), '<paragraph>foo X[]bar baz</paragraph>' );
|
|
|
|
|
- const markerRange = editor.model.markers.get( 'restricted-editing-exception:1' ).getRange();
|
|
|
|
|
-
|
|
|
|
|
- const expectedRange = model.createRange(
|
|
|
|
|
- model.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- model.createPositionAt( firstParagraph, 8 )
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- expect( markerRange.isEqual( expectedRange ) ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should extend marker when typing on the marker boundary (collapsed marker)', () => {
|
|
|
|
|
- setModelData( model, '<paragraph>[]foo bar baz</paragraph>' );
|
|
|
|
|
- const firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange( writer.createPositionAt( firstParagraph, 4 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createPositionAt( firstParagraph, 4 ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- editor.execute( 'input', { text: 'X' } );
|
|
|
|
|
-
|
|
|
|
|
- assertEqualMarkup( getModelData( model ), '<paragraph>foo X[]bar baz</paragraph>' );
|
|
|
|
|
- const markerRange = editor.model.markers.get( 'restricted-editing-exception:1' ).getRange();
|
|
|
|
|
-
|
|
|
|
|
- const expectedRange = model.createRange(
|
|
|
|
|
- model.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- model.createPositionAt( firstParagraph, 5 )
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- expect( markerRange.isEqual( expectedRange ) ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should not move collapsed marker to $graveyard', () => {
|
|
|
|
|
- setModelData( model, '<paragraph>foo b[]ar baz</paragraph>' );
|
|
|
|
|
- const firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 )
|
|
|
|
|
- ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- editor.execute( 'delete' );
|
|
|
|
|
-
|
|
|
|
|
- assertEqualMarkup( getModelData( model ), '<paragraph>foo []ar baz</paragraph>' );
|
|
|
|
|
- const markerRange = editor.model.markers.get( 'restricted-editing-exception:1' ).getRange();
|
|
|
|
|
-
|
|
|
|
|
- const expectedRange = model.createRange(
|
|
|
|
|
- model.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- model.createPositionAt( firstParagraph, 4 )
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- expect( markerRange.isEqual( expectedRange ) ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- describe( 'commands behavior', () => {
|
|
|
|
|
- let model, firstParagraph;
|
|
|
|
|
-
|
|
|
|
|
- beforeEach( async () => {
|
|
|
|
|
- editor = await VirtualTestEditor.create( { plugins: [ Paragraph, Typing, RestrictedEditingEditing ] } );
|
|
|
|
|
- model = editor.model;
|
|
|
|
|
-
|
|
|
|
|
- setModelData( model, '<paragraph>[]foo bar baz</paragraph>' );
|
|
|
|
|
- firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- afterEach( async () => {
|
|
|
|
|
- await editor.destroy();
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- describe( 'undo', () => {
|
|
|
|
|
- beforeEach( () => {
|
|
|
|
|
- editor.commands.add( 'undo', buildFakeCommand( editor ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled outside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'undo' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled inside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'undo' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- describe( 'redo', () => {
|
|
|
|
|
- beforeEach( () => {
|
|
|
|
|
- editor.commands.add( 'redo', buildFakeCommand( editor ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled outside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'redo' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled inside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'redo' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- const commandsEnabledOnWholeRange = [
|
|
|
|
|
- 'input', 'bold', 'link', 'italic'
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- for ( const commandName of commandsEnabledOnWholeRange ) {
|
|
|
|
|
- describe( commandName, () => {
|
|
|
|
|
- beforeEach( () => {
|
|
|
|
|
- editor.commands.add( commandName, buildFakeCommand( editor ) );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 'end' );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is outside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled when caret is inside exception marker (not touching boundaries)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is inside other marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'foo-bar:1', {
|
|
|
|
|
- range: writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 0 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 3 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled when caret is inside exception marker (start boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 4 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled when caret is inside exception marker (end boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 7 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for multi-range selection (collapsed ranges)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( [
|
|
|
|
|
- writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 )
|
|
|
|
|
- ),
|
|
|
|
|
- writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 9 )
|
|
|
|
|
- )
|
|
|
|
|
- ] );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection that expands over exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 0 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection that is fully contained inside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection inside exception marker (start position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection inside exception marker (end position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection is equal to exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection with more then one range', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( [
|
|
|
|
|
- writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ),
|
|
|
|
|
- writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 8 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 9 )
|
|
|
|
|
- )
|
|
|
|
|
- ] );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( commandName ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- describe( 'delete', () => {
|
|
|
|
|
- beforeEach( () => {
|
|
|
|
|
- editor.commands.add( 'delete', buildFakeCommand( editor ) );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 'end' );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is outside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled when caret is inside exception marker (not touching boundaries)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is inside exception marker (start boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 4 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled when caret is inside exception marker (end boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 7 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection that expands over exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 0 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection that is fully contained inside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection inside exception marker (start position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection inside exception marker (end position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection is equal to exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- describe( 'forwardDelete', () => {
|
|
|
|
|
- beforeEach( () => {
|
|
|
|
|
- editor.commands.add( 'forwardDelete', buildFakeCommand( editor ) );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 'end' );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is outside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled when caret is inside exception marker (not touching boundaries)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled when caret is inside exception marker (start boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 4 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is inside exception marker (end boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 7 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection that expands over exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 0 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection that is fully contained inside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection inside exception marker (start position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection inside exception marker (end position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be enabled for non-collapsed selection is equal to exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'forwardDelete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- describe( 'other', () => {
|
|
|
|
|
- beforeEach( () => {
|
|
|
|
|
- editor.commands.add( 'other', buildFakeCommand( editor ) );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 'end' );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled outside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled inside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 1 );
|
|
|
|
|
- } );
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is inside exception marker (not touching boundaries)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 5 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is inside exception marker (start boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 4 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled when caret is inside exception marker (end boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 7 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection that expands over exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 0 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection that is fully contained inside exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection inside exception marker (start position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 6 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection inside exception marker (end position on marker boundary)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 5 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- it( 'should be disabled for non-collapsed selection is equal to exception marker', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 )
|
|
|
|
|
- ) );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'other' ).isEnabled ).to.be.false;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- describe( 'commands integration', () => {
|
|
|
|
|
- let model, firstParagraph;
|
|
|
|
|
-
|
|
|
|
|
- beforeEach( async () => {
|
|
|
|
|
- editor = await VirtualTestEditor.create( { plugins: [ Paragraph, Typing, UndoEditing, RestrictedEditingEditing ] } );
|
|
|
|
|
- model = editor.model;
|
|
|
|
|
-
|
|
|
|
|
- setModelData( model, '<paragraph>[]foo bar baz</paragraph>' );
|
|
|
|
|
- firstParagraph = model.document.getRoot().getChild( 0 );
|
|
|
|
|
-
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.addMarker( 'restricted-editing-exception:1', {
|
|
|
|
|
- range: writer.createRange(
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 4 ),
|
|
|
|
|
- writer.createPositionAt( firstParagraph, 7 ) ),
|
|
|
|
|
- usingOperation: true,
|
|
|
|
|
- affectsData: true
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- afterEach( async () => {
|
|
|
|
|
- await editor.destroy();
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- describe( 'delete + undo', () => {
|
|
|
|
|
- it( 'should be enabled after data change (no selection change event on undo)', () => {
|
|
|
|
|
- model.change( writer => {
|
|
|
|
|
- writer.setSelection( firstParagraph, 7 );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- editor.execute( 'delete' );
|
|
|
|
|
- editor.execute( 'undo' );
|
|
|
|
|
-
|
|
|
|
|
- expect( editor.commands.get( 'delete' ).isEnabled ).to.be.true;
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
- } );
|
|
|
|
|
-
|
|
|
|
|
- class FakeCommand extends Command {
|
|
|
|
|
- refresh() {
|
|
|
|
|
- this.isEnabled = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- function buildFakeCommand( editor ) {
|
|
|
|
|
- return new FakeCommand( editor );
|
|
|
|
|
- }
|
|
|
|
|
} );
|
|
} );
|