Explorar o código

Added more tests to core.treeView.writer.

Szymon Kupś %!s(int64=9) %!d(string=hai) anos
pai
achega
e7474ecf05

+ 1 - 1
packages/ckeditor5-engine/src/treeview/writer.js

@@ -492,7 +492,7 @@ function wrapChildren( writer, parent, startOffset, endOffset, attribute ) {
 
 	for ( let position of wrapPositions ) {
 		// Do not merge with elements outside selected children.
-		if ( position.offset == startOffset || position.offset == endOffset ) {
+		if ( position.offset == startOffset ) {
 			continue;
 		}
 

+ 363 - 2
packages/ckeditor5-engine/tests/treeview/writer.js

@@ -12,6 +12,7 @@ import Element from '/ckeditor5/core/treeview/element.js';
 import Text from '/ckeditor5/core/treeview/text.js';
 import Position from '/ckeditor5/core/treeview/position.js';
 import Range from '/ckeditor5/core/treeview/range.js';
+import CKEditorError from '/ckeditor5/core/ckeditorerror.js';
 
 describe( 'Writer', () => {
 	/**
@@ -202,6 +203,31 @@ describe( 'Writer', () => {
 		} );
 	} );
 
+	describe( 'getParentContainer', () => {
+		it( 'should return parent container of the node', () => {
+			const writer = new Writer();
+			const text = new Text( 'foobar' );
+			const b = new Element( 'b', null, [ text ] );
+			const parent = new Element( 'p', null, [ b ] );
+
+			writer.setPriority( b, 1 );
+			const container = writer.getParentContainer( new Position( text, 0 ) );
+
+			expect( container ).to.equal( parent );
+		} );
+
+		it( 'should return null if no parent container', () => {
+			const writer = new Writer();
+			const text = new Text( 'foobar' );
+			const b = new Element( 'b', null, [ text ] );
+
+			writer.setPriority( b, 1 );
+			const container = writer.getParentContainer( new Position( text, 0 ) );
+
+			expect( container ).to.equal( null );
+		} );
+	} );
+
 	describe( 'breakAttributes', () => {
 		// <p>{|foobar}</p> -> <p>|{foobar}</p>
 		it( '<p>{|foobar}</p>', () => {
@@ -504,6 +530,35 @@ describe( 'Writer', () => {
 			test( writer, newPosition, created.node, description );
 		} );
 
+		it( 'should not merge if between containers', () => {
+			// <div><p>{foo}</p>|<p>{bar}</p></div>
+			const writer = new Writer();
+			const description = {
+				instanceOf: Element,
+				name: 'div',
+				position: 1,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'p',
+						children: [
+							{ instanceOf: Text, data: 'foo' }
+						]
+					},
+					{
+						instanceOf: Element,
+						name: 'p',
+						children: [
+							{ instanceOf: Text, data: 'bar' }
+						]
+					}
+				]
+			};
+			const created = create( writer, description );
+			const newPosition = writer.mergeAttributes( created.position );
+			test( writer, newPosition, created.node, description );
+		} );
+
 		it( 'should return same position when inside empty container', () => {
 			// <p>|</p>
 			const writer = new Writer();
@@ -774,12 +829,24 @@ describe( 'Writer', () => {
 	} );
 
 	describe( 'wrap', () => {
-		// TODO: test - range not in same container
-		// TODO: test - range collapsed
 		// TODO: tests - different priorities
 		// TODO: tests - empty containers left
 		// TODO: merge with elements outside range at the ends
 
+		it( 'should do nothing on collapsed ranges', () => {
+			const writer = new Writer();
+			const description = {
+				instanceOf: Element,
+				name: 'p',
+				children: [
+					{ instanceOf: Text, data: 'foo', rangeStart: 1, rangeEnd: 1 }
+				]
+			};
+			const created = create( writer, description );
+			const newRange = writer.wrap( created.range, new Element( 'b' ), 1 );
+			test( writer, newRange, created.node, description );
+		} );
+
 		it( 'wraps single text node', () => {
 			// <p>[{foobar}]</p>
 			// wrap <b>
@@ -816,6 +883,21 @@ describe( 'Writer', () => {
 			} );
 		} );
 
+		it( 'should throw error when range placed in two containers', () => {
+			const writer = new Writer();
+			const container1 = new Element( 'p' );
+			const container2 = new Element( 'p' );
+			const range = new Range(
+				new Position( container1, 0 ),
+				new Position( container2, 1 )
+			);
+			const b = new Element( 'b' );
+
+			expect( () => {
+				writer.wrap( range, b, 1 );
+			} ).to.throw( CKEditorError, 'treeview-writer-unwrap-invalid-range' );
+		} );
+
 		it( 'wraps part of single text node', () => {
 			// <p>[{foo]bar}</p>
 			// wrap with <b>
@@ -852,6 +934,54 @@ describe( 'Writer', () => {
 			} );
 		} );
 
+		it( 'should not wrap inside nested containers', () => {
+			// <div>[{foobar}<p>{baz}</p>]</div>
+			// wrap with <b>
+			// <div>[<b>{foobar}</b><p>{baz}</p>]</div>
+			const writer = new Writer();
+			const created = create( writer, {
+				instanceOf: Element,
+				name: 'div',
+				rangeStart: 0,
+				rangeEnd: 2,
+				children: [
+					{ instanceOf: Text, data: 'foobar' },
+					{
+						instanceOf: Element,
+						name: 'p',
+						children: [
+							{ instanceOf: Text, data: 'baz' }
+						]
+					}
+				]
+			} );
+
+			const newRange = writer.wrap( created.range, new Element( 'b' ), 1 );
+			test( writer, newRange, created.node, {
+				instanceOf: Element,
+				name: 'div',
+				rangeStart: 0,
+				rangeEnd: 2,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'foobar' }
+						]
+					},
+					{
+						instanceOf: Element,
+						name: 'p',
+						children: [
+							{ instanceOf: Text, data: 'baz' }
+						]
+					}
+				]
+			} );
+		} );
+
 		it( 'wraps according to priorities', () => {
 			// <p>[<u>{foobar}</u>]</p>
 			// wrap with <b> that has higher priority than <u>
@@ -953,9 +1083,225 @@ describe( 'Writer', () => {
 				]
 			} );
 		} );
+
+		it( 'merges wrapped nodes #2', () => {
+			// <p><b>{foo}</b>[{bar]baz}</p>
+			// wrap with <b>
+			// <p><b>{foo[bar}</b>]{baz}</p>
+
+			const writer = new Writer();
+			const created = create( writer, {
+				instanceOf: Element,
+				name: 'p',
+				rangeStart: 1,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'foo' }
+						]
+					},
+					{ instanceOf: Text, data: 'barbaz', rangeEnd: 3 }
+				]
+			} );
+
+			const newRange = writer.wrap( created.range, new Element( 'b' ), 1 );
+			test( writer, newRange, created.node, {
+				instanceOf: Element,
+				name: 'p',
+				rangeEnd: 1,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'foobar', rangeStart: 3 }
+						]
+					},
+					{ instanceOf: Text, data: 'baz' }
+				]
+			} );
+		} );
+
+		it( 'merges wrapped nodes #3', () => {
+			// <p><b>{foobar}</b>[{baz}]</p>
+			// wrap with <b>
+			// <p><b>{foobar[baz}</b>]</p>
+
+			const writer = new Writer();
+			const created = create( writer, {
+				instanceOf: Element,
+				name: 'p',
+				rangeStart: 1,
+				rangeEnd: 2,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'foobar' }
+						]
+					},
+					{ instanceOf: Text, data: 'baz', rangeEnd: 3 }
+				]
+			} );
+
+			const newRange = writer.wrap( created.range, new Element( 'b' ), 1 );
+			test( writer, newRange, created.node, {
+				instanceOf: Element,
+				name: 'p',
+				rangeEnd: 1,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'foobarbaz', rangeStart: 6 }
+						]
+					}
+				]
+			} );
+		} );
+
+		it( 'merges wrapped nodes #4', () => {
+			// <p>[{foo}<i>{bar}</i>]{baz}</p>
+			// wrap with <b>
+			// <p>[<b>{foo}<i>{bar}</i></b>]{baz}</p>
+			const writer = new Writer();
+			const created = create( writer, {
+				instanceOf: Element,
+				name: 'p',
+				rangeStart: 0,
+				rangeEnd: 2,
+				children: [
+					{ instanceOf: Text, data: 'foo' },
+					{
+						instanceOf: Element,
+						name: 'i',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'bar' }
+						]
+					},
+					{ instanceOf: Text, data: 'baz' }
+				]
+			} );
+
+			const newRange = writer.wrap( created.range, new Element( 'b' ), 1 );
+			test( writer, newRange, created.node, {
+				instanceOf: Element,
+				name: 'p',
+				rangeStart: 0,
+				rangeEnd: 1,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'foo' },
+							{
+								instanceOf: Element,
+								name: 'i',
+								priority: 1,
+								children: [
+									{ instanceOf: Text, data: 'bar' }
+								]
+							}
+						]
+					},
+					{ instanceOf: Text, data: 'baz' }
+				]
+			} );
+		} );
+
+		it( 'merges wrapped nodes #5', () => {
+			// <p>[{foo}<i>{bar}</i>{baz}]</p>
+			// wrap with <b>, that has higher priority than <i>
+			// <p>[<b>{foo}</b><i><b>{bar}</b></i><b>{baz}</b>]</p>
+			const writer = new Writer();
+			const created = create( writer, {
+				instanceOf: Element,
+				name: 'p',
+				rangeStart: 0,
+				rangeEnd: 3,
+				children: [
+					{ instanceOf: Text, data: 'foo' },
+					{
+						instanceOf: Element,
+						name: 'i',
+						priority: 1,
+						children: [
+							{ instanceOf: Text, data: 'bar' }
+						]
+					},
+					{ instanceOf: Text, data: 'baz' }
+				]
+			} );
+
+			const newRange = writer.wrap( created.range, new Element( 'b' ), 2 );
+			test( writer, newRange, created.node, {
+				instanceOf: Element,
+				name: 'p',
+				rangeStart: 0,
+				rangeEnd: 3,
+				children: [
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 2,
+						children: [
+							{ instanceOf: Text, data: 'foo' }
+						]
+					},
+					{
+						instanceOf: Element,
+						name: 'i',
+						priority: 1,
+						children: [
+							{
+								instanceOf: Element,
+								name: 'b',
+								priority: 2,
+								children: [
+									{ instanceOf: Text, data: 'bar' }
+								]
+							}
+						]
+					},
+					{
+						instanceOf: Element,
+						name: 'b',
+						priority: 2,
+						children: [
+							{ instanceOf: Text, data: 'baz' }
+						]
+					},
+				]
+			} );
+		} );
 	} );
 
 	describe( 'unwrap', () => {
+		it( 'should do nothing on collapsed ranges', () => {
+			const writer = new Writer();
+			const description = {
+				instanceOf: Element,
+				name: 'p',
+				children: [
+					{ instanceOf: Text, data: 'foo', rangeStart: 1, rangeEnd: 1 }
+				]
+			};
+			const created = create( writer, description );
+			const newRange = writer.unwrap( created.range, new Element( 'b' ), 1 );
+			test( writer, newRange, created.node, description );
+		} );
+
 		it( 'should do nothing on single text node', () => {
 			// <p>[{foobar}]</p>
 			const writer = new Writer();
@@ -977,6 +1323,21 @@ describe( 'Writer', () => {
 			test( writer, newRange, created.node, description );
 		} );
 
+		it( 'should throw error when range placed in two containers', () => {
+			const writer = new Writer();
+			const container1 = new Element( 'p' );
+			const container2 = new Element( 'p' );
+			const range = new Range(
+				new Position( container1, 0 ),
+				new Position( container2, 1 )
+			);
+			const b = new Element( 'b' );
+
+			expect( () => {
+				writer.unwrap( range, b, 1 );
+			} ).to.throw( CKEditorError, 'treeview-writer-unwrap-invalid-range' );
+		} );
+
 		it( 'should unwrap single node', () => {
 			// <p>[<b>{foobar}</b>]<p> -> <p>[{foobar}]</p>
 			const writer = new Writer();