/** * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md. */ import { Client, expectClients, clearBuffer } from './utils.js'; describe( 'transform', () => { let john; beforeEach( () => { return Client.get( 'john' ).then( client => ( john = client ) ); } ); afterEach( () => { clearBuffer(); return john.destroy(); } ); it( 'split, remove', () => { john.setData( 'Foo[]Bar' ); john.split(); john.setSelection( [ 1 ], [ 2 ] ); john.remove(); john.undo(); john.undo(); expectClients( 'FooBar' ); } ); it( 'move, merge', () => { john.setData( '[Foo]Bar' ); john.move( [ 2 ] ); john.setSelection( [ 1 ] ); john.merge(); john.undo(); john.undo(); expectClients( 'FooBar' ); } ); it.skip( 'move multiple, merge', () => { john.setData( '[FooBar]Xyz' ); john.move( [ 3 ] ); expectClients( 'XyzFooBar' ); john.setSelection( [ 1 ] ); john.merge(); expectClients( 'XyzFooBar' ); john.undo(); expectClients( 'XyzFooBar' ); john.undo(); // Wrong move is done. expectClients( 'FooBarXyz' ); } ); it( 'move inside unwrapped content', () => { john.setData( '
[Foo]Bar
' ); john.move( [ 0, 2 ] ); john.setSelection( [ 0, 0 ] ); john.unwrap(); john.undo(); john.undo(); expectClients( '
' + 'Foo' + 'Bar' + '
' ); } ); it( 'remove node, merge', () => { john.setData( 'Foo[Bar]' ); john.remove(); john.setSelection( [ 1 ] ); john.merge(); john.undo(); john.undo(); expectClients( 'FooBar' ); } ); it( 'merge, merge #1', () => { john.setData( '
' + 'Foo' + 'Bar' + '
' + '[]' + '
' + 'Xyz' + '
' ); john.merge(); john.setSelection( [ 0, 2 ] ); john.merge(); expectClients( '
' + 'Foo' + 'BarXyz' + '
' ); john.undo(); john.undo(); expectClients( '
' + 'Foo' + 'Bar' + '
' + '
' + 'Xyz' + '
' ); } ); it( 'merge, merge #2', () => { john.setData( '
' + 'Foo' + '
' + '[]' + '
' + 'Bar' + 'Xyz' + '
' ); john.merge(); john.setSelection( [ 0, 1 ] ); john.merge(); expectClients( '
' + 'FooBar' + 'Xyz' + '
' ); john.undo(); john.undo(); expectClients( '
' + 'Foo' + '
' + '
' + 'Bar' + 'Xyz' + '
' ); } ); it( 'merge, unwrap', () => { john.setData( '[]Foo' ); john.merge(); john.setSelection( [ 0, 0 ] ); john.unwrap(); john.undo(); john.undo(); expectClients( 'Foo' ); } ); it( 'remove node at the split position #1', () => { john.setData( 'Ab[]Xy' ); john.merge(); john.setSelection( [ 0, 1 ], [ 0, 2 ] ); john.remove(); john.undo(); john.undo(); expectClients( 'AbXy' ); } ); it( 'remove node at the split position #2', () => { john.setData( 'Ab[]Xy' ); john.merge(); john.setSelection( [ 0, 2 ], [ 0, 3 ] ); john.remove(); john.undo(); john.undo(); expectClients( 'AbXy' ); } ); it( 'undoing split after the element created by split has been removed', () => { // This example is ported here from ckeditor5-undo to keep 100% CC in ckeditor5-engine alone. john.setData( 'Foo[]bar' ); john.split(); john.setSelection( [ 0, 3 ], [ 1, 3 ] ); john.delete(); expectClients( 'Foo' ); john.undo(); expectClients( 'Foobar' ); john.undo(); expectClients( 'Foobar' ); } ); it( 'remove text from paragraph and merge it', () => { john.setData( 'Foo[Bar]' ); john.remove(); john.setSelection( [ 1 ] ); john.merge(); expectClients( 'Foo' ); john.undo(); expectClients( 'Foo' ); john.undo(); expectClients( 'FooBar' ); } ); it( 'delete split paragraphs', () => { john.setData( 'FooB[]ar' ); john.split(); john.setSelection( [ 2, 1 ] ); john.split(); john.setSelection( [ 1, 0 ], [ 3, 1 ] ); john.delete(); john.setSelection( [ 1 ] ); john.merge(); expectClients( 'Foo' ); john.undo(); expectClients( 'Foo' ); john.undo(); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); john.redo(); expectClients( 'FooBar' ); john.redo(); expectClients( 'FooBar' ); john.redo(); expectClients( 'Foo' ); john.redo(); expectClients( 'Foo' ); } ); it( 'pasting on collapsed selection undo and redo', () => { john.setData( 'Foo[]Bar' ); // Below simulates pasting. john.editor.model.change( () => { john.split(); john.setSelection( [ 1 ] ); john.insert( '1' ); john.setSelection( [ 1 ] ); john.merge(); john.setSelection( [ 1 ] ); john.insert( '2' ); john.setSelection( [ 2 ] ); john.merge(); } ); expectClients( 'Foo12Bar' ); john.undo(); expectClients( 'FooBar' ); john.redo(); expectClients( 'Foo12Bar' ); john.undo(); expectClients( 'FooBar' ); john.redo(); expectClients( 'Foo12Bar' ); } ); it( 'selection attribute setting: split, bold, merge, undo, undo, undo', () => { // This test is ported from undo to keep 100% CC in engine. john.setData( 'Foo[]Bar' ); john.split(); john.setSelection( [ 1, 0 ] ); john._processExecute( 'bold' ); john._processExecute( 'forwardDelete' ); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); } ); // https://github.com/ckeditor/ckeditor5/issues/1288 it( 'remove two groups of blocks then undo, undo', () => { john.setData( 'XAB[CD]' ); john.delete(); john.setSelection( [ 0, 1 ], [ 2, 1 ] ); john.delete(); expectClients( 'X' ); john.undo(); expectClients( 'XAB' ); john.undo(); expectClients( 'XABCD' ); } ); // https://github.com/ckeditor/ckeditor5/issues/1287 TC1 it( 'pasting on non-collapsed selection undo and redo', () => { john.setData( 'Fo[oB]ar' ); // Below simulates pasting. john.editor.model.change( () => { john.editor.model.deleteContent( john.document.selection ); john.setSelection( [ 0, 2 ] ); john.split(); john.setSelection( [ 1 ] ); john.insert( '1' ); john.setSelection( [ 1 ] ); john.merge(); john.setSelection( [ 1 ] ); john.insert( '2' ); john.setSelection( [ 2 ] ); john.merge(); } ); expectClients( 'Fo12ar' ); john.undo(); expectClients( 'FooBar' ); john.redo(); expectClients( 'Fo12ar' ); john.undo(); expectClients( 'FooBar' ); } ); it( 'collapsed marker at the beginning of merged element then undo', () => { john.setData( 'Foo[]Bar' ); john.setMarker( 'm1' ); john.setSelection( [ 1 ] ); john.merge(); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); } ); it( 'collapsed marker at the end of merge-target element then undo', () => { john.setData( 'Foo[]Bar' ); john.setMarker( 'm1' ); john.setSelection( [ 1 ] ); john.merge(); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); } ); it( 'empty marker between merged elements then undo', () => { john.setData( 'Foo[]Bar' ); john.setMarker( 'm1' ); john.setSelection( [ 1 ] ); john.merge(); expectClients( 'FooBar' ); john.undo(); expectClients( 'FooBar' ); } ); it( 'left side of marker moved then undo', () => { john.setData( 'Foo[bar]' ); john.setMarker( 'm1' ); john.setSelection( [ 0, 2 ], [ 0, 4 ] ); john.move( [ 1, 0 ] ); expectClients( 'Foarob' ); john.undo(); expectClients( 'Foobar' ); } ); it( 'right side of marker moved then undo', () => { john.setData( '[Foo]bar' ); john.setMarker( 'm1' ); john.setSelection( [ 0, 2 ], [ 0, 4 ] ); john.move( [ 1, 0 ] ); expectClients( 'Foarob' ); john.undo(); expectClients( 'Foobar' ); } ); it( 'marker on closing and opening tag - remove multiple elements #1', () => { john.setData( 'Abc' + 'Foo[' + ']Bar' ); john.setMarker( 'm1' ); john.setSelection( [ 0, 1 ], [ 2, 2 ] ); john._processExecute( 'delete' ); expectClients( 'Ar' ); john.undo(); expectClients( 'Abc' + 'Foo' + 'Bar' ); } ); it( 'marker on closing and opening tag - remove multiple elements #2', () => { john.setData( 'Foo[' + ']Bar' + 'Xyz' ); john.setMarker( 'm1' ); john.setSelection( [ 0, 1 ], [ 2, 2 ] ); john._processExecute( 'delete' ); expectClients( 'Fz' ); john.undo(); expectClients( 'Foo' + 'Bar' + 'Xyz' ); } ); it( 'marker on closing and opening tag + some text - merge elements + remove text', () => { john.setData( 'Foo[' + 'B]ar' ); john.setMarker( 'm1' ); john.setSelection( [ 0, 1 ], [ 1, 2 ] ); john._processExecute( 'delete' ); expectClients( 'Fr' ); john.undo(); expectClients( 'Foo' + 'Bar' ); } ); // https://github.com/ckeditor/ckeditor5-engine/issues/1668 it( 'marker and moves with undo-redo-undo', () => { john.setData( 'X[]Y' ); const inputBufferBatch = john.editor.commands.get( 'input' ).buffer.batch; john.editor.model.enqueueChange( inputBufferBatch, () => { john.type( 'a' ); john.type( 'b' ); john.type( 'c' ); john.setSelection( [ 0, 1 ], [ 0, 4 ] ); john.setMarker( 'm1' ); } ); expectClients( 'XabcY' ); john.setSelection( [ 0, 0 ], [ 0, 5 ] ); john._processExecute( 'delete' ); expectClients( '' ); john.undo(); expectClients( 'XabcY' ); john.undo(); expectClients( 'XY' ); john.redo(); expectClients( 'XabcY' ); john.redo(); expectClients( '' ); john.undo(); expectClients( 'XabcY' ); john.undo(); expectClients( 'XY' ); } ); } );