浏览代码

Aligned test with engine changes.

Oskar Wróbel 8 年之前
父节点
当前提交
2a9fab0886

+ 4 - 5
packages/ckeditor5-undo/tests/basecommand.js

@@ -4,16 +4,15 @@
  */
 
 import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
+import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
 import BaseCommand from '../src/basecommand';
 
 describe( 'BaseCommand', () => {
-	let editor, doc, base;
+	let editor, base;
 
 	beforeEach( () => {
 		editor = new ModelTestEditor();
 		base = new BaseCommand( editor );
-
-		doc = editor.document;
 	} );
 
 	afterEach( () => {
@@ -32,7 +31,7 @@ describe( 'BaseCommand', () => {
 		} );
 
 		it( 'should be true if there are batches in command stack', () => {
-			base.addBatch( doc.batch() );
+			base.addBatch( new Batch() );
 
 			expect( base.isEnabled ).to.be.true;
 		} );
@@ -40,7 +39,7 @@ describe( 'BaseCommand', () => {
 
 	describe( 'clearStack', () => {
 		it( 'should remove all batches from the stack', () => {
-			base.addBatch( doc.batch() );
+			base.addBatch( new Batch() );
 			base.clearStack();
 
 			expect( base.isEnabled ).to.be.false;

+ 41 - 30
packages/ckeditor5-undo/tests/redocommand.js

@@ -6,20 +6,21 @@
 import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
 import Range from '@ckeditor/ckeditor5-engine/src/model/range';
 import Position from '@ckeditor/ckeditor5-engine/src/model/position';
+import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
 import UndoCommand from '../src/undocommand';
 import RedoCommand from '../src/redocommand';
 import { itemAt, getText } from '@ckeditor/ckeditor5-engine/tests/model/_utils/utils';
 
 describe( 'RedoCommand', () => {
-	let editor, doc, root, redo, undo;
+	let editor, model, root, redo, undo;
 
 	beforeEach( () => {
 		editor = new ModelTestEditor();
 		redo = new RedoCommand( editor );
 
-		doc = editor.document;
+		model = editor.model;
 
-		root = doc.getRoot();
+		root = model.document.getRoot();
 	} );
 
 	afterEach( () => {
@@ -49,10 +50,12 @@ describe( 'RedoCommand', () => {
 				 [root]
 				 - {}
 				 */
-				editor.document.selection.setRanges( [ r( 0, 0 ) ] );
-				batch0 = doc.batch();
+				editor.model.document.selection.setRanges( [ r( 0, 0 ) ] );
+				batch0 = new Batch();
 				undo.addBatch( batch0 );
-				batch0.insertText( 'foobar', p( 0 ) );
+				model.enqueueChange( batch0, writer => {
+					writer.insertText( 'foobar', p( 0 ) );
+				} );
 
 				/*
 				 [root]
@@ -64,10 +67,12 @@ describe( 'RedoCommand', () => {
 				 - r{}
 				 */
 				// Let's make things spicy and this time, make a backward selection.
-				editor.document.selection.setRanges( [ r( 2, 4 ) ], true );
-				batch1 = doc.batch();
+				editor.model.document.selection.setRanges( [ r( 2, 4 ) ], true );
+				batch1 = new Batch();
 				undo.addBatch( batch1 );
-				batch1.setAttribute( 'key', 'value', r( 2, 4 ) );
+				model.enqueueChange( batch1, writer => {
+					writer.setAttribute( 'key', 'value', r( 2, 4 ) );
+				} );
 
 				/*
 				 [root]
@@ -78,10 +83,12 @@ describe( 'RedoCommand', () => {
 				 - a
 				 - r
 				 */
-				editor.document.selection.setRanges( [ r( 1, 3 ) ] );
-				batch2 = doc.batch();
+				editor.model.document.selection.setRanges( [ r( 1, 3 ) ] );
+				batch2 = new Batch();
 				undo.addBatch( batch2 );
-				batch2.move( r( 1, 3 ), p( 6 ) );
+				model.enqueueChange( batch2, writer => {
+					writer.move( r( 1, 3 ), p( 6 ) );
+				} );
 
 				/*
 				 [root]
@@ -112,8 +119,8 @@ describe( 'RedoCommand', () => {
 				expect( itemAt( root, 1 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 5 ).getAttribute( 'key' ) ).to.equal( 'value' );
 
-				expect( editor.document.selection.getRanges().next().value.isEqual( r( 4, 6 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getRanges().next().value.isEqual( r( 4, 6 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 			} );
 
 			it( 'should redo series of batches undone by undo command', () => {
@@ -135,8 +142,8 @@ describe( 'RedoCommand', () => {
 				expect( getText( root ) ).to.equal( 'foobar' );
 				expect( Array.from( root.getChildren() ).find( node => node.hasAttribute( 'key' ) ) ).to.be.undefined;
 
-				expect( editor.document.selection.getRanges().next().value.isEqual( r( 6, 6 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getRanges().next().value.isEqual( r( 6, 6 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 
 				redo.execute();
 				// Should be like after applying `batch1`:
@@ -153,8 +160,8 @@ describe( 'RedoCommand', () => {
 				expect( itemAt( root, 2 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 3 ).getAttribute( 'key' ) ).to.equal( 'value' );
 
-				expect( editor.document.selection.getRanges().next().value.isEqual( r( 2, 4 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.true;
+				expect( editor.model.document.selection.getRanges().next().value.isEqual( r( 2, 4 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.true;
 
 				redo.execute();
 				// Should be like after applying `batch2`:
@@ -171,8 +178,8 @@ describe( 'RedoCommand', () => {
 				expect( itemAt( root, 1 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 5 ).getAttribute( 'key' ) ).to.equal( 'value' );
 
-				expect( editor.document.selection.getRanges().next().value.isEqual( r( 4, 6 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getRanges().next().value.isEqual( r( 4, 6 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 			} );
 
 			it( 'should redo batch selectively undone by undo command', () => {
@@ -193,8 +200,8 @@ describe( 'RedoCommand', () => {
 				expect( itemAt( root, 1 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 5 ).getAttribute( 'key' ) ).to.equal( 'value' );
 
-				expect( editor.document.selection.getRanges().next().value.isEqual( r( 6, 6 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getRanges().next().value.isEqual( r( 6, 6 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 			} );
 
 			it( 'should redo batch selectively undone by undo command #2', () => {
@@ -217,8 +224,8 @@ describe( 'RedoCommand', () => {
 				expect( itemAt( root, 1 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 5 ).getAttribute( 'key' ) ).to.equal( 'value' );
 
-				expect( editor.document.selection.getRanges().next().value.isEqual( r( 1, 2 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.true;
+				expect( editor.model.document.selection.getRanges().next().value.isEqual( r( 1, 2 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.true;
 			} );
 
 			it( 'should transform redo batch by changes written in history that happened after undo but before redo #2', () => {
@@ -227,13 +234,17 @@ describe( 'RedoCommand', () => {
 				undo.execute();
 
 				// Remove "ar".
-				doc.batch().remove( r( 4, 6 ) );
+				model.change( writer => {
+					writer.remove( r( 4, 6 ) );
+				} );
 
 				// Undo setting attribute on "ob". Now it is "foob".
 				undo.execute();
 
 				// Append "xx" at the beginning. Now it is "xxfoob".
-				doc.batch().insertText( 'xx', p( 0 ) );
+				model.change( writer => {
+					writer.insertText( 'xx', p( 0 ) );
+				} );
 
 				// Redo setting attribute on "ob". Now it is "xxfoOB".
 				redo.execute();
@@ -241,8 +252,8 @@ describe( 'RedoCommand', () => {
 				expect( getText( root ) ).to.equal( 'xxfoob' );
 				expect( itemAt( root, 4 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 5 ).getAttribute( 'key' ) ).to.equal( 'value' );
-				expect( editor.document.selection.getFirstRange().isEqual( r( 4, 6 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.true;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 4, 6 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.true;
 
 				// Redo moving "oo". Now it is "xxfBoO". Selection is expected to be on just moved "oO".
 				redo.execute();
@@ -250,8 +261,8 @@ describe( 'RedoCommand', () => {
 				expect( getText( root ) ).to.equal( 'xxfboo' );
 				expect( itemAt( root, 3 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 5 ).getAttribute( 'key' ) ).to.equal( 'value' );
-				expect( editor.document.selection.getFirstRange().isEqual( r( 4, 6 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 4, 6 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 			} );
 		} );
 	} );

+ 64 - 45
packages/ckeditor5-undo/tests/undocommand.js

@@ -6,18 +6,20 @@
 import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
 import Range from '@ckeditor/ckeditor5-engine/src/model/range';
 import Position from '@ckeditor/ckeditor5-engine/src/model/position';
+import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
 import Text from '@ckeditor/ckeditor5-engine/src/model/text';
 import UndoCommand from '../src/undocommand';
 import { itemAt, getText } from '@ckeditor/ckeditor5-engine/tests/model/_utils/utils';
 
 describe( 'UndoCommand', () => {
-	let editor, doc, root, undo;
+	let editor, model, doc, root, undo;
 
 	beforeEach( () => {
 		editor = new ModelTestEditor();
 		undo = new UndoCommand( editor );
 
-		doc = editor.document;
+		model = editor.model;
+		doc = model.document;
 
 		root = doc.getRoot();
 	} );
@@ -38,10 +40,12 @@ describe( 'UndoCommand', () => {
 				 [root]
 				 - {}
 				 */
-				editor.document.selection.setRanges( [ r( 0, 0 ) ] );
-				batch0 = doc.batch();
+				editor.model.document.selection.setRanges( [ r( 0, 0 ) ] );
+				batch0 = new Batch();
 				undo.addBatch( batch0 );
-				batch0.insertText( 'foobar', p( 0 ) );
+				model.enqueueChange( batch0, writer => {
+					writer.insertText( 'foobar', p( 0 ) );
+				} );
 
 				/*
 				 [root]
@@ -53,10 +57,12 @@ describe( 'UndoCommand', () => {
 				 - r{}
 				 */
 				// Let's make things spicy and this time, make a backward selection.
-				editor.document.selection.setRanges( [ r( 2, 4 ) ], true );
-				batch1 = doc.batch();
+				editor.model.document.selection.setRanges( [ r( 2, 4 ) ], true );
+				batch1 = new Batch();
 				undo.addBatch( batch1 );
-				batch1.setAttribute( 'key', 'value', r( 2, 4 ) );
+				model.enqueueChange( batch1, writer => {
+					writer.setAttribute( 'key', 'value', r( 2, 4 ) );
+				} );
 
 				/*
 				 [root]
@@ -67,10 +73,12 @@ describe( 'UndoCommand', () => {
 				 - a
 				 - r
 				 */
-				editor.document.selection.setRanges( [ r( 1, 3 ) ] );
-				batch2 = doc.batch();
+				editor.model.document.selection.setRanges( [ r( 1, 3 ) ] );
+				batch2 = new Batch();
 				undo.addBatch( batch2 );
-				batch2.move( r( 1, 3 ), p( 6 ) );
+				model.enqueueChange( batch2, writer => {
+					writer.move( r( 1, 3 ), p( 6 ) );
+				} );
 
 				/*
 				 [root]
@@ -81,10 +89,12 @@ describe( 'UndoCommand', () => {
 				 - {o
 				 - o} (key: value)
 				 */
-				editor.document.selection.setRanges( [ r( 1, 4 ) ] );
-				batch3 = doc.batch();
+				editor.model.document.selection.setRanges( [ r( 1, 4 ) ] );
+				batch3 = new Batch();
 				undo.addBatch( batch3 );
-				batch3.wrap( r( 1, 4 ), 'p' );
+				model.enqueueChange( batch3, writer => {
+					writer.wrap( r( 1, 4 ), 'p' );
+				} );
 
 				/*
 				 [root]
@@ -96,8 +106,10 @@ describe( 'UndoCommand', () => {
 				 - o
 				 - o (key: value)
 				 */
-				editor.document.selection.setRanges( [ r( 0, 1 ) ] );
-				batch2.move( r( 0, 1 ), p( 3 ) );
+				editor.model.document.selection.setRanges( [ r( 0, 1 ) ] );
+				model.enqueueChange( batch2, writer => {
+					writer.move( r( 0, 1 ), p( 3 ) );
+				} );
 
 				/*
 				 [root]
@@ -109,7 +121,7 @@ describe( 'UndoCommand', () => {
 				 - f
 				 - o{} (key: value)
 				 */
-				editor.document.selection.setRanges( [ r( 4, 4 ) ] );
+				editor.model.document.selection.setRanges( [ r( 4, 4 ) ] );
 			} );
 
 			it( 'should revert changes done by deltas from the batch that was most recently added to the command stack', () => {
@@ -130,8 +142,8 @@ describe( 'UndoCommand', () => {
 				expect( itemAt( root, 0 ).getAttribute( 'key' ) ).to.equal( 'value' );
 				expect( itemAt( root, 5 ).getAttribute( 'key' ) ).to.equal( 'value' );
 
-				expect( editor.document.selection.getFirstRange().isEqual( r( 0, 3 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 0, 3 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 
 				undo.execute();
 
@@ -152,8 +164,8 @@ describe( 'UndoCommand', () => {
 
 				// Since selection restoring is not 100% accurate, selected range is not perfectly correct
 				// with what is expected in comment above. The correct result would be if range was [ 1 ] - [ 3 ].
-				expect( editor.document.selection.getFirstRange().isEqual( r( 0, 3 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 0, 3 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 
 				undo.execute();
 
@@ -172,8 +184,8 @@ describe( 'UndoCommand', () => {
 				expect( itemAt( root, 2 ).hasAttribute( 'key' ) ).to.be.false;
 				expect( itemAt( root, 3 ).hasAttribute( 'key' ) ).to.be.false;
 
-				expect( editor.document.selection.getFirstRange().isEqual( r( 2, 4 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.true;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 2, 4 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.true;
 
 				undo.execute();
 
@@ -183,7 +195,7 @@ describe( 'UndoCommand', () => {
 				 */
 
 				expect( root.childCount ).to.equal( 0 );
-				expect( editor.document.selection.getFirstRange().isEqual( r( 0, 0 ) ) ).to.be.true;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 0, 0 ) ) ).to.be.true;
 			} );
 
 			it( 'should revert changes done by deltas from given batch, if parameter was passed (test: revert set attribute)', () => {
@@ -210,8 +222,8 @@ describe( 'UndoCommand', () => {
 
 				// Selection is only partially restored because the range got broken.
 				// The selection would have to best on letter "b" and letter "o", but it is set only on letter "b".
-				expect( editor.document.selection.getFirstRange().isEqual( r( [ 0, 0 ], [ 0, 1 ] ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.true;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( [ 0, 0 ], [ 0, 1 ] ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.true;
 			} );
 
 			it( 'should revert changes done by deltas from given batch, if parameter was passed (test: revert insert foobar)', () => {
@@ -228,8 +240,8 @@ describe( 'UndoCommand', () => {
 				expect( root.childCount ).to.equal( 1 );
 				expect( itemAt( root, 0 ).name ).to.equal( 'p' );
 
-				expect( editor.document.selection.getFirstRange().isEqual( r( 1, 1 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 1, 1 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 
 				undo.execute( batch1 );
 				// Remove attributes.
@@ -240,8 +252,8 @@ describe( 'UndoCommand', () => {
 				expect( itemAt( root, 0 ).name ).to.equal( 'p' );
 
 				// Operations for undoing that batch were working on graveyard so document selection should not change.
-				expect( editor.document.selection.getFirstRange().isEqual( r( 1, 1 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 1, 1 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 
 				expect( doc.graveyard.maxOffset ).to.equal( 6 );
 
@@ -253,20 +265,23 @@ describe( 'UndoCommand', () => {
 				undo.execute( batch3 );
 				expect( root.maxOffset ).to.equal( 0 );
 
-				expect( editor.document.selection.getFirstRange().isEqual( r( 0, 0 ) ) ).to.be.true;
-				expect( editor.document.selection.isBackward ).to.be.false;
+				expect( editor.model.document.selection.getFirstRange().isEqual( r( 0, 0 ) ) ).to.be.true;
+				expect( editor.model.document.selection.isBackward ).to.be.false;
 			} );
 
 			it( 'should omit deltas with non-document operations', () => {
-				const batch = doc.batch();
-				const element = batch.createElement( 'p' );
+				let element;
 
-				undo.addBatch( batch );
+				model.change( writer => {
+					element = writer.createElement( 'p' );
 
-				batch.setAttribute( 'foo', 'bar', element );
-				batch.setAttribute( 'foo', 'bar', root );
+					undo.addBatch( writer.batch );
 
-				undo.execute();
+					writer.setAttribute( 'foo', 'bar', element );
+					writer.setAttribute( 'foo', 'bar', root );
+
+					undo.execute();
+				} );
 
 				expect( element.getAttribute( 'foo' ) ).to.equal( 'bar' );
 				expect( root.getAttribute( 'foo' ) ).to.not.equal( 'bar' );
@@ -288,16 +303,20 @@ describe( 'UndoCommand', () => {
 			root.appendChildren( new Text( 'abcdef' ) );
 			expect( getCaseText( root ) ).to.equal( 'abcdef' );
 
-			editor.document.selection.setRanges( [ r( 1, 4 ) ] );
-			const batch0 = doc.batch();
+			editor.model.document.selection.setRanges( [ r( 1, 4 ) ] );
+			const batch0 = new Batch();
 			undo.addBatch( batch0 );
-			batch0.setAttribute( 'uppercase', true, r( 1, 4 ) );
+			model.enqueueChange( batch0, writer => {
+				writer.setAttribute( 'uppercase', true, r( 1, 4 ) );
+			} );
 			expect( getCaseText( root ) ).to.equal( 'aBCDef' );
 
-			editor.document.selection.setRanges( [ r( 3, 4 ) ] );
-			const batch1 = doc.batch();
+			editor.model.document.selection.setRanges( [ r( 3, 4 ) ] );
+			const batch1 = new Batch();
 			undo.addBatch( batch1 );
-			batch1.move( r( 3, 4 ), p( 1 ) );
+			model.enqueueChange( batch1, writer => {
+				writer.move( r( 3, 4 ), p( 1 ) );
+			} );
 			expect( getCaseText( root ) ).to.equal( 'aDBCef' );
 
 			undo.execute( batch0 );
@@ -305,7 +324,7 @@ describe( 'UndoCommand', () => {
 			// After undo-attr: acdbef <--- "cdb" should be selected, it would look weird if only "cd" or "b" is selected
 			// but the whole unbroken part "cdb" changed attribute.
 			expect( getCaseText( root ) ).to.equal( 'adbcef' );
-			expect( editor.document.selection.getFirstRange().isEqual( r( 1, 4 ) ) ).to.be.true;
+			expect( editor.model.document.selection.getFirstRange().isEqual( r( 1, 4 ) ) ).to.be.true;
 		} );
 	} );
 } );

+ 113 - 96
packages/ckeditor5-undo/tests/undoengine-integration.js

@@ -9,6 +9,7 @@ import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'
 
 import Range from '@ckeditor/ckeditor5-engine/src/model/range';
 import Position from '@ckeditor/ckeditor5-engine/src/model/position';
+import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
 import UndoEngine from '../src/undoengine';
 
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
@@ -24,7 +25,7 @@ import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildv
 import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
 describe( 'UndoEngine integration', () => {
-	let editor, doc, root, div;
+	let editor, model, doc, root, div;
 
 	beforeEach( () => {
 		div = document.createElement( 'div' );
@@ -34,10 +35,11 @@ describe( 'UndoEngine integration', () => {
 			.then( newEditor => {
 				editor = newEditor;
 
-				doc = editor.document;
+				model = editor.model;
+				doc = model.document;
 
 				// Add "div feature".
-				doc.schema.registerItem( 'div', '$block' );
+				model.schema.registerItem( 'div', '$block' );
 				buildModelConverter().for( editor.data.modelToView, editor.editing.modelToView ).fromElement( 'div' ).toElement( 'div' );
 				buildViewConverter().for( editor.data.viewToModel ).fromElement( 'div' ).toElement( 'div' );
 
@@ -50,11 +52,11 @@ describe( 'UndoEngine integration', () => {
 	}
 
 	function input( input ) {
-		setData( doc, input );
+		setData( model, input );
 	}
 
 	function output( output ) {
-		expect( getData( doc ) ).to.equal( output );
+		expect( getData( model ) ).to.equal( output );
 	}
 
 	function undoDisabled() {
@@ -69,8 +71,8 @@ describe( 'UndoEngine integration', () => {
 		it( 'add and undo', () => {
 			input( '<paragraph>fo[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().insertText( 'zzz', doc.selection.getFirstPosition() );
+			model.change( writer => {
+				writer.insertText( 'zzz', doc.selection.getFirstPosition() );
 			} );
 			output( '<paragraph>fozzz[]o</paragraph><paragraph>bar</paragraph>' );
 
@@ -83,18 +85,16 @@ describe( 'UndoEngine integration', () => {
 		it( 'multiple adding and undo', () => {
 			input( '<paragraph>fo[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				const batch = doc.batch();
-
-				batch.insertText( 'zzz', doc.selection.getFirstPosition() );
-				batch.insertText( 'xxx', new Position( root, [ 1, 0 ] ) );
+			model.change( writer => {
+				writer.insertText( 'zzz', doc.selection.getFirstPosition() );
+				writer.insertText( 'xxx', new Position( root, [ 1, 0 ] ) );
 			} );
 
 			output( '<paragraph>fozzz[]o</paragraph><paragraph>xxxbar</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 1, 0 ], [ 1, 0 ] );
-				doc.batch().insertText( 'yyy', doc.selection.getFirstPosition() );
+				writer.insertText( 'yyy', doc.selection.getFirstPosition() );
 			} );
 
 			output( '<paragraph>fozzzo</paragraph><paragraph>yyy[]xxxbar</paragraph>' );
@@ -111,14 +111,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'multiple adding mixed with undo', () => {
 			input( '<paragraph>fo[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().insertText( 'zzz', doc.selection.getFirstPosition() );
+			model.change( writer => {
+				writer.insertText( 'zzz', doc.selection.getFirstPosition() );
 			} );
 			output( '<paragraph>fozzz[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 1, 0 ], [ 1, 0 ] );
-				doc.batch().insertText( 'yyy', doc.selection.getFirstPosition() );
+				writer.insertText( 'yyy', doc.selection.getFirstPosition() );
 			} );
 
 			output( '<paragraph>fozzzo</paragraph><paragraph>yyy[]bar</paragraph>' );
@@ -126,9 +126,9 @@ describe( 'UndoEngine integration', () => {
 			editor.execute( 'undo' );
 			output( '<paragraph>fozzzo</paragraph><paragraph>[]bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 0, 0 ], [ 0, 0 ] );
-				doc.batch().insertText( 'xxx', doc.selection.getFirstPosition() );
+				writer.insertText( 'xxx', doc.selection.getFirstPosition() );
 			} );
 			output( '<paragraph>xxx[]fozzzo</paragraph><paragraph>bar</paragraph>' );
 
@@ -144,14 +144,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'multiple remove and undo', () => {
 			input( '<paragraph>[]foo</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().remove( Range.createFromPositionAndShift( doc.selection.getFirstPosition(), 2 ) );
+			model.change( writer => {
+				writer.remove( Range.createFromPositionAndShift( doc.selection.getFirstPosition(), 2 ) );
 			} );
 			output( '<paragraph>[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 1, 1 ], [ 1, 1 ] );
-				doc.batch().remove( Range.createFromPositionAndShift( doc.selection.getFirstPosition(), 2 ) );
+				writer.remove( Range.createFromPositionAndShift( doc.selection.getFirstPosition(), 2 ) );
 			} );
 			output( '<paragraph>o</paragraph><paragraph>b[]</paragraph>' );
 
@@ -169,14 +169,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'add and remove different parts and undo', () => {
 			input( '<paragraph>fo[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().insertText( 'zzz', doc.selection.getFirstPosition() );
+			model.change( writer => {
+				writer.insertText( 'zzz', doc.selection.getFirstPosition() );
 			} );
 			output( '<paragraph>fozzz[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 1, 2 ], [ 1, 2 ] );
-				doc.batch().remove( Range.createFromPositionAndShift( new Position( root, [ 1, 1 ] ), 1 ) );
+				writer.remove( Range.createFromPositionAndShift( new Position( root, [ 1, 1 ] ), 1 ) );
 			} );
 			output( '<paragraph>fozzzo</paragraph><paragraph>b[]r</paragraph>' );
 
@@ -192,13 +192,13 @@ describe( 'UndoEngine integration', () => {
 		it( 'add and remove same part and undo', () => {
 			input( '<paragraph>fo[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().insertText( 'zzz', doc.selection.getFirstPosition() );
+			model.change( writer => {
+				writer.insertText( 'zzz', doc.selection.getFirstPosition() );
 			} );
 			output( '<paragraph>fozzz[]o</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().remove( Range.createFromPositionAndShift( new Position( root, [ 0, 2 ] ), 3 ) );
+			model.change( writer => {
+				writer.remove( Range.createFromPositionAndShift( new Position( root, [ 0, 2 ] ), 3 ) );
 			} );
 			output( '<paragraph>fo[]o</paragraph><paragraph>bar</paragraph>' );
 
@@ -214,8 +214,8 @@ describe( 'UndoEngine integration', () => {
 		it( 'undo remove all content', () => {
 			input( '<paragraph>foo[]</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().remove( Range.createIn( root ) );
+			model.change( writer => {
+				writer.remove( Range.createIn( root ) );
 			} );
 			output( '<paragraph>[]</paragraph>' ); // All hail our king and savior, autoparagraphing!
 
@@ -228,8 +228,8 @@ describe( 'UndoEngine integration', () => {
 		it( 'undo insert first content', () => {
 			input( '' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().insertElement( 'heading1', doc.selection.getFirstPosition() );
+			model.change( writer => {
+				writer.insertElement( 'heading1', doc.selection.getFirstPosition() );
 			} );
 			output( '<heading1>[]</heading1>' );
 
@@ -246,12 +246,10 @@ describe( 'UndoEngine integration', () => {
 			const p = root.getChild( 0 );
 			const pos = new Position( root, [ 0 ] );
 
-			doc.enqueueChanges( () => {
-				const batch = doc.batch();
-
-				batch.remove( p );
-				batch.insertElement( 'heading1', pos );
-				batch.insertElement( 'heading2', pos.getShiftedBy( 1 ) );
+			model.change( writer => {
+				writer.remove( p );
+				writer.insertElement( 'heading1', pos );
+				writer.insertElement( 'heading2', pos.getShiftedBy( 1 ) );
 			} );
 
 			output( '<heading1>[]</heading1><heading2></heading2>' );
@@ -268,13 +266,13 @@ describe( 'UndoEngine integration', () => {
 		it( 'move same content twice then undo', () => {
 			input( '<paragraph>f[o]z</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 1, 0 ] ) );
+			model.change( writer => {
+				writer.move( doc.selection.getFirstRange(), new Position( root, [ 1, 0 ] ) );
 			} );
 			output( '<paragraph>fz</paragraph><paragraph>[o]bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 0, 2 ] ) );
+			model.change( writer => {
+				writer.move( doc.selection.getFirstRange(), new Position( root, [ 0, 2 ] ) );
 			} );
 			output( '<paragraph>fz[o]</paragraph><paragraph>bar</paragraph>' );
 
@@ -290,14 +288,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'move content and new parent then undo', () => {
 			input( '<paragraph>f[o]z</paragraph><paragraph>bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 1, 0 ] ) );
+			model.change( writer => {
+				writer.move( doc.selection.getFirstRange(), new Position( root, [ 1, 0 ] ) );
 			} );
 			output( '<paragraph>fz</paragraph><paragraph>[o]bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 1 ], [ 2 ] );
-				doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 0 ] ) );
+				writer.move( doc.selection.getFirstRange(), new Position( root, [ 0 ] ) );
 			} );
 			output( '[<paragraph>obar</paragraph>]<paragraph>fz</paragraph>' );
 
@@ -315,14 +313,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'attributes then insert inside then undo', () => {
 			input( '<paragraph>fo[ob]ar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().setAttribute( 'bold', true, doc.selection.getFirstRange() );
+			model.change( writer => {
+				writer.setAttribute( 'bold', true, doc.selection.getFirstRange() );
 			} );
 			output( '<paragraph>fo[<$text bold="true">ob</$text>]ar</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 0, 3 ], [ 0, 3 ] );
-				doc.batch().insertText( 'zzz', doc.selection.getFirstPosition() );
+				writer.insertText( 'zzz', doc.selection.getFirstPosition() );
 			} );
 			output( '<paragraph>fo<$text bold="true">o</$text>zzz<$text bold="true">[]b</$text>ar</paragraph>' );
 			expect( doc.selection.getAttribute( 'bold' ) ).to.true;
@@ -340,11 +338,11 @@ describe( 'UndoEngine integration', () => {
 
 	describe( 'wrapping, unwrapping, merging, splitting', () => {
 		it( 'wrap and undo', () => {
-			doc.schema.allow( { name: '$text', inside: '$root' } );
+			model.schema.allow( { name: '$text', inside: '$root' } );
 			input( 'fo[zb]ar' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().wrap( doc.selection.getFirstRange(), 'paragraph' );
+			model.change( writer => {
+				writer.wrap( doc.selection.getFirstRange(), 'paragraph' );
 			} );
 			output( 'fo<paragraph>[zb]</paragraph>ar' );
 
@@ -355,18 +353,18 @@ describe( 'UndoEngine integration', () => {
 		} );
 
 		it( 'wrap, move and undo', () => {
-			doc.schema.allow( { name: '$text', inside: '$root' } );
+			model.schema.allow( { name: '$text', inside: '$root' } );
 			input( 'fo[zb]ar' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().wrap( doc.selection.getFirstRange(), 'paragraph' );
+			model.change( writer => {
+				writer.wrap( doc.selection.getFirstRange(), 'paragraph' );
 			} );
 			// Would be better if selection was inside P.
 			output( 'fo<paragraph>[zb]</paragraph>ar' );
 
-			doc.enqueueChanges( () => {
+			model.change( writer => {
 				setSelection( [ 2, 0 ], [ 2, 1 ] );
-				doc.batch().move( doc.selection.getFirstRange(), new Position( root, [ 0 ] ) );
+				writer.move( doc.selection.getFirstRange(), new Position( root, [ 0 ] ) );
 			} );
 			output( '[z]fo<paragraph>b</paragraph>ar' );
 
@@ -382,8 +380,8 @@ describe( 'UndoEngine integration', () => {
 		it( 'unwrap and undo', () => {
 			input( '<paragraph>foo[]bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().unwrap( doc.selection.getFirstPosition().parent );
+			model.change( writer => {
+				writer.unwrap( doc.selection.getFirstPosition().parent );
 			} );
 			output( 'foo[]bar' );
 
@@ -396,8 +394,8 @@ describe( 'UndoEngine integration', () => {
 		it( 'merge and undo', () => {
 			input( '<paragraph>foo</paragraph><paragraph>[]bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().merge( new Position( root, [ 1 ] ) );
+			model.change( writer => {
+				writer.merge( new Position( root, [ 1 ] ) );
 				// Because selection is stuck with <paragraph> it ends up in graveyard. We have to manually move it to correct node.
 				setSelection( [ 0, 3 ], [ 0, 3 ] );
 			} );
@@ -412,8 +410,8 @@ describe( 'UndoEngine integration', () => {
 		it( 'split and undo', () => {
 			input( '<paragraph>foo[]bar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				doc.batch().split( doc.selection.getFirstPosition() );
+			model.change( writer => {
+				writer.split( doc.selection.getFirstPosition() );
 				// Because selection is stuck with <paragraph> it ends up in wrong node. We have to manually move it to correct node.
 				setSelection( [ 1, 0 ], [ 1, 0 ] );
 			} );
@@ -771,13 +769,19 @@ describe( 'UndoEngine integration', () => {
 		it( 'rename leaks to other elements on undo #1', () => {
 			input( '<heading1>[]Foo</heading1><paragraph>Bar</paragraph>' );
 
-			doc.batch().rename( root.getChild( 0 ), 'paragraph' );
+			model.change( writer => {
+				writer.rename( root.getChild( 0 ), 'paragraph' );
+			} );
 			output( '<paragraph>[]Foo</paragraph><paragraph>Bar</paragraph>' );
 
-			doc.batch().split( Position.createAt( root.getChild( 0 ), 1 ) );
+			model.change( writer => {
+				writer.split( Position.createAt( root.getChild( 0 ), 1 ) );
+			} );
 			output( '<paragraph>[]F</paragraph><paragraph>oo</paragraph><paragraph>Bar</paragraph>' );
 
-			doc.batch().merge( Position.createAt( root, 2 ) );
+			model.change( writer => {
+				writer.merge( Position.createAt( root, 2 ) );
+			} );
 			output( '<paragraph>[]F</paragraph><paragraph>ooBar</paragraph>' );
 
 			editor.execute( 'undo' );
@@ -794,10 +798,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'rename leaks to other elements on undo #2', () => {
 			input( '<heading1>[]Foo</heading1><paragraph>Bar</paragraph>' );
 
-			doc.batch().rename( root.getChild( 0 ), 'heading2' );
+			model.change( writer => {
+				writer.rename( root.getChild( 0 ), 'heading2' );
+			} );
 			output( '<heading2>[]Foo</heading2><paragraph>Bar</paragraph>' );
 
-			doc.batch().merge( Position.createAt( root, 1 ) );
+			model.change( writer => {
+				writer.merge( Position.createAt( root, 1 ) );
+			} );
 			output( '<heading2>[]FooBar</heading2>' );
 
 			editor.execute( 'undo' );
@@ -811,10 +819,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'merge, rename, undo, undo is correct', () => {
 			input( '<heading1>[]Foo</heading1><paragraph>Bar</paragraph>' );
 
-			doc.batch().merge( Position.createAt( root, 1 ) );
+			model.change( writer => {
+				writer.merge( Position.createAt( root, 1 ) );
+			} );
 			output( '<heading1>[]FooBar</heading1>' );
 
-			doc.batch().rename( root.getChild( 0 ), 'heading2' );
+			model.change( writer => {
+				writer.rename( root.getChild( 0 ), 'heading2' );
+			} );
 			output( '<heading2>[]FooBar</heading2>' );
 
 			editor.execute( 'undo' );
@@ -828,10 +840,14 @@ describe( 'UndoEngine integration', () => {
 		it( 'wrap, split, undo, undo is correct', () => {
 			input( '<paragraph>[]Foo</paragraph><paragraph>Bar</paragraph>' );
 
-			doc.batch().wrap( Range.createIn( root ), 'div' );
+			model.change( writer => {
+				writer.wrap( Range.createIn( root ), 'div' );
+			} );
 			output( '<div><paragraph>[]Foo</paragraph><paragraph>Bar</paragraph></div>' );
 
-			doc.batch().split( new Position( root, [ 0, 0, 1 ] ) );
+			model.change( writer => {
+				writer.split( new Position( root, [ 0, 0, 1 ] ) );
+			} );
 			output( '<div><paragraph>[]F</paragraph><paragraph>oo</paragraph><paragraph>Bar</paragraph></div>' );
 
 			editor.execute( 'undo' );
@@ -878,7 +894,7 @@ describe( 'UndoEngine integration', () => {
 
 			editor.execute( 'enter' );
 
-			doc.enqueueChanges( () => {
+			model.change( () => {
 				const range = new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 1, 3 ] ) );
 
 				doc.selection.setRanges( [ range ] );
@@ -914,17 +930,17 @@ describe( 'UndoEngine integration', () => {
 
 		// ckeditor5-engine#t/1065
 		it( 'undo paste into non empty element should not throw and be correct', () => {
-			doc.enqueueChanges( () => {
+			model.change( () => {
 				input( '<paragraph>Foo[]</paragraph>' );
 			} );
 
-			doc.enqueueChanges( () => {
+			model.change( () => {
 				pasteHtml( editor, '<p>a</p><p>b</p>' );
 			} );
 
 			output( '<paragraph>Fooa</paragraph><paragraph>b[]</paragraph>' );
 
-			doc.enqueueChanges( () => {
+			model.change( () => {
 				pasteHtml( editor, '<p>c</p><p>d</p>' );
 			} );
 
@@ -942,9 +958,7 @@ describe( 'UndoEngine integration', () => {
 		it( 'deleteContent between two nodes', () => {
 			input( '<paragraph>fo[o</paragraph><paragraph>b]ar</paragraph>' );
 
-			doc.enqueueChanges( () => {
-				editor.data.deleteContent( doc.selection, doc.batch() );
-			} );
+			editor.data.deleteContent( doc.selection );
 			output( '<paragraph>fo[]ar</paragraph>' );
 
 			editor.execute( 'undo' );
@@ -958,9 +972,12 @@ describe( 'UndoEngine integration', () => {
 			const gy = doc.graveyard;
 			const p = doc.getRoot().getChild( 0 );
 
-			doc.enqueueChanges( () => {
-				doc.batch().remove( p );
-				doc.batch().setAttribute( 'bold', true, p );
+			model.change( writer => {
+				writer.remove( p );
+			} );
+
+			model.change( writer => {
+				writer.setAttribute( 'bold', true, p );
 			} );
 
 			editor.execute( 'undo' );
@@ -979,18 +996,18 @@ describe( 'UndoEngine integration', () => {
 			// Remove children from graveyard because they are inserted there after `input` call.
 			doc.graveyard.removeChildren( 0, doc.graveyard.childCount );
 
-			const batchWithMerge = doc.batch();
+			const batchWithMerge = new Batch();
 
-			doc.enqueueChanges( () => {
-				batchWithMerge.merge( new Position( root, [ 1 ] ) );
+			model.enqueueChange( batchWithMerge, writer => {
+				writer.merge( new Position( root, [ 1 ] ) );
+			} );
 
-				const split = batchWithMerge.deltas[ 0 ].getReversed();
-				const batch = doc.batch();
-				batch.addDelta( split );
+			const split = batchWithMerge.deltas[ 0 ].getReversed();
+			const batch = new Batch();
+			batch.addDelta( split );
 
-				doc.applyOperation( split.operations[ 0 ] );
-				doc.applyOperation( split.operations[ 1 ] );
-			} );
+			model.applyOperation( split.operations[ 0 ] );
+			model.applyOperation( split.operations[ 1 ] );
 
 			output( '<paragraph>[]Foo</paragraph><paragraph>Bar</paragraph>' );
 

+ 17 - 9
packages/ckeditor5-undo/tests/undoengine.js

@@ -4,17 +4,17 @@
  */
 
 import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
+import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
 import UndoEngine from '../src/undoengine';
 
 describe( 'UndoEngine', () => {
-	let editor, undo, batch, doc, root;
+	let editor, undo, model, root;
 
 	beforeEach( () => {
 		editor = new ModelTestEditor();
 
-		doc = editor.document;
-		batch = doc.batch();
-		root = doc.getRoot();
+		model = editor.model;
+		root = model.document.getRoot();
 
 		undo = new UndoEngine( editor );
 		undo.init();
@@ -37,7 +37,9 @@ describe( 'UndoEngine', () => {
 			expect( undo._undoCommand.addBatch.called ).to.be.false;
 			expect( undo._redoCommand.clearStack.called ).to.be.false;
 
-			batch.insertText( 'foobar', root );
+			model.change( writer => {
+				writer.insertText( 'foobar', root );
+			} );
 
 			expect( undo._undoCommand.addBatch.calledOnce ).to.be.true;
 			expect( undo._redoCommand.clearStack.calledOnce ).to.be.true;
@@ -46,8 +48,10 @@ describe( 'UndoEngine', () => {
 		it( 'should add each batch only once', () => {
 			sinon.spy( undo._undoCommand, 'addBatch' );
 
-			batch.insertText( 'foobar', root );
-			batch.insertText( 'foobar', root );
+			model.change( writer => {
+				writer.insertText( 'foobar', root );
+				writer.insertText( 'foobar', root );
+			} );
 
 			expect( undo._undoCommand.addBatch.calledOnce ).to.be.true;
 		} );
@@ -56,9 +60,13 @@ describe( 'UndoEngine', () => {
 			sinon.spy( undo._undoCommand, 'addBatch' );
 			sinon.spy( undo._redoCommand, 'clearStack' );
 
+			const batch = new Batch();
+
 			undo._redoCommand._createdBatches.add( batch );
 
-			batch.insertText( 'foobar', root );
+			model.enqueueChange( batch, writer => {
+				writer.insertText( 'foobar', root );
+			} );
 
 			expect( undo._undoCommand.addBatch.calledOnce ).to.be.true;
 			expect( undo._redoCommand.clearStack.called ).to.be.false;
@@ -68,7 +76,7 @@ describe( 'UndoEngine', () => {
 			sinon.spy( undo._redoCommand, 'addBatch' );
 			sinon.spy( undo._redoCommand, 'clearStack' );
 
-			undo._undoCommand.fire( 'revert', null, batch );
+			undo._undoCommand.fire( 'revert', null, new Batch() );
 
 			expect( undo._redoCommand.addBatch.calledOnce ).to.be.true;
 			expect( undo._redoCommand.clearStack.called ).to.be.false;