|
|
@@ -1409,6 +1409,188 @@ describe( 'RestrictedEditingModeEditing', () => {
|
|
|
} );
|
|
|
} );
|
|
|
|
|
|
+ describe( 'custom keydown behaviour', () => {
|
|
|
+ let view, evtData;
|
|
|
+
|
|
|
+ beforeEach( async () => {
|
|
|
+ editor = await VirtualTestEditor.create( {
|
|
|
+ plugins: [ Paragraph, RestrictedEditingModeEditing, BoldEditing ]
|
|
|
+ } );
|
|
|
+
|
|
|
+ model = editor.model;
|
|
|
+ view = editor.editing.view;
|
|
|
+ } );
|
|
|
+
|
|
|
+ afterEach( () => {
|
|
|
+ return editor.destroy();
|
|
|
+ } );
|
|
|
+
|
|
|
+ describe( 'Ctrl+A handler', () => {
|
|
|
+ beforeEach( async () => {
|
|
|
+ evtData = {
|
|
|
+ keyCode: getCode( 'A' ),
|
|
|
+ ctrlKey: true,
|
|
|
+ preventDefault: sinon.spy(),
|
|
|
+ stopPropagation: sinon.spy()
|
|
|
+ };
|
|
|
+ } );
|
|
|
+
|
|
|
+ describe( 'collapsed selection', () => {
|
|
|
+ it( 'should select text only within an exception when selection is inside an exception', () => {
|
|
|
+ setModelData( model, '<paragraph>foo ba[]r baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>foo <marker>ba[]r</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledOnce( evtData.preventDefault );
|
|
|
+ sinon.assert.calledOnce( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should select text only within an exception when selection is at the begining of an exception', () => {
|
|
|
+ setModelData( model, '<paragraph>foo []bar baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>foo <marker>[]bar</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledOnce( evtData.preventDefault );
|
|
|
+ sinon.assert.calledOnce( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should select text only within an exception when selection is at the end of an exception', () => {
|
|
|
+ setModelData( model, '<paragraph>foo bar[] baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>foo <marker>bar[]</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledOnce( evtData.preventDefault );
|
|
|
+ sinon.assert.calledOnce( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should not change the selection if the caret is not inside an exception', () => {
|
|
|
+ setModelData( model, '<paragraph>foo ba[]r baz</paragraph>' );
|
|
|
+
|
|
|
+ // no markers
|
|
|
+ // <paragraph>foo ba[]r baz</paragraph>
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.notCalled( evtData.preventDefault );
|
|
|
+ sinon.assert.notCalled( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo ba[]r baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should not extend the selection outside an exception when press Ctrl+A second time', () => {
|
|
|
+ setModelData( model, '<paragraph>foo b[]ar baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>foo <marker>b[]ar</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledTwice( evtData.preventDefault );
|
|
|
+ sinon.assert.calledTwice( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
+
|
|
|
+ describe( 'non-collapsed selection', () => {
|
|
|
+ it( 'should select text within an exception when a whole selection range is inside an exception', () => {
|
|
|
+ setModelData( model, '<paragraph>fo[o ba]r baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph><marker>fo[o ba]r</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 0, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledOnce( evtData.preventDefault );
|
|
|
+ sinon.assert.calledOnce( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>[foo bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should select text within an exception when end of selection range is equal exception end', () => {
|
|
|
+ setModelData( model, '<paragraph>foo b[ar] baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>foo <marker>b[ar]</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledOnce( evtData.preventDefault );
|
|
|
+ sinon.assert.calledOnce( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should select text within an exception when start of selection range is equal exception start', () => {
|
|
|
+ setModelData( model, '<paragraph>foo [ba]r baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>foo <marker>[ba]r</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledOnce( evtData.preventDefault );
|
|
|
+ sinon.assert.calledOnce( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should not select text within an exception when a part of the selection range is outside an exception', () => {
|
|
|
+ setModelData( model, '<paragraph>fo[o ba]r baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>fo[o <marker>ba]r</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.notCalled( evtData.preventDefault );
|
|
|
+ sinon.assert.notCalled( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>fo[o ba]r baz</paragraph>' );
|
|
|
+ } );
|
|
|
+
|
|
|
+ it( 'should not extend the selection outside an exception when press Ctrl+A second time', () => {
|
|
|
+ setModelData( model, '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+
|
|
|
+ const paragraph = model.document.getRoot().getChild( 0 );
|
|
|
+
|
|
|
+ // <paragraph>foo <marker>[bar]</marker> baz</paragraph>
|
|
|
+ addExceptionMarker( 4, 7, paragraph );
|
|
|
+
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+ view.document.fire( 'keydown', evtData );
|
|
|
+
|
|
|
+ sinon.assert.calledTwice( evtData.preventDefault );
|
|
|
+ sinon.assert.calledTwice( evtData.stopPropagation );
|
|
|
+ expect( getModelData( model ) ).to.be.equal( '<paragraph>foo [bar] baz</paragraph>' );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
+
|
|
|
// Helper method that creates an exception marker inside given parent.
|
|
|
// Marker range is set to given position offsets (start, end).
|
|
|
function addExceptionMarker( startOffset, endOffset = startOffset, parent, id = 1 ) {
|