Ver código fonte

Tests: Fixed and added tests for delta transformations after changes done to operations and deltas transformations.

Szymon Cofalik 8 anos atrás
pai
commit
a9b215ad08

+ 69 - 0
packages/ckeditor5-engine/tests/model/delta/transform/attributedelta.js

@@ -14,7 +14,9 @@ import Position from '../../../../src/model/position';
 import Range from '../../../../src/model/range';
 
 import AttributeDelta from '../../../../src/model/delta/attributedelta';
+import Delta from '../../../../src/model/delta/delta';
 import AttributeOperation from '../../../../src/model/operation/attributeoperation';
+import NoOperation from '../../../../src/model/operation/nooperation';
 
 import {
 	expectDelta,
@@ -255,5 +257,72 @@ describe( 'transform', () => {
 				} );
 			} );
 		} );
+
+		describe( 'AttributeDelta', () => {
+			it( 'should be converted to no delta if all operations are NoOperations', () => {
+				const rangeA = new Range( new Position( root, [ 2 ] ), new Position( root, [ 4 ] ) );
+				const rangeB = new Range( new Position( root, [ 4 ] ), new Position( root, [ 7 ] ) );
+
+				const attrDeltaA = new AttributeDelta();
+				attrDeltaA.addOperation( new AttributeOperation( rangeA, 'key', 'old', 'new', 0 ) );
+				attrDeltaA.addOperation( new AttributeOperation( rangeB, 'key', null, 'new', 1 ) );
+
+				const attrDeltaB = new AttributeDelta();
+				attrDeltaB.addOperation( new AttributeOperation( rangeA, 'key', 'old', 'other', 0 ) );
+				attrDeltaB.addOperation( new AttributeOperation( rangeB, 'key', null, 'other', 1 ) );
+
+				const transformed = transform( attrDeltaA, attrDeltaB, context );
+
+				expect( transformed.length ).to.equal( 1 );
+
+				expectDelta( transformed[ 0 ], {
+					type: Delta,
+					operations: [
+						{
+							type: NoOperation,
+							baseVersion: 2
+						},
+						{
+							type: NoOperation,
+							baseVersion: 3
+						}
+					]
+				} );
+			} );
+
+			it( 'should put AttributeOperation as first operation in the delta', () => {
+				const rangeA = new Range( new Position( root, [ 2 ] ), new Position( root, [ 4 ] ) );
+				const rangeB = new Range( new Position( root, [ 4 ] ), new Position( root, [ 7 ] ) );
+
+				const attrDeltaA = new AttributeDelta();
+				attrDeltaA.addOperation( new AttributeOperation( rangeA, 'key', 'old', 'new', 0 ) );
+				attrDeltaA.addOperation( new AttributeOperation( rangeB, 'key', null, 'new', 1 ) );
+
+				const attrDeltaB = new AttributeDelta();
+				attrDeltaB.addOperation( new AttributeOperation( rangeA, 'key', 'old', 'other', 0 ) );
+
+				const transformed = transform( attrDeltaA, attrDeltaB, context );
+
+				expect( transformed.length ).to.equal( 1 );
+
+				expectDelta( transformed[ 0 ], {
+					type: AttributeDelta,
+					operations: [
+						{
+							type: AttributeOperation,
+							range: rangeB,
+							key: 'key',
+							oldValue: null,
+							newValue: 'new',
+							baseVersion: 1
+						},
+						{
+							type: NoOperation,
+							baseVersion: 2
+						}
+					]
+				} );
+			} );
+		} );
 	} );
 } );

+ 28 - 1
packages/ckeditor5-engine/tests/model/delta/transform/movedelta.js

@@ -109,7 +109,7 @@ describe( 'transform', () => {
 				expect( nodesAndText ).to.equal( 'DIVPabcfoobarxyzPXXXXXabcdXDIV' );
 			} );
 
