import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard'; import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { modelTable } from './_utils/utils'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import ImageEditing from '@ckeditor/ckeditor5-image/src/image/imageediting'; import MediaEmbedEditing from '@ckeditor/ckeditor5-media-embed/src/mediaembedediting'; import TableNavigation from '../src/tablenavigation'; import TableEditing from '../src/tableediting'; describe( 'TableNavigation', () => { let editor, model; beforeEach( () => { return VirtualTestEditor .create( { plugins: [ TableEditing, TableNavigation, Paragraph, ImageEditing, MediaEmbedEditing ] } ) .then( newEditor => { editor = newEditor; model = editor.model; } ); } ); afterEach( () => { editor.destroy(); } ); it( 'should have pluginName', () => { expect( TableNavigation.pluginName ).to.equal( 'TableNavigation' ); } ); describe( 'caret movement', () => { let domEvtDataStub; beforeEach( () => { domEvtDataStub = { keyCode: getCode( 'Tab' ), preventDefault: sinon.spy(), stopPropagation: sinon.spy() }; } ); it( 'should do nothing if not tab pressed', () => { setModelData( model, modelTable( [ [ '11', '12[]' ] ] ) ); domEvtDataStub.keyCode = getCode( 'a' ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.notCalled( domEvtDataStub.preventDefault ); sinon.assert.notCalled( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '12[]' ] ] ) ); } ); it( 'should do nothing if Ctrl+Tab is pressed', () => { setModelData( model, modelTable( [ [ '11', '12[]' ] ] ) ); domEvtDataStub.ctrlKey = true; editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.notCalled( domEvtDataStub.preventDefault ); sinon.assert.notCalled( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '12[]' ] ] ) ); } ); describe( 'on TAB', () => { it( 'should do nothing if selection is not in a table', () => { setModelData( model, '[]' + modelTable( [ [ '11', '12' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.notCalled( domEvtDataStub.preventDefault ); sinon.assert.notCalled( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), '[]' + modelTable( [ [ '11', '12' ] ] ) ); } ); it( 'should move to next cell', () => { setModelData( model, modelTable( [ [ '11[]', '12' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( domEvtDataStub.preventDefault ); sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '[12]' ] ] ) ); } ); it( 'should create another row and move to first cell in new row', () => { setModelData( model, modelTable( [ [ '11', '[12]' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '12' ], [ '[]', '' ] ] ) ); } ); it( 'should not create another row and not move the caret if insertTableRowBelow command is disabled', () => { setModelData( model, modelTable( [ [ '11', '12[]' ] ] ) ); const insertTableRowBelowCommand = editor.commands.get( 'insertTableRowBelow' ); insertTableRowBelowCommand.forceDisabled( 'test' ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '12[]' ] ] ) ); } ); it( 'should move to the first cell of next row if on end of a row', () => { setModelData( model, modelTable( [ [ '11', '12[]' ], [ '21', '22' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '12' ], [ '[21]', '22' ] ] ) ); } ); it( 'should move to the next table cell if part of block content is selected', () => { setModelData( model, modelTable( [ [ '11', '12[foo]bar', '13' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '12foobar', '[13]' ] ] ) ); } ); it( 'should move to next cell with an image', () => { setModelData( model, modelTable( [ [ '11[]', 'foo' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( domEvtDataStub.preventDefault ); sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '[foo]' ] ] ) ); } ); it( 'should move to next cell with an blockQuote', () => { model.schema.register( 'blockQuote', { allowWhere: '$block', allowContentOf: '$root' } ); editor.conversion.elementToElement( { model: 'blockQuote', view: 'blockquote' } ); setModelData( model, modelTable( [ [ '11[]', '
foo
' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( domEvtDataStub.preventDefault ); sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '
[foo]
' ] ] ) ); } ); it( 'should listen with lower priority then its children', () => { // Cancel TAB event. editor.keystrokes.set( 'Tab', ( data, cancel ) => cancel() ); setModelData( model, modelTable( [ [ '11[]', '12' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( domEvtDataStub.preventDefault ); sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11[]', '12' ] ] ) ); } ); describe( 'on table widget selected', () => { beforeEach( () => { editor.model.schema.register( 'block', { allowWhere: '$block', allowContentOf: '$block', isObject: true } ); editor.conversion.elementToElement( { model: 'block', view: 'block' } ); } ); it( 'should move caret to the first table cell on TAB', () => { const spy = sinon.spy(); editor.keystrokes.set( 'Tab', spy, { priority: 'lowest' } ); setModelData( model, '[' + modelTable( [ [ '11', '12' ] ] ) + ']' ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( domEvtDataStub.preventDefault ); sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '[11]', '12' ] ] ) ); // Should cancel event - so no other tab handler is called. sinon.assert.notCalled( spy ); } ); it( 'shouldn\'t do anything on other blocks', () => { const spy = sinon.spy(); editor.editing.view.document.on( 'keydown', spy ); setModelData( model, '[foo]' ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.notCalled( domEvtDataStub.preventDefault ); sinon.assert.notCalled( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), '[foo]' ); // Should not cancel event. sinon.assert.calledOnce( spy ); } ); } ); } ); describe( 'on SHIFT+TAB', () => { beforeEach( () => { domEvtDataStub.shiftKey = true; } ); it( 'should do nothing if selection is not in a table', () => { setModelData( model, '[]' + modelTable( [ [ '11', '12' ] ] ) ); domEvtDataStub.keyCode = getCode( 'Tab' ); domEvtDataStub.shiftKey = true; editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.notCalled( domEvtDataStub.preventDefault ); sinon.assert.notCalled( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), '[]' + modelTable( [ [ '11', '12' ] ] ) ); } ); it( 'should move to previous cell', () => { setModelData( model, modelTable( [ [ '11', '12[]' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( domEvtDataStub.preventDefault ); sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '[11]', '12' ] ] ) ); } ); it( 'should not move if caret is in first table cell', () => { setModelData( model, 'foo' + modelTable( [ [ '[]11', '12' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); assertEqualMarkup( getModelData( model ), 'foo' + modelTable( [ [ '[]11', '12' ] ] ) ); } ); it( 'should move to the last cell of previous row if on beginning of a row', () => { setModelData( model, modelTable( [ [ '11', '12' ], [ '[]21', '22' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '11', '[12]' ], [ '21', '22' ] ] ) ); } ); it( 'should move to the previous table cell if part of block content is selected', () => { setModelData( model, modelTable( [ [ '11', '12[foo]bar', '13' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '[11]', '12foobar', '13' ] ] ) ); } ); it( 'should move to previous cell with an image', () => { setModelData( model, modelTable( [ [ 'foo', 'bar[]' ] ] ) ); editor.editing.view.document.fire( 'keydown', domEvtDataStub ); sinon.assert.calledOnce( domEvtDataStub.preventDefault ); sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); assertEqualMarkup( getModelData( model ), modelTable( [ [ '[foo]', 'bar' ] ] ) ); } ); } ); } ); } );