瀏覽代碼

Fixed and added MoveOperation tests.

Szymon Cofalik 10 年之前
父節點
當前提交
9eddf5e763

+ 2 - 2
packages/ckeditor5-engine/src/document/moveoperation.js

@@ -73,7 +73,7 @@ CKEDITOR.define( [
 				 * @param {document.MoveOperation} moveOperation
 				 */
 				throw new CKEditorError(
-					'operation-move-source-position-invalid: Source position or target position is invalid.',
+					'operation-move-position-invalid: Source position or target position is invalid.',
 					{ moveOperation: this }
 				);
 			} else if ( sourceOffset + this.howMany > sourceElement.getChildCount() ) {
@@ -87,7 +87,7 @@ CKEDITOR.define( [
 					'operation-move-nodes-do-not-exist: The nodes which should be moved do not exist.',
 					{ moveOperation: this }
 				);
-			} else if ( sourceElement === targetElement && sourceOffset + this.howMany >= targetOffset ) {
+			} else if ( sourceElement === targetElement && sourceOffset <= targetOffset && targetOffset < sourceOffset + this.howMany ) {
 				/**
 				 * Trying to move a range of nodes into the middle of that range.
 				 *

+ 4 - 4
packages/ckeditor5-engine/src/utils.js

@@ -76,21 +76,21 @@ CKEDITOR.define( [ 'utils-lodash', 'lib/lodash/lodash-ckeditor' ], function( lod
 			for ( var i = 0; i < minLen; i++ ) {
 				if ( a[ i ] != b[ i ] ) {
 					// The arrays are different.
-					return this.DIFFERENT;
+					return utils.compareArrays.DIFFERENT;
 				}
 			}
 
 			// Both arrays were same at all points.
 			if ( a.length == b.length ) {
 				// If their length is also same, they are the same.
-				return this.SAME;
+				return utils.compareArrays.SAME;
 			} else if ( a.length < b.length ) {
 				// Compared array is shorter so it is a prefix of the other array.
-				return this.PREFIX;
+				return utils.compareArrays.PREFIX;
 			}
 
 			// In other case, the arrays are different.
-			return this.DIFFERENT;
+			return utils.compareArrays.DIFFERENT;
 		}
 	};
 

+ 163 - 124
packages/ckeditor5-engine/tests/document/moveoperation.js

@@ -11,166 +11,205 @@ var modules = bender.amd.require(
 	'document/document',
 	'document/moveoperation',
 	'document/position',
-	'document/character',
 	'document/element',
 	'document/nodelist',
-	'ckeditorerror' );
+	'ckeditorerror'
+);
 
 describe( 'MoveOperation', function() {
-	it( 'should move from one node to another', function() {
-		var Document = modules[ 'document/document' ];
-		var MoveOperation = modules[ 'document/moveoperation' ];
-		var Position = modules[ 'document/position' ];
-		var Element = modules[ 'document/element' ];
+	var Document, MoveOperation, Position, Element, NodeList, CKEditorError;
+
+	before( function() {
+		Document = modules[ 'document/document' ];
+		MoveOperation = modules[ 'document/moveoperation' ];
+		Position = modules[ 'document/position' ];
+		Element = modules[ 'document/element' ];
+		NodeList = modules[ 'document/nodelist' ];
+		CKEditorError = modules.ckeditorerror;
+	} );
+
+	var doc, root;
 
-		var doc = new Document();
+	beforeEach( function() {
+		doc = new Document();
+		root = doc.createRoot( 'root' );
+	} );
 
+	it( 'should move from one node to another', function() {
 		var p1 = new Element( 'p1', [], new Element( 'x' ) );
 		var p2 = new Element( 'p2' );
 
-		doc.root.insertChildren( 0, [ p1, p2 ] );
-
-		doc.applyOperation( new MoveOperation(
-			new Position( [ 0, 0 ], doc.root ),
-			new Position( [ 1, 0 ], doc.root ),
-			p1.getChild( 0 ),
-			doc.version ) );
-
-		expect( doc.version ).to.be.equal( 1 );
-		expect( doc.root.getChildCount() ).to.be.equal( 2 );
-		expect( doc.root.getChild( 0 ).name ).to.be.equal( 'p1' );
-		expect( doc.root.getChild( 1 ).name ).to.be.equal( 'p2' );
-		expect( p1.getChildCount() ).to.be.equal( 0 );
-		expect( p2.getChildCount() ).to.be.equal( 1 );
-		expect( p2.getChild( 0 ).name ).to.be.equal( 'x' );
+		root.insertChildren( 0, [ p1, p2 ] );
+
+		doc.applyOperation(
+			new MoveOperation(
+				new Position( [ 0, 0 ], root ),
+				new Position( [ 1, 0 ], root ),
+				1,
+				doc.version
+			)
+		);
+
+		expect( doc.version ).to.equal( 1 );
+		expect( root.getChildCount() ).to.equal( 2 );
+		expect( root.getChild( 0 ).name ).to.equal( 'p1' );
+		expect( root.getChild( 1 ).name ).to.equal( 'p2' );
+		expect( p1.getChildCount() ).to.equal( 0 );
+		expect( p2.getChildCount() ).to.equal( 1 );
+		expect( p2.getChild( 0 ).name ).to.equal( 'x' );
 	} );
 
 	it( 'should move position of children in one node backward', function() {
-		var Document = modules[ 'document/document' ];
-		var MoveOperation = modules[ 'document/moveoperation' ];
-		var Position = modules[ 'document/position' ];
-
-		var doc = new Document();
-
-		doc.root.insertChildren( 0, 'xbarx' );
-
-		doc.applyOperation( new MoveOperation(
-			new Position( [ 2 ], doc.root ),
-			new Position( [ 1 ], doc.root ),
-			[ doc.root.getChild( 2 ),  doc.root.getChild( 3 ) ],
-			doc.version ) );
-
-		expect( doc.version ).to.be.equal( 1 );
-		expect( doc.root.getChildCount() ).to.be.equal( 5 );
-		expect( doc.root.getChild( 0 ).character ).to.be.equal( 'x' );
-		expect( doc.root.getChild( 1 ).character ).to.be.equal( 'a' );
-		expect( doc.root.getChild( 2 ).character ).to.be.equal( 'r' );
-		expect( doc.root.getChild( 3 ).character ).to.be.equal( 'b' );
-		expect( doc.root.getChild( 4 ).character ).to.be.equal( 'x' );
+		root.insertChildren( 0, 'xbarx' );
+
+		doc.applyOperation(
+			new MoveOperation(
+				new Position( [ 2 ], root ),
+				new Position( [ 1 ], root ),
+				2,
+				doc.version
+			)
+		);
+
+		expect( doc.version ).to.equal( 1 );
+		expect( root.getChildCount() ).to.equal( 5 );
+		expect( root.getChild( 0 ).character ).to.equal( 'x' );
+		expect( root.getChild( 1 ).character ).to.equal( 'a' );
+		expect( root.getChild( 2 ).character ).to.equal( 'r' );
+		expect( root.getChild( 3 ).character ).to.equal( 'b' );
+		expect( root.getChild( 4 ).character ).to.equal( 'x' );
 	} );
 
 	it( 'should move position of children in one node forward', function() {
-		var Document = modules[ 'document/document' ];
-		var MoveOperation = modules[ 'document/moveoperation' ];
-		var Position = modules[ 'document/position' ];
-
-		var doc = new Document();
-
-		doc.root.insertChildren( 0, 'xbarx' );
-
-		doc.applyOperation( new MoveOperation(
-			new Position( [ 1 ], doc.root ),
-			new Position( [ 4 ], doc.root ),
-			[ doc.root.getChild( 1 ),  doc.root.getChild( 2 ) ],
-			doc.version ) );
-
-		expect( doc.version ).to.be.equal( 1 );
-		expect( doc.root.getChildCount() ).to.be.equal( 5 );
-		expect( doc.root.getChild( 0 ).character ).to.be.equal( 'x' );
-		expect( doc.root.getChild( 1 ).character ).to.be.equal( 'r' );
-		expect( doc.root.getChild( 2 ).character ).to.be.equal( 'b' );
-		expect( doc.root.getChild( 3 ).character ).to.be.equal( 'a' );
-		expect( doc.root.getChild( 4 ).character ).to.be.equal( 'x' );
+		root.insertChildren( 0, 'xbarx' );
+
+		doc.applyOperation(
+			new MoveOperation(
+				new Position( [ 1 ], root ),
+				new Position( [ 4 ], root ),
+				2,
+				doc.version
+			)
+		);
+
+		expect( doc.version ).to.equal( 1 );
+		expect( root.getChildCount() ).to.equal( 5 );
+		expect( root.getChild( 0 ).character ).to.equal( 'x' );
+		expect( root.getChild( 1 ).character ).to.equal( 'r' );
+		expect( root.getChild( 2 ).character ).to.equal( 'b' );
+		expect( root.getChild( 3 ).character ).to.equal( 'a' );
+		expect( root.getChild( 4 ).character ).to.equal( 'x' );
 	} );
 
 	it( 'should create a move operation as a reverse', function() {
-		var Document = modules[ 'document/document' ];
-		var MoveOperation = modules[ 'document/moveoperation' ];
-		var Position = modules[ 'document/position' ];
-		var NodeList = modules[ 'document/nodelist' ];
-
-		var doc = new Document();
-
 		var nodeList = new NodeList( 'bar' );
 
-		var sourcePosition = new Position( [ 0 ], doc.root );
-		var targetPosition = new Position( [ 4 ], doc.root );
+		var sourcePosition = new Position( [ 0 ], root );
+		var targetPosition = new Position( [ 4 ], root );
 
-		var operation = new MoveOperation( sourcePosition, targetPosition, nodeList, doc.version );
+		var operation = new MoveOperation( sourcePosition, targetPosition, nodeList.length, doc.version );
 
 		var reverse = operation.reverseOperation();
 
 		expect( reverse ).to.be.an.instanceof( MoveOperation );
-		expect( reverse.baseVersion ).to.equals( 1 );
-		expect( reverse.nodeList ).to.equals( nodeList );
-		expect( reverse.sourcePosition ).to.equals( targetPosition );
-		expect( reverse.targetPosition ).to.equals( sourcePosition );
+		expect( reverse.baseVersion ).to.equal( 1 );
+		expect( reverse.howMany ).to.equal( nodeList.length );
+		expect( reverse.sourcePosition ).to.equal( targetPosition );
+		expect( reverse.targetPosition ).to.equal( sourcePosition );
 	} );
 
-	it( 'should move node by applying reverse operation', function() {
-		var Document = modules[ 'document/document' ];
-		var MoveOperation = modules[ 'document/moveoperation' ];
-		var Position = modules[ 'document/position' ];
-		var Element = modules[ 'document/element' ];
-
-		var doc = new Document();
-
+	it( 'should undo move node by applying reverse operation', function() {
 		var p1 = new Element( 'p1', [], new Element( 'x' ) );
 		var p2 = new Element( 'p2' );
 
-		doc.root.insertChildren( 0, [ p1, p2 ] );
+		root.insertChildren( 0, [ p1, p2 ] );
 
-		var operation =  new MoveOperation(
-			new Position( [ 0, 0 ], doc.root ),
-			new Position( [ 1, 0 ], doc.root ),
-			p1.getChild( 0 ),
-			doc.version );
+		var operation = new MoveOperation(
+			new Position( [ 0, 0 ], root ),
+			new Position( [ 1, 0 ], root ),
+			1,
+			doc.version
+		);
 
 		doc.applyOperation( operation );
 
-		expect( doc.version ).to.be.equal( 1 );
-		expect( doc.root.getChildCount() ).to.be.equal( 2 );
-		expect( p1.getChildCount() ).to.be.equal( 0 );
-		expect( p2.getChildCount() ).to.be.equal( 1 );
-		expect( p2.getChild( 0 ).name ).to.be.equal( 'x' );
+		expect( doc.version ).to.equal( 1 );
+		expect( root.getChildCount() ).to.equal( 2 );
+		expect( p1.getChildCount() ).to.equal( 0 );
+		expect( p2.getChildCount() ).to.equal( 1 );
+		expect( p2.getChild( 0 ).name ).to.equal( 'x' );
 
 		doc.applyOperation( operation.reverseOperation() );
 
-		expect( doc.version ).to.be.equal( 2 );
-		expect( doc.root.getChildCount() ).to.be.equal( 2 );
-		expect( p1.getChildCount() ).to.be.equal( 1 );
-		expect( p1.getChild( 0 ).name ).to.be.equal( 'x' );
-		expect( p2.getChildCount() ).to.be.equal( 0 );
+		expect( doc.version ).to.equal( 2 );
+		expect( root.getChildCount() ).to.equal( 2 );
+		expect( p1.getChildCount() ).to.equal( 1 );
+		expect( p1.getChild( 0 ).name ).to.equal( 'x' );
+		expect( p2.getChildCount() ).to.equal( 0 );
 	} );
 
-	if ( CKEDITOR.isDebug ) {
-		it( 'should throw error if nodes to move are different then actual nodes', function() {
-			var Document = modules[ 'document/document' ];
-			var MoveOperation = modules[ 'document/moveoperation' ];
-			var Position = modules[ 'document/position' ];
-			var CKEditorError = modules.ckeditorerror;
-
-			var doc = new Document();
-
-			doc.root.insertChildren( 0, 'xbarx' );
-
-			expect( function() {
-				doc.applyOperation( new MoveOperation(
-					new Position( [ 1 ], doc.root ),
-					new Position( [ 4 ], doc.root ),
-					'y',
-					doc.version ) );
-			} ).to.throw( CKEditorError, /operation-move-node-does-not-exists/ );
-		} );
-	}
-} );
+	it( 'should throw an error if number of nodes to move exceeds the number of existing nodes in given element', function() {
+		root.insertChildren( 0, 'xbarx' );
+
+		expect( function() {
+			doc.applyOperation(
+				new MoveOperation(
+					new Position( [ 3 ], root ),
+					new Position( [ 1 ], root ),
+					3,
+					doc.version
+				)
+			);
+		} ).to.throw( CKEditorError, /operation-move-nodes-do-not-exist/ );
+	} );
+
+	it( 'should throw an error if target or source parent-element specified by position does not exist', function() {
+		var p = new Element( 'p' );
+		p.insertChildren( 0, 'foo' );
+		root.insertChildren( 0, [ 'ab', p ] );
+
+		var operation = new MoveOperation(
+			new Position( [ 2, 0 ], root ),
+			new Position( [ 1 ], root ),
+			3,
+			doc.version
+		);
+
+		root.removeChildren( 2, 1 );
+
+		expect( function() {
+			doc.applyOperation( operation );
+		} ).to.throw( CKEditorError, /operation-move-position-invalid/ );
+	} );
+
+	it( 'should throw an error if operation tries to move a range between the beginning and the end of that range', function() {
+		root.insertChildren( 0, 'xbarx' );
+
+		var operation = new MoveOperation(
+			new Position( [ 1 ], root ),
+			new Position( [ 2 ], root ),
+			3,
+			doc.version
+		);
+
+		expect( function() {
+			doc.applyOperation( operation );
+		} ).to.throw( CKEditorError, /operation-move-range-into-itself/ );
+	} );
+
+	it( 'should throw an error if operation tries to move a range into a sub-tree of a node that is in that range', function() {
+		var p = new Element( 'p', [], [ new Element( 'p' ) ] );
+		root.insertChildren( 0, [ 'ab', p, 'xy' ] );
+
+		var operation = new MoveOperation(
+			new Position( [ 1 ], root ),
+			new Position( [ 2, 0, 0 ], root ),
+			3,
+			doc.version
+		);
+
+		expect( function() {
+			doc.applyOperation( operation );
+		} ).to.throw( CKEditorError, /operation-move-node-into-itself/ );
+	} );
+} );