-			it( 'move range in merged node', () => {
+			it( 'move range in merged node #1', () => {
 				const mergePosition = new Position( root, [ 3, 3 ] );
 				const mergeDelta = getMergeDelta( mergePosition, 1, 4, baseVersion );
 
@@ -132,6 +132,33 @@ describe( 'transform', () => {
 					]
 				} );
 			} );
+
+			it( 'move range in merged node #2', () => {
+				moveDelta._moveOperation.sourcePosition.path = [ 3, 3, 1 ];
+				moveDelta._moveOperation.targetPosition.path = [ 3, 3, 4 ];
+
+				const mergePosition = new Position( root, [ 3, 3 ] );
+				const mergeDelta = getMergeDelta( mergePosition, 1, 4, baseVersion );
+
+				const transformed = transform( moveDelta, mergeDelta, context );
+
+				expect( transformed.length ).to.equal( 1 );
+
+				baseVersion = mergeDelta.operations.length;
+
+				expectDelta( transformed[ 0 ], {
+					type: MoveDelta,
+					operations: [
+						{
+							type: MoveOperation,
+							sourcePosition: new Position( root, [ 3, 2, 2 ] ),
+							howMany: 1,
+							targetPosition: new Position( root, [ 3, 2, 5 ] ),
+							baseVersion
+						}
+					]
+				} );
+			} );
 		} );
 	} );
 } );

+ 30 - 0
packages/ckeditor5-engine/tests/model/delta/transform/removedelta.js

@@ -12,9 +12,11 @@ import Element from '../../../../src/model/element';
 import Position from '../../../../src/model/position';
 import Range from '../../../../src/model/range';
 
+import Delta from '../../../../src/model/delta/delta';
 import RemoveDelta from '../../../../src/model/delta/removedelta';
 import SplitDelta from '../../../../src/model/delta/splitdelta';
 
+import NoOperation from '../../../../src/model/operation/nooperation';
 import MoveOperation from '../../../../src/model/operation/moveoperation';
 import RemoveOperation from '../../../../src/model/operation/removeoperation';
 
@@ -128,6 +130,34 @@ describe( 'transform', () => {
 				} );
 			} );
 
+			it( 'removed nodes in split node, after split position, isStrong = false', () => {
+				const sourcePosition = new Position( root, [ 3, 3, 2, 4 ] );
+				const removeDelta = getRemoveDelta( sourcePosition, 3, baseVersion );
+
+				const splitPosition = new Position( root, [ 3, 3, 2, 2 ] );
+				const nodeCopy = new Element( 'x' );
+				const splitDelta = getSplitDelta( splitPosition, nodeCopy, 8, baseVersion );
+
+				const transformed = transform( removeDelta, splitDelta, {
+					isStrong: false,
+					forceWeakRemove: true
+				} );
+
+				expect( transformed.length ).to.equal( 1 );
+
+				baseVersion = splitDelta.operations.length;
+
+				expectDelta( transformed[ 0 ], {
+					type: Delta,
+					operations: [
+						{
+							type: NoOperation,
+							baseVersion
+						}
+					]
+				} );
+			} );
+
 			it( 'last node in the removed range was a node that has been split', () => {
 				const sourcePosition = new Position( root, [ 3, 2 ] );
 				const removeDelta = getRemoveDelta( sourcePosition, 2, baseVersion );

+ 28 - 0
packages/ckeditor5-engine/tests/model/delta/transform/renamedelta.js

@@ -11,7 +11,9 @@ import Element from '../../../../src/model/element';
 import Position from '../../../../src/model/position';
 
 import RenameDelta from '../../../../src/model/delta/renamedelta';
+import Delta from '../../../../src/model/delta/delta';
 import RenameOperation from '../../../../src/model/operation/renameoperation';
+import NoOperation from '../../../../src/model/operation/nooperation';
 
 import {
 	getFilledDocument,
@@ -105,5 +107,31 @@ describe( 'transform', () => {
 				} );
 			} );
 		} );
+
+		describe( 'RenameDelta', () => {
+			it( 'should be transformed to NoDelta if its operation is transformed to NoOperation', () => {
+				const renameDeltaA = new RenameDelta();
+				const renameDeltaB = new RenameDelta();
+
+				const op = new RenameOperation( new Position( root, [ 3 ] ), 'p', 'li', baseVersion );
+
+				renameDeltaA.addOperation( op );
+				renameDeltaB.addOperation( op.clone() );
+
+				const transformed = transform( renameDeltaA, renameDeltaB, context );
+
+				expect( transformed.length ).to.equal( 1 );
+
+				expectDelta( transformed[ 0 ], {
+					type: Delta,
+					operations: [
+						{
+							type: NoOperation,
+							baseVersion: 1
+						}
+					]
+				} );
+			} );
+		} );
 	} );
 } );

