|
@@ -12,7 +12,7 @@ import UndoEngine from '/ckeditor5/undo/undoengine.js';
|
|
|
|
|
|
|
|
import { setData, getData } from '/tests/engine/_utils/model.js';
|
|
import { setData, getData } from '/tests/engine/_utils/model.js';
|
|
|
|
|
|
|
|
-// import deleteContents from '/ckeditor5/engine/model/composer/deletecontents.js';
|
|
|
|
|
|
|
+import deleteContents from '/ckeditor5/engine/model/composer/deletecontents.js';
|
|
|
|
|
|
|
|
let editor, doc, root;
|
|
let editor, doc, root;
|
|
|
|
|
|
|
@@ -115,12 +115,12 @@ describe( 'UndoEngine integration', () => {
|
|
|
output( '<p>o</p><p>b<selection /></p>' );
|
|
output( '<p>o</p><p>b<selection /></p>' );
|
|
|
|
|
|
|
|
editor.execute( 'undo' );
|
|
editor.execute( 'undo' );
|
|
|
- // Here is an edge case that selection could be before or after `ar` but selection always ends up after.
|
|
|
|
|
- output( '<p>o</p><p>bar<selection /></p>' );
|
|
|
|
|
|
|
+ // Here is an edge case that selection could be before or after `ar`.
|
|
|
|
|
+ output( '<p>o</p><p>b<selection />ar</p>' );
|
|
|
|
|
|
|
|
editor.execute( 'undo' );
|
|
editor.execute( 'undo' );
|
|
|
// As above.
|
|
// As above.
|
|
|
- output( '<p>fo<selection />o</p><p>bar</p>' );
|
|
|
|
|
|
|
+ output( '<p><selection />foo</p><p>bar</p>' );
|
|
|
|
|
|
|
|
undoDisabled();
|
|
undoDisabled();
|
|
|
} );
|
|
} );
|
|
@@ -144,45 +144,43 @@ describe( 'UndoEngine integration', () => {
|
|
|
undoDisabled();
|
|
undoDisabled();
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
- //it( 'add and remove same part and undo', () => {
|
|
|
|
|
- // // This test case fails because some operations are transformed to NoOperations incorrectly.
|
|
|
|
|
- // input( '<p>fo<selection />o</p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // doc.batch().insert( doc.selection.getFirstPosition(), 'zzz' );
|
|
|
|
|
- // output( '<p>fozzz<selection />o</p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // doc.batch().remove( Range.createFromPositionAndShift( new Position( root, [ 0, 2 ] ) , 3 ) );
|
|
|
|
|
- // output( '<p>fo<selection />o</p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // output( '<p>fozzz<selection />o</p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // output( '<p>fo<selection />o</p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // undoDisabled();
|
|
|
|
|
- //} );
|
|
|
|
|
|
|
+ it( 'add and remove same part and undo', () => {
|
|
|
|
|
+ input( '<p>fo<selection />o</p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ doc.batch().insert( doc.selection.getFirstPosition(), 'zzz' );
|
|
|
|
|
+ output( '<p>fozzz<selection />o</p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ doc.batch().remove( Range.createFromPositionAndShift( new Position( root, [ 0, 2 ] ) , 3 ) );
|
|
|
|
|
+ output( '<p>fo<selection />o</p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( '<p>fozzz<selection />o</p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( '<p>fo<selection />o</p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ undoDisabled();
|
|
|
|
|
+ } );
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
describe( 'moving', () => {
|
|
describe( 'moving', () => {
|
|
|
- //it( 'move same content twice then undo', () => {
|
|
|
|
|
- // // This test case fails because some operations are transformed to NoOperations incorrectly.
|
|
|
|
|
- // input( '<p>f<selection>o</selection>z</p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 1, 0 ] ) );
|
|
|
|
|
- // output( '<p>fz</p><p><selection>o</selection>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 0, 2 ] ) );
|
|
|
|
|
- // output( '<p>fz<selection>o</selection></p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // output( '<p>fz</p><p><selection>o</selection>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // output( '<p>f<selection>o</selection>z</p><p>bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // undoDisabled();
|
|
|
|
|
- //} );
|
|
|
|
|
|
|
+ it( 'move same content twice then undo', () => {
|
|
|
|
|
+ input( '<p>f<selection>o</selection>z</p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 1, 0 ] ) );
|
|
|
|
|
+ output( '<p>fz</p><p><selection>o</selection>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 0, 2 ] ) );
|
|
|
|
|
+ output( '<p>fz<selection>o</selection></p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( '<p>fz</p><p><selection>o</selection>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( '<p>f<selection>o</selection>z</p><p>bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ undoDisabled();
|
|
|
|
|
+ } );
|
|
|
|
|
|
|
|
it( 'move content and new parent then undo', () => {
|
|
it( 'move content and new parent then undo', () => {
|
|
|
input( '<p>f<selection>o</selection>z</p><p>bar</p>' );
|
|
input( '<p>f<selection>o</selection>z</p><p>bar</p>' );
|
|
@@ -230,7 +228,7 @@ describe( 'UndoEngine integration', () => {
|
|
|
input( 'fo<selection>zb</selection>ar' );
|
|
input( 'fo<selection>zb</selection>ar' );
|
|
|
|
|
|
|
|
doc.batch().wrap( doc.selection.getFirstRange(), 'p' );
|
|
doc.batch().wrap( doc.selection.getFirstRange(), 'p' );
|
|
|
- output( 'fo<p><selection>zb</selection></p>ar' );
|
|
|
|
|
|
|
+ output( 'fo<selection><p>zb</p></selection>ar' );
|
|
|
|
|
|
|
|
editor.execute( 'undo' );
|
|
editor.execute( 'undo' );
|
|
|
output( 'fo<selection>zb</selection>ar' );
|
|
output( 'fo<selection>zb</selection>ar' );
|
|
@@ -238,26 +236,25 @@ describe( 'UndoEngine integration', () => {
|
|
|
undoDisabled();
|
|
undoDisabled();
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
- //it( 'wrap, move and undo', () => {
|
|
|
|
|
- // input( 'fo<selection>zb</selection>ar' );
|
|
|
|
|
- //
|
|
|
|
|
- // doc.batch().wrap( doc.selection.getFirstRange(), 'p' );
|
|
|
|
|
- // output( 'fo<p><selection>zb</selection></p>ar' );
|
|
|
|
|
- //
|
|
|
|
|
- // setSelection( [ 2, 0 ], [ 2, 1 ] );
|
|
|
|
|
- // doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 0 ] ) );
|
|
|
|
|
- // output( '<selection>z</selection>fo<p>b</p>ar' );
|
|
|
|
|
- //
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // output( 'fo<p><selection>z</selection>b</p>ar' );
|
|
|
|
|
- //
|
|
|
|
|
- // // This test case fails here for unknown reason, but "z" letter magically disappears.
|
|
|
|
|
- // // AssertionError: expected 'fo<selection>b</selection>ar' to equal 'fo<selection>zb</selection>ar'
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // output( 'fo<selection>zb</selection>ar' );
|
|
|
|
|
- //
|
|
|
|
|
- // undoDisabled();
|
|
|
|
|
- //} );
|
|
|
|
|
|
|
+ it( 'wrap, move and undo', () => {
|
|
|
|
|
+ input( 'fo<selection>zb</selection>ar' );
|
|
|
|
|
+
|
|
|
|
|
+ doc.batch().wrap( doc.selection.getFirstRange(), 'p' );
|
|
|
|
|
+ // Would be better if selection was inside P.
|
|
|
|
|
+ output( 'fo<selection><p>zb</p></selection>ar' );
|
|
|
|
|
+
|
|
|
|
|
+ setSelection( [ 2, 0 ], [ 2, 1 ] );
|
|
|
|
|
+ doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 0 ] ) );
|
|
|
|
|
+ output( '<selection>z</selection>fo<p>b</p>ar' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( 'fo<p><selection>z</selection>b</p>ar' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( 'fo<selection>zb</selection>ar' );
|
|
|
|
|
+
|
|
|
|
|
+ undoDisabled();
|
|
|
|
|
+ } );
|
|
|
|
|
|
|
|
it( 'unwrap and undo', () => {
|
|
it( 'unwrap and undo', () => {
|
|
|
input( '<p>foo<selection />bar</p>' );
|
|
input( '<p>foo<selection />bar</p>' );
|
|
@@ -271,54 +268,44 @@ describe( 'UndoEngine integration', () => {
|
|
|
undoDisabled();
|
|
undoDisabled();
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
- //it( 'merge and undo', () => {
|
|
|
|
|
- // input( '<p>foo</p><p><selection />bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // doc.batch().merge( new Position( root, [ 1 ] ) );
|
|
|
|
|
- // // This test fails here because selection is stuck with <p> element and ends up in graveyard.
|
|
|
|
|
- // // AssertionError: expected '<p>foobar</p>' to equal '<p>foo<selection />bar</p>'
|
|
|
|
|
- // output( '<p>foo<selection />bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // // This test fails because when selection is transformed it is first in empty <p> but when
|
|
|
|
|
- // // "bar" is inserted, it gets moved to the right.
|
|
|
|
|
- // // AssertionError: expected '<p>foo</p><p>bar<selection /></p>' to equal '<p>foo</p><p><selection />bar</p>'
|
|
|
|
|
- // output( '<p>foo</p><p><selection />bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // undoDisabled();
|
|
|
|
|
- //} );
|
|
|
|
|
-
|
|
|
|
|
- //it( 'split and undo', () => {
|
|
|
|
|
- // input( '<p>foo<selection />bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // doc.batch().split( doc.selection.getFirstPosition() );
|
|
|
|
|
- // // This test fails because selection ends up in wrong node after splitting.
|
|
|
|
|
- // // AssertionError: expected '<p>foo<selection /></p><p>bar</p>' to equal '<p>foo</p><p><selection />bar</p>'
|
|
|
|
|
- // output( '<p>foo</p><p><selection />bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // // This test fails because selection after transforming ends up after inserted test.
|
|
|
|
|
- // // AssertionError: expected '<p>foobar<selection /></p>' to equal '<p>foo<selection />bar</p>'
|
|
|
|
|
- // output( '<p>foo<selection />bar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // undoDisabled();
|
|
|
|
|
- //} );
|
|
|
|
|
|
|
+ it( 'merge and undo', () => {
|
|
|
|
|
+ input( '<p>foo</p><p><selection />bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ doc.batch().merge( new Position( root, [ 1 ] ) );
|
|
|
|
|
+ // Because selection is stuck with <p> it ends up in graveyard. We have to manually move it to correct node.
|
|
|
|
|
+ setSelection( [ 0, 3 ], [ 0, 3 ] );
|
|
|
|
|
+ output( '<p>foo<selection />bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( '<p>foo</p><p><selection />bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ undoDisabled();
|
|
|
|
|
+ } );
|
|
|
|
|
+
|
|
|
|
|
+ it( 'split and undo', () => {
|
|
|
|
|
+ input( '<p>foo<selection />bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ doc.batch().split( doc.selection.getFirstPosition() );
|
|
|
|
|
+ // Because selection is stuck with <p> it ends up in wrong node. We have to manually move it to correct node.
|
|
|
|
|
+ setSelection( [ 1, 0 ], [ 1, 0 ] );
|
|
|
|
|
+ output( '<p>foo</p><p><selection />bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( '<p>foo<selection />bar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ undoDisabled();
|
|
|
|
|
+ } );
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
describe( 'other edge cases', () => {
|
|
describe( 'other edge cases', () => {
|
|
|
- //it( 'deleteContents between two nodes', () => {
|
|
|
|
|
- // input( '<p>fo<selection>o</p><p>b</selection>ar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // deleteContents( doc.batch(), doc.selection, { merge: true } );
|
|
|
|
|
- // output( '<p>fo<selection />ar</p>' );
|
|
|
|
|
- //
|
|
|
|
|
- // // This test case fails because of OT problems.
|
|
|
|
|
- // // When the batch is undone, first MergeDelta is reversed to SplitDelta and it is undone.
|
|
|
|
|
- // // Then RemoveOperations are reversed to ReinsertOperation.
|
|
|
|
|
- // // Unfortunately, ReinsertOperation that inserts "o" points to the same position were split happened.
|
|
|
|
|
- // // Then, when ReinsertOperation is transformed by operations of SplitDelta, it ends up in wrong <p>.
|
|
|
|
|
- // editor.execute( 'undo' );
|
|
|
|
|
- // output( '<p>fo<selection>o</p><p>b</selection>ar</p>' );
|
|
|
|
|
- //} );
|
|
|
|
|
|
|
+ it( 'deleteContents between two nodes', () => {
|
|
|
|
|
+ input( '<p>fo<selection>o</p><p>b</selection>ar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ deleteContents( doc.batch(), doc.selection, { merge: true } );
|
|
|
|
|
+ output( '<p>fo<selection />ar</p>' );
|
|
|
|
|
+
|
|
|
|
|
+ editor.execute( 'undo' );
|
|
|
|
|
+ output( '<p>fo<selection>o</p><p>b</selection>ar</p>' );
|
|
|
|
|
+ } );
|
|
|
} );
|
|
} );
|
|
|
} );
|
|
} );
|