Bladeren bron

Fixed view writer tests.

Szymon Kupś 8 jaren geleden
bovenliggende
commit
606f5a65b9

+ 2 - 2
packages/ckeditor5-engine/src/view/writer.js

@@ -732,7 +732,7 @@ export default class Writer {
 	// @param {Number} startOffset
 	// @param {Number} endOffset
 	// @param {module:engine/view/element~Element} attribute
-	wrapChildren( parent, startOffset, endOffset, attribute ) {
+	_wrapChildren( parent, startOffset, endOffset, attribute ) {
 		let i = startOffset;
 		const wrapPositions = [];
 
@@ -757,7 +757,7 @@ export default class Writer {
 			}
 			// If other nested attribute is found start wrapping there.
 			else if ( isAttribute ) {
-				this.wrapChildren( child, 0, child.childCount, attribute );
+				this._wrapChildren( child, 0, child.childCount, attribute );
 			}
 
 			i++;

+ 17 - 11
packages/ckeditor5-engine/tests/view/writer/breakattributes.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { breakAttributes } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import { stringify, parse } from '../../../src/dev-utils/view';
 import ContainerElement from '../../../src/view/containerelement';
 import AttributeElement from '../../../src/view/attributeelement';
@@ -13,8 +13,14 @@ import Range from '../../../src/view/range';
 import Position from '../../../src/view/position';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
-describe( 'writer', () => {
-	describe( 'breakAttributes', () => {
+describe( 'Writer', () => {
+	describe( 'breakAttributes()', () => {
+		let writer;
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		describe( 'break position', () => {
 			/**
 			 * Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
@@ -26,7 +32,7 @@ describe( 'writer', () => {
 			function test( input, expected ) {
 				const { view, selection } = parse( input );
 
-				const newPosition = breakAttributes( selection.getFirstPosition() );
+				const newPosition = writer.breakAttributes( selection.getFirstPosition() );
 				expect( stringify( view.root, newPosition, {
 					showType: true,
 					showPriority: true
@@ -138,7 +144,7 @@ describe( 'writer', () => {
 			function test( input, expected ) {
 				const { view, selection } = parse( input );
 
-				const newRange = breakAttributes( selection.getFirstRange() );
+				const newRange = writer.breakAttributes( selection.getFirstRange() );
 				expect( stringify( view.root, newRange, { showType: true } ) ).to.equal( expected );
 			}
 
@@ -147,7 +153,7 @@ describe( 'writer', () => {
 				const p2 = new ContainerElement( 'p' );
 
 				expect( () => {
-					breakAttributes( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) );
+					writer.breakAttributes( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) );
 				} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 			} );
 
@@ -155,7 +161,7 @@ describe( 'writer', () => {
 				const el = new AttributeElement( 'b' );
 
 				expect( () => {
-					breakAttributes( Range.createFromParentsAndOffsets( el, 0, el, 0 ) );
+					writer.breakAttributes( Range.createFromParentsAndOffsets( el, 0, el, 0 ) );
 				} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 			} );
 
@@ -237,7 +243,7 @@ describe( 'writer', () => {
 				const position = new Position( img, 0 );
 
 				expect( () => {
-					breakAttributes( position );
+					writer.breakAttributes( position );
 				} ).to.throw( CKEditorError, 'view-writer-cannot-break-empty-element' );
 			} );
 
@@ -248,7 +254,7 @@ describe( 'writer', () => {
 				const range = Range.createFromParentsAndOffsets( img, 0, b, 0 );
 
 				expect( () => {
-					breakAttributes( range );
+					writer.breakAttributes( range );
 				} ).to.throw( CKEditorError, 'view-writer-cannot-break-empty-element' );
 			} );
 
@@ -258,7 +264,7 @@ describe( 'writer', () => {
 				const position = new Position( span, 0 );
 
 				expect( () => {
-					breakAttributes( position );
+					writer.breakAttributes( position );
 				} ).to.throw( CKEditorError, 'view-writer-cannot-break-ui-element' );
 			} );
 
@@ -269,7 +275,7 @@ describe( 'writer', () => {
 				const range = Range.createFromParentsAndOffsets( span, 0, b, 0 );
 
 				expect( () => {
-					breakAttributes( range );
+					writer.breakAttributes( range );
 				} ).to.throw( CKEditorError, 'view-writer-cannot-break-ui-element' );
 			} );
 		} );

+ 21 - 17
packages/ckeditor5-engine/tests/view/writer/breakcontainer.js

@@ -3,28 +3,32 @@
  * For licensing, see LICENSE.md.
  */
 
-import { breakContainer } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import { stringify, parse } from '../../../src/dev-utils/view';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 import ContainerElement from '../../../src/view/containerelement';
 import Position from '../../../src/view/position';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
-	 * test break position.
-	 *
-	 * @param {String} input
-	 * @param {String} expected
-	 */
-	function test( input, expected ) {
-		const { view, selection } = parse( input );
+describe( 'Writer', () => {
+	describe( 'breakContainer()', () => {
+		let writer;
 
-		const newPosition = breakContainer( selection.getFirstPosition() );
-		expect( stringify( view.root, newPosition, { showType: true, showPriority: false } ) ).to.equal( expected );
-	}
+		// Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
+		// test break position.
+		//
+		// @param {String} input
+		// @param {String} expected
+		function test( input, expected ) {
+			const { view, selection } = parse( input );
+
+			const newPosition = writer.breakContainer( selection.getFirstPosition() );
+			expect( stringify( view.root, newPosition, { showType: true, showPriority: false } ) ).to.equal( expected );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
 
-	describe( 'breakContainer', () => {
 		it( 'break inside element - should break container element at given position', () => {
 			test(
 				'<container:div>' +
@@ -62,7 +66,7 @@ describe( 'writer', () => {
 			const { selection } = parse( '<container:div>foo{}bar</container:div>' );
 
 			expect( () => {
-				breakContainer( selection.getFirstPosition() );
+				writer.breakContainer( selection.getFirstPosition() );
 			} ).to.throw( CKEditorError, /view-writer-break-non-container-element/ );
 		} );
 
@@ -71,7 +75,7 @@ describe( 'writer', () => {
 			const position = Position.createAt( element, 0 );
 
 			expect( () => {
-				breakContainer( position );
+				writer.breakContainer( position );
 			} ).to.throw( CKEditorError, /view-writer-break-root/ );
 		} );
 	} );

+ 21 - 15
packages/ckeditor5-engine/tests/view/writer/clear.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { clear } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import Range from '../../../src/view/range';
 import { stringify, parse } from '../../../src/dev-utils/view';
 import ContainerElement from '../../../src/view/containerelement';
@@ -12,27 +12,33 @@ import EmptyElement from '../../../src/view/emptyelement';
 import UIElement from '../../../src/view/uielement';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
-describe( 'writer', () => {
-	// Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create ranges.
-	//
-	// @param {Object} elementToRemove
-	// @param {String} input
-	// @param {String} expectedResult
-	function test( elementToRemove, input, expectedResult ) {
-		const { view, selection } = parse( input );
+describe( 'Writer', () => {
+	describe( 'clear()', () => {
+		let writer;
 
-		clear( selection.getFirstRange(), elementToRemove );
+		// Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create ranges.
+		//
+		// @param {Object} elementToRemove
+		// @param {String} input
+		// @param {String} expectedResult
+		function test( elementToRemove, input, expectedResult ) {
+			const { view, selection } = parse( input );
 
-		expect( stringify( view, null, { showType: true } ) ).to.equal( expectedResult );
-	}
+			writer.clear( selection.getFirstRange(), elementToRemove );
+
+			expect( stringify( view, null, { showType: true } ) ).to.equal( expectedResult );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
 
-	describe( 'clear', () => {
 		it( 'should throw when range placed in two containers', () => {
 			const p1 = new ContainerElement( 'p' );
 			const p2 = new ContainerElement( 'p' );
 
 			expect( () => {
-				clear( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) );
+				writer.clear( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 
@@ -40,7 +46,7 @@ describe( 'writer', () => {
 			const el = new AttributeElement( 'b' );
 
 			expect( () => {
-				clear( Range.createFromParentsAndOffsets( el, 0, el, 0 ) );
+				writer.clear( Range.createFromParentsAndOffsets( el, 0, el, 0 ) );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 

+ 27 - 23
packages/ckeditor5-engine/tests/view/writer/insert.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { insert } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import ContainerElement from '../../../src/view/containerelement';
 import Element from '../../../src/view/element';
 import EmptyElement from '../../../src/view/emptyelement';
@@ -13,23 +13,27 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 import { stringify, parse } from '../../../src/dev-utils/view';
 import AttributeElement from '../../../src/view/attributeelement';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions.
-	 *
-	 * @param {String} input
-	 * @param {Array.<String>} nodesToInsert
-	 * @param {String} expected
-	 */
-	function test( input, nodesToInsert, expected ) {
-		nodesToInsert = nodesToInsert.map( node => parse( node ) );
-		const { view, selection } = parse( input );
-
-		const newRange = insert( selection.getFirstPosition(), nodesToInsert );
-		expect( stringify( view.root, newRange, { showType: true, showPriority: true } ) ).to.equal( expected );
-	}
-
-	describe( 'insert', () => {
+describe( 'Writer', () => {
+	describe( 'insert()', () => {
+		let writer;
+
+		// Executes test using `parse` and `stringify` utils functions.
+		//
+		// @param {String} input
+		// @param {Array.<String>} nodesToInsert
+		// @param {String} expected
+		function test( input, nodesToInsert, expected ) {
+			nodesToInsert = nodesToInsert.map( node => parse( node ) );
+			const { view, selection } = parse( input );
+
+			const newRange = writer.insert( selection.getFirstPosition(), nodesToInsert );
+			expect( stringify( view.root, newRange, { showType: true, showPriority: true } ) ).to.equal( expected );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		it( 'should return collapsed range in insertion position when using empty array', () => {
 			test(
 				'<container:p>foo{}bar</container:p>',
@@ -151,7 +155,7 @@ describe( 'writer', () => {
 			const container = new ContainerElement( 'p' );
 			const position = new Position( container, 0 );
 			expect( () => {
-				insert( position, element );
+				writer.insert( position, element );
 			} ).to.throw( CKEditorError, 'view-writer-insert-invalid-node' );
 		} );
 
@@ -162,7 +166,7 @@ describe( 'writer', () => {
 			const position = new Position( container, 0 );
 
 			expect( () => {
-				insert( position, root );
+				writer.insert( position, root );
 			} ).to.throw( CKEditorError, 'view-writer-insert-invalid-node' );
 		} );
 
@@ -172,7 +176,7 @@ describe( 'writer', () => {
 			const attributeElement = new AttributeElement( 'i' );
 
 			expect( () => {
-				insert( position, attributeElement );
+				writer.insert( position, attributeElement );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-position-container' );
 		} );
 
@@ -191,7 +195,7 @@ describe( 'writer', () => {
 			const attributeElement = new AttributeElement( 'i' );
 
 			expect( () => {
-				insert( position, attributeElement );
+				writer.insert( position, attributeElement );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-empty-element' );
 		} );
 
@@ -202,7 +206,7 @@ describe( 'writer', () => {
 			const attributeElement = new AttributeElement( 'i' );
 
 			expect( () => {
-				insert( position, attributeElement );
+				writer.insert( position, attributeElement );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-ui-element' );
 		} );
 	} );

+ 20 - 16
packages/ckeditor5-engine/tests/view/writer/mergeattributes.js

@@ -3,27 +3,31 @@
  * For licensing, see LICENSE.md.
  */
 
-import { mergeAttributes } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import ContainerElement from '../../../src/view/containerelement';
 import Text from '../../../src/view/text';
 import Position from '../../../src/view/position';
 import { stringify, parse } from '../../../src/dev-utils/view';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
-	 * test merge position.
-	 *
-	 * @param {String} input
-	 * @param {String} expected
-	 */
-	function test( input, expected ) {
-		const { view, selection } = parse( input );
-		const newPosition = mergeAttributes( selection.getFirstPosition() );
-		expect( stringify( view, newPosition, { showType: true, showPriority: true } ) ).to.equal( expected );
-	}
-
+describe( 'Writer', () => {
 	describe( 'mergeAttributes', () => {
+		let writer;
+
+		// Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
+		// test merge position.
+		//
+		// @param {String} input
+		// @param {String} expected
+		function test( input, expected ) {
+			const { view, selection } = parse( input );
+			const newPosition = writer.mergeAttributes( selection.getFirstPosition() );
+			expect( stringify( view, newPosition, { showType: true, showPriority: true } ) ).to.equal( expected );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		it( 'should not merge if inside text node', () => {
 			test( '<container:p>fo{}bar</container:p>', '<container:p>fo{}bar</container:p>' );
 		} );
@@ -63,7 +67,7 @@ describe( 'writer', () => {
 			const p = new ContainerElement( 'p', null, [ t1, t2 ] );
 			const position = new Position( p, 1 );
 
-			const newPosition = mergeAttributes( position );
+			const newPosition = writer.mergeAttributes( position );
 			expect( stringify( p, newPosition ) ).to.equal( '<p>foo{}bar</p>' );
 		} );
 

+ 25 - 21
packages/ckeditor5-engine/tests/view/writer/mergecontainers.js

@@ -3,26 +3,30 @@
  * For licensing, see LICENSE.md.
  */
 
-import { mergeContainers } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import { stringify, parse } from '../../../src/dev-utils/view';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
-	 * test break position.
-	 *
-	 * @param {String} input
-	 * @param {String} expected
-	 */
-	function test( input, expected ) {
-		const { view, selection } = parse( input );
-
-		const newPosition = mergeContainers( selection.getFirstPosition() );
-		expect( stringify( view.root, newPosition, { showType: true, showPriority: false } ) ).to.equal( expected );
-	}
-
-	describe( 'mergeContainers', () => {
+describe( 'Writer', () => {
+	describe( 'mergeContainers()', () => {
+		let writer;
+
+		// Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
+		// test break position.
+		//
+		// @param {String} input
+		// @param {String} expected
+		function test( input, expected ) {
+			const { view, selection } = parse( input );
+
+			const newPosition = writer.mergeContainers( selection.getFirstPosition() );
+			expect( stringify( view.root, newPosition, { showType: true, showPriority: false } ) ).to.equal( expected );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		it( 'should merge two container elements - position between elements', () => {
 			test(
 				'<container:div>' +
@@ -54,7 +58,7 @@ describe( 'writer', () => {
 			const { selection } = parse( '[]<container:div>foobar</container:div>' );
 
 			expect( () => {
-				mergeContainers( selection.getFirstPosition() );
+				writer.mergeContainers( selection.getFirstPosition() );
 			} ).to.throw( CKEditorError, /view-writer-merge-containers-invalid-position/ );
 		} );
 
@@ -62,7 +66,7 @@ describe( 'writer', () => {
 			const { selection } = parse( '<container:div>foobar</container:div>[]' );
 
 			expect( () => {
-				mergeContainers( selection.getFirstPosition() );
+				writer.mergeContainers( selection.getFirstPosition() );
 			} ).to.throw( CKEditorError, /view-writer-merge-containers-invalid-position/ );
 		} );
 
@@ -70,7 +74,7 @@ describe( 'writer', () => {
 			const { selection } = parse( '<attribute:u>foo</attribute:u>[]<container:div>bar</container:div>' );
 
 			expect( () => {
-				mergeContainers( selection.getFirstPosition() );
+				writer.mergeContainers( selection.getFirstPosition() );
 			} ).to.throw( CKEditorError, /view-writer-merge-containers-invalid-position/ );
 		} );
 
@@ -78,7 +82,7 @@ describe( 'writer', () => {
 			const { selection } = parse( '<container:div>foo</container:div>[]<attribute:u>bar</attribute:u>' );
 
 			expect( () => {
-				mergeContainers( selection.getFirstPosition() );
+				writer.mergeContainers( selection.getFirstPosition() );
 			} ).to.throw( CKEditorError, /view-writer-merge-containers-invalid-position/ );
 		} );
 	} );

+ 29 - 25
packages/ckeditor5-engine/tests/view/writer/move.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { move } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import { stringify, parse } from '../../../src/dev-utils/view';
 import ContainerElement from '../../../src/view/containerelement';
 import AttributeElement from '../../../src/view/attributeelement';
@@ -13,26 +13,30 @@ import Range from '../../../src/view/range';
 import Position from '../../../src/view/position';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
-	 * test ranges.
-	 *
-	 * @param {String} input
-	 * @param {String} expectedResult
-	 * @param {String} expectedRemoved
-	 */
-	function test( source, destination, sourceAfterMove, destinationAfterMove ) {
-		const { view: srcView, selection: srcSelection } = parse( source );
-		const { view: dstView, selection: dstSelection } = parse( destination );
-
-		const newRange = move( srcSelection.getFirstRange(), dstSelection.getFirstPosition() );
-
-		expect( stringify( dstView, newRange, { showType: true, showPriority: true } ) ).to.equal( destinationAfterMove );
-		expect( stringify( srcView, null, { showType: true, showPriority: true } ) ).to.equal( sourceAfterMove );
-	}
-
-	describe( 'move', () => {
+describe( 'Writer', () => {
+	describe( 'move()', () => {
+		let writer;
+
+		// Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
+		// test ranges.
+		//
+		// @param {String} input
+		// @param {String} expectedResult
+		// @param {String} expectedRemoved
+		function test( source, destination, sourceAfterMove, destinationAfterMove ) {
+			const { view: srcView, selection: srcSelection } = parse( source );
+			const { view: dstView, selection: dstSelection } = parse( destination );
+
+			const newRange = writer.move( srcSelection.getFirstRange(), dstSelection.getFirstPosition() );
+
+			expect( stringify( dstView, newRange, { showType: true, showPriority: true } ) ).to.equal( destinationAfterMove );
+			expect( stringify( srcView, null, { showType: true, showPriority: true } ) ).to.equal( sourceAfterMove );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		it( 'should move single text node', () => {
 			test(
 				'<container:p>[foobar]</container:p>',
@@ -111,7 +115,7 @@ describe( 'writer', () => {
 		it( 'should correctly move text nodes inside same parent', () => {
 			const { view, selection } = parse( '<container:p>[<attribute:b>a</attribute:b>]b<attribute:b>c</attribute:b></container:p>' );
 
-			const newRange = move( selection.getFirstRange(), Position.createAt( view, 2 ) );
+			const newRange = writer.move( selection.getFirstRange(), Position.createAt( view, 2 ) );
 
 			const expectedView = '<container:p>b[<attribute:b>a}c</attribute:b></container:p>';
 			expect( stringify( view, newRange, { showType: true } ) ).to.equal( expectedView );
@@ -123,7 +127,7 @@ describe( 'writer', () => {
 			);
 
 			const viewText = view.getChild( 3 );
-			const newRange = move( selection.getFirstRange(), Position.createAt( viewText, 1 ) );
+			const newRange = writer.move( selection.getFirstRange(), Position.createAt( viewText, 1 ) );
 
 			expect( stringify( view, newRange, { showType: true } ) ).to.equal(
 				'<container:p><attribute:b>ad</attribute:b>y[<attribute:b>b</attribute:b>xx<attribute:b>c</attribute:b>]y</container:p>'
@@ -149,7 +153,7 @@ describe( 'writer', () => {
 			const dstPosition = new Position( dstEmpty, 0 );
 
 			expect( () => {
-				move( srcRange, dstPosition );
+				writer.move( srcRange, dstPosition );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-empty-element' );
 		} );
 
@@ -172,7 +176,7 @@ describe( 'writer', () => {
 			const dstPosition = new Position( dstUI, 0 );
 
 			expect( () => {
-				move( srcRange, dstPosition );
+				writer.move( srcRange, dstPosition );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-ui-element' );
 		} );
 	} );

+ 29 - 25
packages/ckeditor5-engine/tests/view/writer/remove.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { remove } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import ContainerElement from '../../../src/view/containerelement';
 import Range from '../../../src/view/range';
 import DocumentFragment from '../../../src/view/documentfragment';
@@ -13,31 +13,35 @@ import EmptyElement from '../../../src/view/emptyelement';
 import UIElement from '../../../src/view/uielement';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
-	 * test ranges.
-	 *
-	 * @param {String} input
-	 * @param {String} expectedResult
-	 * @param {String} expectedRemoved
-	 */
-	function test( input, expectedResult, expectedRemoved ) {
-		const { view, selection } = parse( input );
-
-		const range = selection.getFirstRange();
-		const removed = remove( range );
-		expect( stringify( view, range, { showType: true, showPriority: true } ) ).to.equal( expectedResult );
-		expect( stringify( removed, null, { showType: true, showPriority: true } ) ).to.equal( expectedRemoved );
-	}
-
-	describe( 'remove', () => {
+describe( 'Writer', () => {
+	describe( 'remove()', () => {
+		let writer;
+
+		// Executes test using `parse` and `stringify` utils functions. Uses range delimiters `[]{}` to create and
+		// test ranges.
+		//
+		// @param {String} input
+		// @param {String} expectedResult
+		// @param {String} expectedRemoved
+		function test( input, expectedResult, expectedRemoved ) {
+			const { view, selection } = parse( input );
+
+			const range = selection.getFirstRange();
+			const removed = writer.remove( range );
+			expect( stringify( view, range, { showType: true, showPriority: true } ) ).to.equal( expectedResult );
+			expect( stringify( removed, null, { showType: true, showPriority: true } ) ).to.equal( expectedRemoved );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		it( 'should throw when range placed in two containers', () => {
 			const p1 = new ContainerElement( 'p' );
 			const p2 = new ContainerElement( 'p' );
 
 			expect( () => {
-				remove( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) );
+				writer.remove( Range.createFromParentsAndOffsets( p1, 0, p2, 0 ) );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 
@@ -45,14 +49,14 @@ describe( 'writer', () => {
 			const el = new AttributeElement( 'b' );
 
 			expect( () => {
-				remove( Range.createFromParentsAndOffsets( el, 0, el, 0 ) );
+				writer.remove( Range.createFromParentsAndOffsets( el, 0, el, 0 ) );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 
 		it( 'should return empty DocumentFragment when range is collapsed', () => {
 			const p = new ContainerElement( 'p' );
 			const range = Range.createFromParentsAndOffsets( p, 0, p, 0 );
-			const fragment = remove( range );
+			const fragment = writer.remove( range );
 
 			expect( fragment ).to.be.instanceof( DocumentFragment );
 			expect( fragment.childCount ).to.equal( 0 );
@@ -126,7 +130,7 @@ describe( 'writer', () => {
 			const range = Range.createFromParentsAndOffsets( emptyElement, 0, attributeElement, 0 );
 
 			expect( () => {
-				remove( range );
+				writer.remove( range );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-empty-element' );
 		} );
 
@@ -145,7 +149,7 @@ describe( 'writer', () => {
 			const range = Range.createFromParentsAndOffsets( uiElement, 0, attributeElement, 0 );
 
 			expect( () => {
-				remove( range );
+				writer.remove( range );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-ui-element' );
 		} );
 	} );

+ 10 - 6
packages/ckeditor5-engine/tests/view/writer/rename.js

@@ -3,12 +3,16 @@
  * For licensing, see LICENSE.md.
  */
 
-import { rename } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import { parse } from '../../../src/dev-utils/view';
 
-describe( 'writer', () => {
-	describe( 'rename', () => {
-		let root, foo;
+describe( 'Writer', () => {
+	describe( 'rename()', () => {
+		let root, foo, writer;
+
+		before( () => {
+			writer = new Writer();
+		} );
 
 		beforeEach( () => {
 			root = parse( '<container:div><container:foo foo="1">xxx</container:foo></container:div>' );
@@ -19,7 +23,7 @@ describe( 'writer', () => {
 		it( 'should rename given element by inserting a new element in the place of the old one', () => {
 			const text = foo.getChild( 0 );
 
-			rename( foo, 'bar' );
+			writer.rename( foo, 'bar' );
 
 			const bar = root.getChild( 0 );
 
@@ -30,7 +34,7 @@ describe( 'writer', () => {
 		} );
 
 		it( 'should return a reference to the inserted element', () => {
-			const bar = rename( foo, 'bar' );
+			const bar = writer.rename( foo, 'bar' );
 
 			expect( bar ).to.equal( root.getChild( 0 ) );
 		} );

+ 26 - 22
packages/ckeditor5-engine/tests/view/writer/unwrap.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { unwrap } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import Element from '../../../src/view/element';
 import ContainerElement from '../../../src/view/containerelement';
 import AttributeElement from '../../../src/view/attributeelement';
@@ -15,22 +15,26 @@ import Text from '../../../src/view/text';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 import { stringify, parse } from '../../../src/dev-utils/view';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions.
-	 *
-	 * @param {String} input
-	 * @param {String} unwrapAttribute
-	 * @param {String} expected
-	 */
-	function test( input, unwrapAttribute, expected ) {
-		const { view, selection } = parse( input );
-
-		const newRange = unwrap( selection.getFirstRange(), parse( unwrapAttribute ) );
-		expect( stringify( view.root, newRange, { showType: true, showPriority: true } ) ).to.equal( expected );
-	}
-
-	describe( 'unwrap', () => {
+describe( 'Writer', () => {
+	describe( 'unwrap()', () => {
+		let writer;
+
+		// Executes test using `parse` and `stringify` utils functions.
+		//
+		// @param {String} input
+		// @param {String} unwrapAttribute
+		// @param {String} expected
+		function test( input, unwrapAttribute, expected ) {
+			const { view, selection } = parse( input );
+
+			const newRange = writer.unwrap( selection.getFirstRange(), parse( unwrapAttribute ) );
+			expect( stringify( view.root, newRange, { showType: true, showPriority: true } ) ).to.equal( expected );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		it( 'should do nothing on collapsed ranges', () => {
 			test(
 				'<container:p>f{}oo</container:p>',
@@ -56,7 +60,7 @@ describe( 'writer', () => {
 			const b = new Element( 'b' );
 
 			expect( () => {
-				unwrap( range, b );
+				writer.unwrap( range, b );
 			} ).to.throw( CKEditorError, 'view-writer-unwrap-invalid-attribute' );
 		} );
 
@@ -70,7 +74,7 @@ describe( 'writer', () => {
 			const b = new AttributeElement( 'b' );
 
 			expect( () => {
-				unwrap( range, b );
+				writer.unwrap( range, b );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 
@@ -79,7 +83,7 @@ describe( 'writer', () => {
 			const b = new AttributeElement( 'b' );
 
 			expect( () => {
-				unwrap( Range.createFromParentsAndOffsets( el, 0, el, 0 ), b );
+				writer.unwrap( Range.createFromParentsAndOffsets( el, 0, el, 0 ), b );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 
@@ -345,7 +349,7 @@ describe( 'writer', () => {
 			const range = Range.createFromParentsAndOffsets( empty, 0, container, 2 );
 
 			expect( () => {
-				unwrap( range, attribute );
+				writer.unwrap( range, attribute );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-empty-element' );
 		} );
 
@@ -364,7 +368,7 @@ describe( 'writer', () => {
 			const range = Range.createFromParentsAndOffsets( uiElement, 0, container, 2 );
 
 			expect( () => {
-				unwrap( range, attribute );
+				writer.unwrap( range, attribute );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-ui-element' );
 		} );
 	} );

+ 28 - 22
packages/ckeditor5-engine/tests/view/writer/wrap.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { wrap } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import Element from '../../../src/view/element';
 import ContainerElement from '../../../src/view/containerelement';
 import AttributeElement from '../../../src/view/attributeelement';
@@ -15,22 +15,28 @@ import Text from '../../../src/view/text';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 import { stringify, parse } from '../../../src/dev-utils/view';
 
-describe( 'writer', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions.
-	 *
-	 * @param {String} input
-	 * @param {String} wrapAttribute
-	 * @param {String} expected
-	 */
-	function test( input, wrapAttribute, expected ) {
-		const { view, selection } = parse( input );
-		const newRange = wrap( selection.getFirstRange(), parse( wrapAttribute ) );
-
-		expect( stringify( view.root, newRange, { showType: true, showPriority: true } ) ).to.equal( expected );
-	}
-
-	describe( 'wrap', () => {
+describe( 'Writer', () => {
+	describe( 'wrap()', () => {
+		let writer;
+
+		/**
+		 * Executes test using `parse` and `stringify` utils functions.
+		 *
+		 * @param {String} input
+		 * @param {String} wrapAttribute
+		 * @param {String} expected
+		 */
+		function test( input, wrapAttribute, expected ) {
+			const { view, selection } = parse( input );
+			const newRange = writer.wrap( selection.getFirstRange(), parse( wrapAttribute ) );
+
+			expect( stringify( view.root, newRange, { showType: true, showPriority: true } ) ).to.equal( expected );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
 		it( 'should do nothing on collapsed ranges', () => {
 			test(
 				'<container:p>f{}oo</container:p>',
@@ -64,7 +70,7 @@ describe( 'writer', () => {
 			const b = new Element( 'b' );
 
 			expect( () => {
-				wrap( range, b );
+				writer.wrap( range, b );
 			} ).to.throw( CKEditorError, 'view-writer-wrap-invalid-attribute' );
 		} );
 
@@ -78,7 +84,7 @@ describe( 'writer', () => {
 			const b = new AttributeElement( 'b' );
 
 			expect( () => {
-				wrap( range, b );
+				writer.wrap( range, b );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 
@@ -87,7 +93,7 @@ describe( 'writer', () => {
 			const b = new AttributeElement( 'b' );
 
 			expect( () => {
-				wrap( Range.createFromParentsAndOffsets( el, 0, el, 0 ), b );
+				writer.wrap( Range.createFromParentsAndOffsets( el, 0, el, 0 ), b );
 			} ).to.throw( CKEditorError, 'view-writer-invalid-range-container' );
 		} );
 
@@ -324,7 +330,7 @@ describe( 'writer', () => {
 			const range = Range.createFromParentsAndOffsets( emptyElement, 0, container, 1 );
 
 			expect( () => {
-				wrap( range, new AttributeElement( 'b' ) );
+				writer.wrap( range, new AttributeElement( 'b' ) );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-empty-element' );
 		} );
 
@@ -342,7 +348,7 @@ describe( 'writer', () => {
 			const range = Range.createFromParentsAndOffsets( uiElement, 0, container, 1 );
 
 			expect( () => {
-				wrap( range, new AttributeElement( 'b' ) );
+				writer.wrap( range, new AttributeElement( 'b' ) );
 			} ).to.throw( CKEditorError, 'view-writer-cannot-break-ui-element' );
 		} );
 

+ 141 - 133
packages/ckeditor5-engine/tests/view/writer/wrapposition.js

@@ -3,7 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
-import { wrapPosition } from '../../../src/view/writer';
+import Writer from '../../../src/view/writer';
 import Text from '../../../src/view/text';
 import Element from '../../../src/view/element';
 import ContainerElement from '../../../src/view/containerelement';
@@ -14,137 +14,145 @@ import Position from '../../../src/view/position';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 import { stringify, parse } from '../../../src/dev-utils/view';
 
-describe( 'wrapPosition', () => {
-	/**
-	 * Executes test using `parse` and `stringify` utils functions.
-	 *
-	 * @param {String} input
-	 * @param {String} unwrapAttribute
-	 * @param {String} expected
-	 */
-	function test( input, unwrapAttribute, expected ) {
-		const { view, selection } = parse( input );
-
-		const newPosition = wrapPosition( selection.getFirstPosition(), parse( unwrapAttribute ) );
-		expect( stringify( view, newPosition, { showType: true, showPriority: true } ) ).to.equal( expected );
-	}
-
-	it( 'should throw error when element is not instance of AttributeElement', () => {
-		const container = new ContainerElement( 'p', null, new Text( 'foo' ) );
-		const position = new Position( container, 0 );
-		const b = new Element( 'b' );
-
-		expect( () => {
-			wrapPosition( position, b );
-		} ).to.throw( CKEditorError, 'view-writer-wrap-invalid-attribute' );
-	} );
-
-	it( 'should wrap position at the beginning of text node', () => {
-		test(
-			'<container:p>{}foobar</container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p><attribute:b view-priority="1">[]</attribute:b>foobar</container:p>'
-		);
-	} );
-
-	it( 'should wrap position inside text node', () => {
-		test(
-			'<container:p>foo{}bar</container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p>foo<attribute:b view-priority="1">[]</attribute:b>bar</container:p>'
-		);
-	} );
-
-	it( 'should support unicode', () => {
-		test(
-			'<container:p>நிலை{}க்கு</container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p>நிலை<attribute:b view-priority="1">[]</attribute:b>க்கு</container:p>'
-		);
-	} );
-
-	it( 'should wrap position inside document fragment', () => {
-		test(
-			'<attribute:b view-priority="1">foo</attribute:b>[]<attribute:b view-priority="3">bar</attribute:b>',
-			'<attribute:b view-priority="2"></attribute:b>',
-			'<attribute:b view-priority="1">foo</attribute:b><attribute:b view-priority="2">[]</attribute:b>' +
-			'<attribute:b view-priority="3">bar</attribute:b>'
-		);
-	} );
-
-	it( 'should wrap position at the end of text node', () => {
-		test(
-			'<container:p>foobar{}</container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p>foobar<attribute:b view-priority="1">[]</attribute:b></container:p>'
-		);
-	} );
-
-	it( 'should merge with existing attributes #1', () => {
-		test(
-			'<container:p><attribute:b view-priority="1">foo</attribute:b>[]</container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p><attribute:b view-priority="1">foo{}</attribute:b></container:p>'
-		);
-	} );
-
-	it( 'should merge with existing attributes #2', () => {
-		test(
-			'<container:p>[]<attribute:b view-priority="1">foo</attribute:b></container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p><attribute:b view-priority="1">{}foo</attribute:b></container:p>'
-		);
-	} );
-
-	it( 'should wrap when inside nested attributes', () => {
-		test(
-			'<container:p><attribute:b view-priority="1">foo{}bar</attribute:b></container:p>',
-			'<attribute:u view-priority="1"></attribute:u>',
-			'<container:p>' +
-				'<attribute:b view-priority="1">' +
-					'foo' +
-					'<attribute:u view-priority="1">[]</attribute:u>' +
-					'bar' +
-				'</attribute:b>' +
-			'</container:p>'
-		);
-	} );
-
-	it( 'should merge when wrapping between same attribute', () => {
-		test(
-			'<container:p><attribute:b view-priority="1">foo</attribute:b>[]<attribute:b view-priority="1">bar</attribute:b></container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p><attribute:b view-priority="1">foo{}bar</attribute:b></container:p>'
-		);
-	} );
-
-	it( 'should move position to text node if in same attribute', () => {
-		test(
-			'<container:p><attribute:b view-priority="1">foobar[]</attribute:b></container:p>',
-			'<attribute:b view-priority="1"></attribute:b>',
-			'<container:p><attribute:b view-priority="1">foobar{}</attribute:b></container:p>'
-		);
-	} );
-
-	it( 'should throw if position is set inside EmptyElement', () => {
-		const emptyElement = new EmptyElement( 'img' );
-		new ContainerElement( 'p', null, emptyElement ); // eslint-disable-line no-new
-		const attributeElement = new AttributeElement( 'b' );
-		const position = new Position( emptyElement, 0 );
-
-		expect( () => {
-			wrapPosition( position, attributeElement );
-		} ).to.throw( CKEditorError, 'view-emptyelement-cannot-add' );
-	} );
-
-	it( 'should throw if position is set inside UIElement', () => {
-		const uiElement = new UIElement( 'span' );
-		new ContainerElement( 'p', null, uiElement ); // eslint-disable-line no-new
-		const attributeElement = new AttributeElement( 'b' );
-		const position = new Position( uiElement, 0 );
-
-		expect( () => {
-			wrapPosition( position, attributeElement );
-		} ).to.throw( CKEditorError, 'view-uielement-cannot-add' );
+describe( 'Writer', () => {
+	describe( 'wrapPosition()', () => {
+		let writer;
+
+		// Executes test using `parse` and `stringify` utils functions.
+		//
+		// @param {String} input
+		// @param {String} unwrapAttribute
+		// @param {String} expected
+		function test( input, unwrapAttribute, expected ) {
+			const { view, selection } = parse( input );
+
+			const newPosition = writer.wrapPosition( selection.getFirstPosition(), parse( unwrapAttribute ) );
+			expect( stringify( view, newPosition, { showType: true, showPriority: true } ) ).to.equal( expected );
+		}
+
+		before( () => {
+			writer = new Writer();
+		} );
+
+		it( 'should throw error when element is not instance of AttributeElement', () => {
+			const container = new ContainerElement( 'p', null, new Text( 'foo' ) );
+			const position = new Position( container, 0 );
+			const b = new Element( 'b' );
+
+			expect( () => {
+				writer.wrapPosition( position, b );
+			} ).to.throw( CKEditorError, 'view-writer-wrap-invalid-attribute' );
+		} );
+
+		it( 'should wrap position at the beginning of text node', () => {
+			test(
+				'<container:p>{}foobar</container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p><attribute:b view-priority="1">[]</attribute:b>foobar</container:p>'
+			);
+		} );
+
+		it( 'should wrap position inside text node', () => {
+			test(
+				'<container:p>foo{}bar</container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p>foo<attribute:b view-priority="1">[]</attribute:b>bar</container:p>'
+			);
+		} );
+
+		it( 'should support unicode', () => {
+			test(
+				'<container:p>நிலை{}க்கு</container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p>நிலை<attribute:b view-priority="1">[]</attribute:b>க்கு</container:p>'
+			);
+		} );
+
+		it( 'should wrap position inside document fragment', () => {
+			test(
+				'<attribute:b view-priority="1">foo</attribute:b>[]<attribute:b view-priority="3">bar</attribute:b>',
+				'<attribute:b view-priority="2"></attribute:b>',
+				'<attribute:b view-priority="1">foo</attribute:b><attribute:b view-priority="2">[]</attribute:b>' +
+				'<attribute:b view-priority="3">bar</attribute:b>'
+			);
+		} );
+
+		it( 'should wrap position at the end of text node', () => {
+			test(
+				'<container:p>foobar{}</container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p>foobar<attribute:b view-priority="1">[]</attribute:b></container:p>'
+			);
+		} );
+
+		it( 'should merge with existing attributes #1', () => {
+			test(
+				'<container:p><attribute:b view-priority="1">foo</attribute:b>[]</container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p><attribute:b view-priority="1">foo{}</attribute:b></container:p>'
+			);
+		} );
+
+		it( 'should merge with existing attributes #2', () => {
+			test(
+				'<container:p>[]<attribute:b view-priority="1">foo</attribute:b></container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p><attribute:b view-priority="1">{}foo</attribute:b></container:p>'
+			);
+		} );
+
+		it( 'should wrap when inside nested attributes', () => {
+			test(
+				'<container:p><attribute:b view-priority="1">foo{}bar</attribute:b></container:p>',
+				'<attribute:u view-priority="1"></attribute:u>',
+				'<container:p>' +
+					'<attribute:b view-priority="1">' +
+						'foo' +
+						'<attribute:u view-priority="1">[]</attribute:u>' +
+						'bar' +
+					'</attribute:b>' +
+				'</container:p>'
+			);
+		} );
+
+		it( 'should merge when wrapping between same attribute', () => {
+			test(
+				'<container:p>' +
+					'<attribute:b view-priority="1">foo</attribute:b>[]<attribute:b view-priority="1">bar</attribute:b>' +
+				'</container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p><attribute:b view-priority="1">foo{}bar</attribute:b></container:p>'
+			);
+		} );
+
+		it( 'should move position to text node if in same attribute', () => {
+			test(
+				'<container:p><attribute:b view-priority="1">foobar[]</attribute:b></container:p>',
+				'<attribute:b view-priority="1"></attribute:b>',
+				'<container:p><attribute:b view-priority="1">foobar{}</attribute:b></container:p>'
+			);
+		} );
+
+		it( 'should throw if position is set inside EmptyElement', () => {
+			const emptyElement = new EmptyElement( 'img' );
+			new ContainerElement( 'p', null, emptyElement ); // eslint-disable-line no-new
+			const attributeElement = new AttributeElement( 'b' );
+			const position = new Position( emptyElement, 0 );
+
+			expect( () => {
+				writer.wrapPosition( position, attributeElement );
+			} ).to.throw( CKEditorError, 'view-emptyelement-cannot-add' );
+		} );
+
+		it( 'should throw if position is set inside UIElement', () => {
+			const uiElement = new UIElement( 'span' );
+			new ContainerElement( 'p', null, uiElement ); // eslint-disable-line no-new
+			const attributeElement = new AttributeElement( 'b' );
+			const position = new Position( uiElement, 0 );
+
+			expect( () => {
+				writer.wrapPosition( position, attributeElement );
+			} ).to.throw( CKEditorError, 'view-uielement-cannot-add' );
+		} );
 	} );
 } );