+ 40 - 4
packages/ckeditor5-engine/tests/model/delta/transform/splitdelta.js

@@ -65,11 +65,16 @@ describe( 'transform', () => {
 				expect( transformed.length ).to.equal( 1 );
 
 				expectDelta( transformed[ 0 ], {
-					type: Delta,
+					type: SplitDelta,
 					operations: [
 						{
-							type: NoOperation,
+							type: InsertOperation,
+							position: new Position( root, [ 3, 3, 4 ] ),
 							baseVersion
+						},
+						{
+							type: NoOperation,
+							baseVersion: baseVersion + 1
 						}
 					]
 				} );
@@ -79,11 +84,42 @@ describe( 'transform', () => {
 				applyDelta( splitDeltaB, doc );
 				applyDelta( transformed[ 0 ], doc );
 
-				const nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 0 ] ), 5 ) );
+				const nodesAndText = getNodesAndText( Range.createFromPositionAndShift( new Position( root, [ 3, 3, 0 ] ), 6 ) );
 
 				// Incoming split delta is discarded. Only one new element is created after applying both split deltas.
 				// There are no empty P elements.
-				expect( nodesAndText ).to.equal( 'XXXXXabcdXPabcPPfoobarxyzP' );
+				expect( nodesAndText ).to.equal( 'XXXXXabcdXPabcPPPPfoobarxyzP' );
+			} );
+
+			it( 'should not change context.insertBefore if it was set', () => {
+				// SplitDelta x SplitDelta transformation case sets `context.insertBefore` on its own if it is not set.
+				// It is to achieve better transformation results from UX point of view.
+				// However, if `context.insertBefore` was already set, it should not be changed. This might be important for undo.
+				const splitDeltaB = getSplitDelta( splitPosition, new Element( 'p' ), 9, baseVersion );
+				const transformed = transform( splitDelta, splitDeltaB, {
+					isStrong: false,
+					insertBefore: true
+				} );
+
+				baseVersion = splitDeltaB.operations.length;
+
+				expect( transformed.length ).to.equal( 1 );
+
+				expectDelta( transformed[ 0 ], {
+					type: SplitDelta,
+					operations: [
+						{
+							type: InsertOperation,
+							// If `context.insertBefore` would not be set, the offset would be 4. See an example above.
+							position: new Position( root, [ 3, 3, 5 ] ),
+							baseVersion
+						},
+						{
+							type: NoOperation,
+							baseVersion: baseVersion + 1
+						}
+					]
+				} );
 			} );
 
 			it( 'split in same parent, incoming delta splits closer', () => {

+ 6 - 3
packages/ckeditor5-engine/tests/model/delta/transform/transform.js

@@ -285,7 +285,7 @@ describe( 'transform', () => {
 				const { deltasA, deltasB } = transformDeltaSets( [ moveDelta ], [ removeDelta ] );
 
 				expectDelta( deltasA[ 0 ], {
-					type: MoveDelta,
+					type: Delta,
 					operations: [
 						{
 							type: NoOperation,
@@ -308,10 +308,13 @@ describe( 'transform', () => {
 				} );
 			} );
 
-			it( 'remove delta may be less important if additional context is used', () => {
+			it( 'remove delta may be less important if additional context is used and the delta was undone', () => {
 				const moveDelta = getMoveDelta( new Position( root, [ 0, 4 ] ), 3, new Position( root, [ 1, 0 ] ), baseVersion );
 				const removeDelta = getRemoveDelta( new Position( root, [ 0, 4 ] ), 3, baseVersion );
 
+				// "Fake" delta undoing.
+				doc.history.setDeltaAsUndone( removeDelta, new Delta() );
+
 				const { deltasA, deltasB } = transformDeltaSets( [ moveDelta ], [ removeDelta ], doc );
 
 				expectDelta( deltasA[ 0 ], {
@@ -328,7 +331,7 @@ describe( 'transform', () => {
 				} );
 
 				expectDelta( deltasB[ 0 ], {
-					type: RemoveDelta,
+					type: Delta,
 					operations: [
 						{
 							type: NoOperation,