/** * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md. */ /* globals document */ import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor'; import Typing from '../src/typing'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import Undo from '@ckeditor/ckeditor5-undo/src/undo'; import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold'; import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic'; import Enter from '@ckeditor/ckeditor5-enter/src/enter'; import Range from '@ckeditor/ckeditor5-engine/src/model/range'; import Position from '@ckeditor/ckeditor5-engine/src/model/position'; import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view'; describe( 'InputCommand integration', () => { let editor, doc, viewDocument, boldView, italicView; beforeEach( () => { const editorElement = document.createElement( 'div' ); document.body.appendChild( editorElement ); return ClassicTestEditor.create( editorElement, { plugins: [ Typing, Paragraph, Undo, Bold, Italic, Enter ], typing: { undoStep: 3 } } ) .then( newEditor => { editor = newEditor; doc = editor.document; viewDocument = editor.editing.view; boldView = editor.ui.componentFactory.create( 'bold' ); italicView = editor.ui.componentFactory.create( 'italic' ); } ); } ); afterEach( () => { return editor.destroy(); } ); function expectOutput( modelOutput, viewOutput ) { expect( getModelData( editor.document ) ).to.equal( modelOutput ); expect( getViewData( viewDocument ) ).to.equal( viewOutput ); } function simulateTyping( text ) { // While typing, every character is an atomic change. text.split( '' ).forEach( ( character ) => { editor.execute( 'input', { text: character } ); } ); } function simulateBatches( batches ) { // Use longer text at once in input command. batches.forEach( ( batch ) => { editor.execute( 'input', { text: batch } ); } ); } function setSelection( pathA, pathB ) { doc.selection.setRanges( [ new Range( new Position( doc.getRoot(), pathA ), new Position( doc.getRoot(), pathB ) ) ] ); } describe( 'InputCommand integration', () => { it( 'resets the buffer on typing respecting typing.undoStep', () => { setModelData( doc, '0[]' ); simulateTyping( '123456789' ); expectOutput( '0123456789[]', '

0123456789{}

' ); editor.execute( 'undo' ); expectOutput( '0123456[]', '

0123456{}

' ); editor.execute( 'undo' ); expectOutput( '0123[]', '

0123{}

' ); editor.execute( 'redo' ); expectOutput( '0123456[]', '

0123456{}

' ); } ); it( 'resets the buffer on text insertion respecting typing.undoStep', () => { setModelData( doc, '0[]' ); simulateBatches( [ '1234', '5', '678', '9' ] ); expectOutput( '0123456789[]', '

0123456789{}

' ); editor.execute( 'undo' ); expectOutput( '012345678[]', '

012345678{}

' ); editor.execute( 'undo' ); expectOutput( '01234[]', '

01234{}

' ); editor.execute( 'redo' ); expectOutput( '012345678[]', '

012345678{}

' ); } ); it( 'resets the buffer when selection changes', () => { setModelData( doc, 'Foo[] Bar' ); setSelection( [ 0, 5 ], [ 0, 5 ] ); simulateTyping( '1' ); setSelection( [ 0, 7 ], [ 0, 8 ] ); simulateTyping( '2' ); expectOutput( 'Foo B1a2[]', '

Foo B1a2{}

' ); editor.execute( 'undo' ); expectOutput( 'Foo B1a[r]', '

Foo B1a{r}

' ); editor.execute( 'undo' ); expectOutput( 'Foo B[]ar', '

Foo B{}ar

' ); editor.execute( 'redo' ); expectOutput( 'Foo B1[]ar', '

Foo B1{}ar

' ); } ); it( 'resets the buffer when selection changes (with enter)', () => { setModelData( doc, 'Foo[]Bar' ); simulateTyping( '1' ); editor.execute( 'enter' ); setSelection( [ 1, 3 ], [ 1, 3 ] ); simulateTyping( '2' ); editor.execute( 'enter' ); simulateTyping( 'Baz' ); expectOutput( 'Foo1Bar2Baz[]', '

Foo1

Bar2

Baz{}

' ); editor.execute( 'undo' ); expectOutput( 'Foo1Bar2[]', '

Foo1

Bar2

[]

' ); editor.execute( 'undo' ); expectOutput( 'Foo1Bar2[]', '

Foo1

Bar2{}

' ); editor.execute( 'undo' ); expectOutput( 'Foo1Bar[]', '

Foo1

Bar{}

' ); editor.execute( 'redo' ); expectOutput( 'Foo1Bar2[]', '

Foo1

Bar2{}

' ); } ); it( 'resets the buffer when attribute changes', () => { setModelData( doc, 'Foo[] Bar' ); simulateTyping( ' ' ); boldView.fire( 'execute' ); simulateTyping( 'B' ); italicView.fire( 'execute' ); simulateTyping( 'a' ); boldView.fire( 'execute' ); italicView.fire( 'execute' ); simulateTyping( 'z' ); expectOutput( 'Foo <$text bold="true">B<$text italic="true"><$text bold="true">az[] Bar', '

Foo Baz{} Bar

' ); editor.execute( 'undo' ); expectOutput( 'Foo <$text bold="true">B<$text italic="true"><$text bold="true">a<$text bold="true" italic="true">[] Bar', '

Foo Ba{} Bar

' ); editor.execute( 'undo' ); expectOutput( 'Foo <$text bold="true">B[] Bar', '

Foo B{} Bar

' ); } ); } ); } );