8
0
Pārlūkot izejas kodu

Merge pull request #553 from ckeditor/t/355

T/355 Implement useful range constructors
Piotr Jasiun 9 gadi atpakaļ
vecāks
revīzija
baa8ccc1b7

+ 2 - 2
packages/ckeditor5-engine/src/datacontroller.js

@@ -117,7 +117,7 @@ export default class DataController {
 	get( rootName = 'main' ) {
 		// Get model range.
 		const modelRoot = this.model.getRoot( rootName );
-		const modelRange = ModelRange.createFromElement( modelRoot );
+		const modelRange = ModelRange.createIn( modelRoot );
 
 		// model -> view
 		const viewDocumentFragment = new ViewDocumentFragment();
@@ -148,7 +148,7 @@ export default class DataController {
 		this.model.enqueueChanges( () => {
 			// Initial batch should be ignored by features like undo, etc.
 			this.model.batch( 'transparent' )
-				.remove( ModelRange.createFromElement( modelRoot ) )
+				.remove( ModelRange.createIn( modelRoot ) )
 				.insert( ModelPosition.createAt( modelRoot, 0 ), this.parse( data ) );
 		} );
 	}

+ 2 - 2
packages/ckeditor5-engine/src/model/liverange.js

@@ -38,9 +38,9 @@ export default class LiveRange extends Range {
 	}
 
 	/**
-	 * @see engine.model.Range.createFromElement
+	 * @see engine.model.Range.createIn
 	 * @static
-	 * @method engine.model.LiveRange.createFromElement
+	 * @method engine.model.LiveRange.createIn
 	 * @param {engine.model.Element} element
 	 * @returns {engine.model.LiveRange}
 	 */

+ 1 - 1
packages/ckeditor5-engine/src/model/liveselection.js

@@ -181,7 +181,7 @@ export default class LiveSelection extends Selection {
 		const defaultRoot = this._document._getDefaultRoot();
 
 		// Find the first position where the selection can be put.
-		for ( let position of Range.createFromElement( defaultRoot ).getPositions() ) {
+		for ( let position of Range.createIn( defaultRoot ).getPositions() ) {
 			if ( this._document.schema.check( { name: '$text', inside: position } ) ) {
 				return new Range( position, position );
 			}

+ 25 - 25
packages/ckeditor5-engine/src/model/range.js

@@ -19,9 +19,9 @@ export default class Range {
 	 * **Note:** Constructor creates it's own {@link engine.model.Position Position} instances basing on passed values.
 	 *
 	 * @param {engine.model.Position} start Start position.
-	 * @param {engine.model.Position} end End position.
+	 * @param {engine.model.Position} [end] End position. If not set, range will be collapsed at `start` position.
 	 */
-	constructor( start, end ) {
+	constructor( start, end = null ) {
 		/**
 		 * Start position.
 		 *
@@ -36,7 +36,7 @@ export default class Range {
 		 * @readonly
 		 * @member {engine.model.Position} engine.model.Range#end
 		 */
-		this.end = Position.createFromPosition( end );
+		this.end = end ? Position.createFromPosition( end ) : Position.createFromPosition( start );
 	}
 
 	/**
@@ -489,28 +489,6 @@ export default class Range {
 	}
 
 	/**
-	 * Creates a range inside an {@link engine.model.Element element} which starts before the first child of
-	 * that element and ends after the last child of that element.
-	 *
-	 * @param {engine.model.Element} element Element which is a parent for the range.
-	 * @returns {engine.model.Range}
-	 */
-	static createFromElement( element ) {
-		return this.createFromParentsAndOffsets( element, 0, element, element.maxOffset );
-	}
-
-	/**
-	 * Creates a range on given {@link engine.model.Element element} only. The range starts directly before that element
-	 * and ends before the first child of that element.
-	 *
-	 * @param {engine.model.Element} element Element on which range should be created.
-	 * @returns {engine.model.Range}
-	 */
-	static createOnElement( element ) {
-		return this.createFromParentsAndOffsets( element.parent, element.startOffset, element, 0 );
-	}
-
-	/**
 	 * Creates a new range, spreading from specified {@link engine.model.Position position} to a position moved by
 	 * given `shift`. If `shift` is a negative value, shifted position is treated as the beginning of the range.
 	 *
@@ -552,9 +530,31 @@ export default class Range {
 	}
 
 	/**
+	 * Creates a range inside an {@link engine.model.Element element} which starts before the first child of
+	 * that element and ends after the last child of that element.
+	 *
+	 * @param {engine.model.Element} element Element which is a parent for the range.
+	 * @returns {engine.model.Range}
+	 */
+	static createIn( element ) {
+		return this.createFromParentsAndOffsets( element, 0, element, element.maxOffset );
+	}
+
+	/**
+	 * Creates a range that starts before given {@link engine.model.Node node} and ends after it.
+	 *
+	 * @param {engine.model.Node} node
+	 * @returns {engine.model.Range}
+	 */
+	static createOn( node ) {
+		return this.createFromPositionAndShift( Position.createBefore( node ), node.offsetSize );
+	}
+
+	/**
 	 * Creates a `Range` instance from given plain object (i.e. parsed JSON string).
 	 *
 	 * @param {Object} json Plain object to be converted to `Range`.
+	 * @param {engine.model.Document} doc Document object that will be range owner.
 	 * @returns {engine.model.Element} `Range` instance created using given plain object.
 	 */
 	static fromJSON( json, doc ) {

+ 15 - 4
packages/ckeditor5-engine/src/view/range.js

@@ -14,12 +14,13 @@ import TreeWalker from './treewalker.js';
 export default class Range {
 	/**
 	 * Creates a range spanning from `start` position to `end` position.
+	 *
 	 * **Note:** Constructor creates it's own {@link engine.view.Position} instances basing on passed values.
 	 *
 	 * @param {engine.view.Position} start Start position.
-	 * @param {engine.view.Position} end End position.
+	 * @param {engine.view.Position} [end] End position. If not set, range will be collapsed at `start` position.
 	 */
-	constructor( start, end ) {
+	constructor( start, end = null ) {
 		/**
 		 * Start position.
 		 *
@@ -34,7 +35,7 @@ export default class Range {
 		 * @member engine.view.Range#end
 		 * @type {engine.view.Position}
 		 */
-		this.end = Position.createFromPosition( end );
+		this.end = end ? Position.createFromPosition( end ) : Position.createFromPosition( start );
 	}
 
 	/**
@@ -330,7 +331,17 @@ export default class Range {
 	 * @param {engine.view.Element} element Element which is a parent for the range.
 	 * @returns {engine.view.Range}
 	 */
-	static createFromElement( element ) {
+	static createIn( element ) {
 		return this.createFromParentsAndOffsets( element, 0, element, element.childCount );
 	}
+
+	/**
+	 * Creates a range that starts before given {@link engine.view.Node node} and ends after it.
+	 *
+	 * @param {engine.view.Node} node
+	 * @returns {engine.view.Range}
+	 */
+	static createOn( node ) {
+		return this.createFromPositionAndShift( Position.createBefore( node ), 1 );
+	}
 }

+ 3 - 3
packages/ckeditor5-engine/tests/_utils/model.js

@@ -74,7 +74,7 @@ export function setData( document, data, options = {} ) {
 
 	document.enqueueChanges( () => {
 		document.batch( options.batchType || 'transparent' )
-			.remove( Range.createFromElement( modelRoot ) )
+			.remove( Range.createIn( modelRoot ) )
 			.insert( Position.createAt( modelRoot, 0 ), model );
 
 		if ( selection ) {
@@ -124,12 +124,12 @@ export function stringify( node, selectionOrPositionOrRange = null ) {
 	let selection, range;
 
 	if ( node instanceof RootElement || node instanceof DocumentFragment ) {
-		range = Range.createFromElement( node );
+		range = Range.createIn( node );
 	} else {
 		// Node is detached - create new document fragment.
 		if ( !node.parent ) {
 			const fragment = new DocumentFragment( node );
-			range = Range.createFromElement( fragment );
+			range = Range.createIn( fragment );
 		} else {
 			range = new Range(
 				Position.createBefore( node ),

+ 17 - 15
packages/ckeditor5-engine/tests/conversion/advanced-converters.js

@@ -40,6 +40,8 @@ import {
 } from '/ckeditor5/engine/conversion/model-to-view-converters.js';
 import { convertToModelFragment, convertText } from '/ckeditor5/engine/conversion/view-to-model-converters.js';
 
+import { createRangeOnElementOnly } from '/tests/engine/model/_utils/utils.js';
+
 let modelDoc, modelRoot, viewRoot, mapper, modelDispatcher, viewDispatcher;
 
 beforeEach( () => {
@@ -112,7 +114,7 @@ function modelToString( item ) {
 
 		result = attributes ? '<$text' + attributes + '>' + item.data + '</$text>' : item.data;
 	} else {
-		let walker = new ModelWalker( { boundaries: ModelRange.createFromElement( item ), shallow: true } );
+		let walker = new ModelWalker( { boundaries: ModelRange.createIn( item ), shallow: true } );
 
 		for ( let value of walker ) {
 			result += modelToString( value.item );
@@ -252,14 +254,14 @@ describe( 'image with caption converters', () => {
 	it( 'should convert model images changes without caption to view', () => {
 		let modelElement = new ModelElement( 'image', { src: 'bar.jpg', title: 'bar' } );
 		modelRoot.appendChildren( modelElement );
-		modelDispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		modelDispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><img src="bar.jpg" title="bar"></img></div>' );
 
 		modelElement.setAttribute( 'src', 'new.jpg' );
 		modelElement.removeAttribute( 'title' );
-		modelDispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelElement ), 'src', 'bar.jpg', 'new.jpg' );
-		modelDispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'title', 'bar', null );
+		modelDispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelElement ), 'src', 'bar.jpg', 'new.jpg' );
+		modelDispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'title', 'bar', null );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><img src="new.jpg"></img></div>' );
 	} );
@@ -269,7 +271,7 @@ describe( 'image with caption converters', () => {
 			new ModelElement( 'caption', {}, new ModelText( 'foobar' ) )
 		] );
 		modelRoot.appendChildren( modelElement );
-		modelDispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		modelDispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal(
 			'<div><figure><img src="foo.jpg" title="foo"></img><figcaption>foobar</figcaption></figure></div>'
@@ -277,8 +279,8 @@ describe( 'image with caption converters', () => {
 
 		modelElement.setAttribute( 'src', 'new.jpg' );
 		modelElement.removeAttribute( 'title' );
-		modelDispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelElement ), 'src', 'bar.jpg', 'new.jpg' );
-		modelDispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'title', 'bar', null );
+		modelDispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelElement ), 'src', 'bar.jpg', 'new.jpg' );
+		modelDispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'title', 'bar', null );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><figure><img src="new.jpg"></img><figcaption>foobar</figcaption></figure></div>' );
 	} );
@@ -479,7 +481,7 @@ describe( 'custom attribute handling for given element', () => {
 		const modelText = new ModelText( 'foo', { linkHref: 'foo.html', linkTitle: 'Foo title' } );
 		modelRoot.appendChildren( modelText );
 
-		let range = ModelRange.createFromElement( modelRoot );
+		let range = ModelRange.createIn( modelRoot );
 
 		modelDispatcher.convertInsert( range );
 
@@ -497,12 +499,12 @@ describe( 'custom attribute handling for given element', () => {
 		modelDoc.graveyard.appendChildren( removed );
 		modelDispatcher.convertRemove(
 			ModelPosition.createFromParentAndOffset( modelRoot, 0 ),
-			ModelRange.createFromElement( modelDoc.graveyard )
+			ModelRange.createIn( modelDoc.graveyard )
 		);
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><a href="bar.html" title="Bar title">oo</a></div>' );
 
-		range = ModelRange.createFromElement( modelRoot );
+		range = ModelRange.createIn( modelRoot );
 
 		// Let's remove just one attribute.
 		modelWriter.removeAttribute( range, 'linkTitle' );
@@ -531,7 +533,7 @@ describe( 'custom attribute handling for given element', () => {
 	it( 'should convert quote model element with linkHref and linkTitle attribute to view', () => {
 		let modelElement = new ModelElement( 'quote', { linkHref: 'foo.html', linkTitle: 'Foo source' }, new ModelText( 'foo' ) );
 		modelRoot.appendChildren( modelElement );
-		modelDispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		modelDispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		let expected = '<div><blockquote>foo<a href="foo.html" title="Foo source">see source</a></blockquote></div>';
 		expect( viewToString( viewRoot ) ).to.equal( expected );
@@ -549,14 +551,14 @@ describe( 'custom attribute handling for given element', () => {
 		modelElement.removeAttribute( 'linkTitle' );
 		modelElement.setAttribute( 'linkHref', 'bar.html' );
 
-		modelDispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'linkTitle', 'Foo source', null );
-		modelDispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelElement ), 'linkHref', 'foo.html', 'bar.html' );
+		modelDispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'linkTitle', 'Foo source', null );
+		modelDispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelElement ), 'linkHref', 'foo.html', 'bar.html' );
 
 		expected = '<div><blockquote>foo<strong>bar</strong><a href="bar.html">see source</a></blockquote></div>';
 		expect( viewToString( viewRoot ) ).to.equal( expected );
 
 		modelElement.removeAttribute( 'linkHref' );
-		modelDispatcher.convertAttribute( 'removeAttribute', ModelRange.createFromElement( modelRoot ), 'linkHref', 'bar.html', null );
+		modelDispatcher.convertAttribute( 'removeAttribute', ModelRange.createIn( modelRoot ), 'linkHref', 'bar.html', null );
 
 		expected = '<div><blockquote>foo<strong>bar</strong></blockquote></div>';
 		expect( viewToString( viewRoot ) ).to.equal( expected );
@@ -716,7 +718,7 @@ describe( 'universal converter', () => {
 		] );
 
 		modelRoot.appendChildren( modelElement );
-		modelDispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		modelDispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal(
 			'<div>' +

+ 30 - 28
packages/ckeditor5-engine/tests/conversion/buildmodelconverter.js

@@ -34,6 +34,8 @@ import {
 	clearAttributes
 } from '/ckeditor5/engine/conversion/model-selection-to-view-converters.js';
 
+import { createRangeOnElementOnly } from '/tests/engine/model/_utils/utils.js';
+
 function viewAttributesToString( item ) {
 	let result = '';
 
@@ -97,7 +99,7 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'paragraph', null, new ModelText( 'foobar' ) );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 		} );
@@ -108,7 +110,7 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'image' );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><img></img></div>' );
 		} );
@@ -121,7 +123,7 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'header', { level: 2 }, new ModelText( 'foobar' ) );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><h2>foobar</h2></div>' );
 		} );
@@ -138,13 +140,13 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelText( 'foo', { bold: true } );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><strong>foo</strong></div>' );
 
-			modelWriter.removeAttribute( ModelRange.createFromElement( modelRoot ), 'bold' );
+			modelWriter.removeAttribute( ModelRange.createIn( modelRoot ), 'bold' );
 
-			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createFromElement( modelRoot ), 'bold', true, null );
+			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createIn( modelRoot ), 'bold', true, null );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div>foo</div>' );
 		} );
@@ -155,13 +157,13 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelText( 'foo', { bold: true } );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><strong>foo</strong></div>' );
 
-			modelWriter.removeAttribute( ModelRange.createFromElement( modelRoot ), 'bold' );
+			modelWriter.removeAttribute( ModelRange.createIn( modelRoot ), 'bold' );
 
-			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createFromElement( modelRoot ), 'bold', true, null );
+			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createIn( modelRoot ), 'bold', true, null );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div>foo</div>' );
 		} );
@@ -172,19 +174,19 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelText( 'foo', { italic: 'em' } );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><em>foo</em></div>' );
 
-			modelWriter.setAttribute( ModelRange.createFromElement( modelRoot ), 'italic', 'i' );
+			modelWriter.setAttribute( ModelRange.createIn( modelRoot ), 'italic', 'i' );
 
-			dispatcher.convertAttribute( 'changeAttribute', ModelRange.createFromElement( modelRoot ), 'italic', 'em', 'i' );
+			dispatcher.convertAttribute( 'changeAttribute', ModelRange.createIn( modelRoot ), 'italic', 'em', 'i' );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><i>foo</i></div>' );
 
-			modelWriter.removeAttribute( ModelRange.createFromElement( modelRoot ), 'italic' );
+			modelWriter.removeAttribute( ModelRange.createIn( modelRoot ), 'italic' );
 
-			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createFromElement( modelRoot ), 'italic', 'i', null );
+			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createIn( modelRoot ), 'italic', 'i', null );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div>foo</div>' );
 		} );
@@ -205,7 +207,7 @@ describe( 'Model converter builder', () => {
 			modelDoc.selection._updateAttributes();
 
 			// Convert stuff.
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 			dispatcher.convertSelection( modelDoc.selection );
 
 			// Check if view structure is ok.
@@ -264,17 +266,17 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'paragraph', { class: 'myClass' }, new ModelText( 'foobar' ) );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="myClass">foobar</p></div>' );
 
 			modelElement.setAttribute( 'class', 'newClass' );
-			dispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelElement ), 'class', 'myClass', 'newClass' );
+			dispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelElement ), 'class', 'myClass', 'newClass' );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="newClass">foobar</p></div>' );
 
 			modelElement.removeAttribute( 'class' );
-			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'class', 'newClass', null );
+			dispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'class', 'newClass', null );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 		} );
@@ -285,17 +287,17 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'paragraph', { theme: 'abc' }, new ModelText( 'foobar' ) );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="abc">foobar</p></div>' );
 
 			modelElement.setAttribute( 'theme', 'xyz' );
-			dispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelElement ), 'theme', 'abc', 'xyz' );
+			dispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelElement ), 'theme', 'abc', 'xyz' );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="xyz">foobar</p></div>' );
 
 			modelElement.removeAttribute( 'theme' );
-			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'theme', 'xyz', null );
+			dispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'theme', 'xyz', null );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 		} );
@@ -306,12 +308,12 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'paragraph', { 'highlighted': true }, new ModelText( 'foobar' ) );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p style="background:yellow;">foobar</p></div>' );
 
 			modelElement.removeAttribute( 'highlighted' );
-			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'highlighted', true, null );
+			dispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'highlighted', true, null );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 		} );
@@ -324,17 +326,17 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'paragraph', { theme: 'nice' }, new ModelText( 'foobar' ) );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="nice-theme">foobar</p></div>' );
 
 			modelElement.setAttribute( 'theme', 'good' );
-			dispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelElement ), 'theme', 'nice', 'good' );
+			dispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelElement ), 'theme', 'nice', 'good' );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p class="good-theme">foobar</p></div>' );
 
 			modelElement.removeAttribute( 'theme' );
-			dispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'theme', 'good', null );
+			dispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'theme', 'good', null );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 		} );
@@ -348,7 +350,7 @@ describe( 'Model converter builder', () => {
 			let modelElement = new ModelElement( 'custom', null, new ModelText( 'foobar' ) );
 			modelRoot.appendChildren( modelElement );
 
-			dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+			dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 			expect( viewToString( viewRoot ) ).to.equal( '<div><other>foobar</other></div>' );
 		} );
@@ -364,7 +366,7 @@ describe( 'Model converter builder', () => {
 		let modelElement = new ModelElement( 'div', null, new ModelElement( 'paragraph', null, new ModelText( 'foobar' ) ) );
 		modelRoot.appendChildren( modelElement );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><div><p>foobar</p></div></div>' );
 	} );

+ 1 - 1
packages/ckeditor5-engine/tests/conversion/buildviewconverter.js

@@ -42,7 +42,7 @@ function modelToString( item ) {
 
 		result = attributes ? '<$text' + attributes + '>' + item.data + '</$text>' : item.data;
 	} else {
-		let walker = new ModelWalker( { boundaries: ModelRange.createFromElement( item ), shallow: true } );
+		let walker = new ModelWalker( { boundaries: ModelRange.createIn( item ), shallow: true } );
 
 		for ( let value of walker ) {
 			result += modelToString( value.item );

+ 1 - 1
packages/ckeditor5-engine/tests/conversion/model-selection-to-view-converters.js

@@ -498,7 +498,7 @@ function test( selectionPaths, modelInput, expectedView, selectionAttributes = {
 	viewRoot.removeChildren( 0, viewRoot.childCount );
 
 	// Convert model to view.
-	dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+	dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 	dispatcher.convertSelection( modelSelection );
 
 	// Stringify view and check if it is same as expected.

+ 22 - 20
packages/ckeditor5-engine/tests/conversion/model-to-view-converters.js

@@ -30,6 +30,8 @@ import {
 	remove
 } from '/ckeditor5/engine/conversion/model-to-view-converters.js';
 
+import { createRangeOnElementOnly } from '/tests/engine/model/_utils/utils.js';
+
 let dispatcher, modelDoc, modelRoot, mapper, viewRoot;
 
 beforeEach( () => {
@@ -81,7 +83,7 @@ describe( 'insertText', () => {
 		modelRoot.appendChildren( new ModelText( 'foobar' ) );
 		dispatcher.on( 'insert:$text', insertText() );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div>foobar</div>' );
 	} );
@@ -105,7 +107,7 @@ describe( 'insertElement', () => {
 		dispatcher.on( 'insert:paragraph', insertElement( viewElement ) );
 		dispatcher.on( 'insert:$text', insertText() );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 	} );
@@ -126,7 +128,7 @@ describe( 'insertElement', () => {
 		dispatcher.on( 'insert:myParagraph', insertElement( elementGenerator ) );
 		dispatcher.on( 'insert:$text', insertText() );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><div>foo</div><p>bar</p></div>' );
 	} );
@@ -144,17 +146,17 @@ describe( 'setAttribute/removeAttribute', () => {
 		dispatcher.on( 'changeAttribute:class', setAttribute() );
 		dispatcher.on( 'removeAttribute:class', removeAttribute() );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="foo">foobar</p></div>' );
 
 		modelElement.setAttribute( 'class', 'bar' );
-		dispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelElement ), 'class', 'foo', 'bar' );
+		dispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelElement ), 'class', 'foo', 'bar' );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="bar">foobar</p></div>' );
 
 		modelElement.removeAttribute( 'class' );
-		dispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelElement ), 'class', 'bar', null );
+		dispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelElement ), 'class', 'bar', null );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 	} );
@@ -179,17 +181,17 @@ describe( 'setAttribute/removeAttribute', () => {
 		dispatcher.on( 'changeAttribute:theme', setAttribute( themeConverter ) );
 		dispatcher.on( 'removeAttribute:theme', removeAttribute( themeConverter ) );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="nice fix-content">foobar</p><div class="nice"></div></div>' );
 
 		modelParagraph.setAttribute( 'theme', 'awesome' );
-		dispatcher.convertAttribute( 'changeAttribute', ModelRange.createOnElement( modelParagraph ), 'theme', 'nice', 'awesome' );
+		dispatcher.convertAttribute( 'changeAttribute', createRangeOnElementOnly( modelParagraph ), 'theme', 'nice', 'awesome' );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p class="awesome fix-content">foobar</p><div class="nice"></div></div>' );
 
 		modelParagraph.removeAttribute( 'theme' );
-		dispatcher.convertAttribute( 'removeAttribute', ModelRange.createOnElement( modelParagraph ), 'theme', 'awesome', null );
+		dispatcher.convertAttribute( 'removeAttribute', createRangeOnElementOnly( modelParagraph ), 'theme', 'awesome', null );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p><div class="nice"></div></div>' );
 	} );
@@ -207,13 +209,13 @@ describe( 'wrap/unwrap', () => {
 		dispatcher.on( 'addAttribute:bold', wrap( viewB ) );
 		dispatcher.on( 'removeAttribute:bold', unwrap( viewB ) );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p><b>foobar</b></p></div>' );
 
-		modelWriter.removeAttribute( ModelRange.createFromElement( modelElement ), 'bold' );
+		modelWriter.removeAttribute( ModelRange.createIn( modelElement ), 'bold' );
 
-		dispatcher.convertAttribute( 'removeAttribute', ModelRange.createFromElement( modelElement ), 'bold', true, null );
+		dispatcher.convertAttribute( 'removeAttribute', ModelRange.createIn( modelElement ), 'bold', true, null );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 	} );
@@ -234,13 +236,13 @@ describe( 'wrap/unwrap', () => {
 		dispatcher.on( 'addAttribute:style', wrap( elementGenerator ) );
 		dispatcher.on( 'removeAttribute:style', unwrap( elementGenerator ) );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p><b>foobar</b></p></div>' );
 
-		modelWriter.removeAttribute( ModelRange.createFromElement( modelElement ), 'style' );
+		modelWriter.removeAttribute( ModelRange.createIn( modelElement ), 'style' );
 
-		dispatcher.convertAttribute( 'removeAttribute', ModelRange.createFromElement( modelElement ), 'style', 'bold', null );
+		dispatcher.convertAttribute( 'removeAttribute', ModelRange.createIn( modelElement ), 'style', 'bold', null );
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
 	} );
@@ -263,16 +265,16 @@ describe( 'wrap/unwrap', () => {
 		dispatcher.on( 'changeAttribute:link', wrap( elementGenerator ) );
 
 		dispatcher.convertInsert(
-			ModelRange.createFromElement( modelRoot )
+			ModelRange.createIn( modelRoot )
 		);
 
 		expect( viewToString( viewRoot ) ).to.equal( '<div><p>x<a href="http://foo.com">foo</a>x</p></div>' );
 
-		modelWriter.setAttribute( ModelRange.createFromElement( modelElement ), 'link', 'http://foobar.com' );
+		modelWriter.setAttribute( ModelRange.createIn( modelElement ), 'link', 'http://foobar.com' );
 
 		dispatcher.convertAttribute(
 			'changeAttribute',
-			ModelRange.createFromElement( modelElement ),
+			ModelRange.createIn( modelElement ),
 			'link',
 			'http://foo.com',
 			'http://foobar.com'
@@ -320,7 +322,7 @@ describe( 'move', () => {
 		dispatcher.on( 'insert:$text', insertText() );
 		dispatcher.on( 'move', move() );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		const removedNodes = modelDivA.removeChildren( 0, 2 );
 		modelDivB.insertChildren( 0, removedNodes );
@@ -372,7 +374,7 @@ describe( 'remove', () => {
 		dispatcher.on( 'insert:$text', insertText() );
 		dispatcher.on( 'remove', remove() );
 
-		dispatcher.convertInsert( ModelRange.createFromElement( modelRoot ) );
+		dispatcher.convertInsert( ModelRange.createIn( modelRoot ) );
 
 		const removedNodes = modelDiv.removeChildren( 0, 2 );
 		modelDoc.graveyard.insertChildren( 0, removedNodes );

+ 7 - 7
packages/ckeditor5-engine/tests/conversion/modelconversiondispatcher.js

@@ -202,7 +202,7 @@ describe( 'ModelConversionDispatcher', () => {
 				new ModelElement( 'paragraph', { class: 'nice' }, new ModelText( 'xx', { italic: true } ) )
 			] );
 
-			const range = ModelRange.createFromElement( root );
+			const range = ModelRange.createIn( root );
 			const loggedEvents = [];
 
 			// We will check everything connected with insert event:
@@ -262,7 +262,7 @@ describe( 'ModelConversionDispatcher', () => {
 				consumable.consume( data.item, 'addAttribute:bold' );
 			} );
 
-			const range = ModelRange.createFromElement( root );
+			const range = ModelRange.createIn( root );
 
 			dispatcher.convertInsert( range );
 
@@ -321,7 +321,7 @@ describe( 'ModelConversionDispatcher', () => {
 				new ModelElement( 'paragraph', { bold: true, class: 'nice' }, new ModelText( 'xx', { bold: true, italic: true } ) )
 			] );
 
-			const range = ModelRange.createFromElement( root );
+			const range = ModelRange.createIn( root );
 			const loggedEvents = [];
 
 			dispatcher.on( 'addAttribute', ( evt, data, consumable ) => {
@@ -357,7 +357,7 @@ describe( 'ModelConversionDispatcher', () => {
 				consumable.consume( data.item.getChild( 0 ), 'removeAttribute:attr' );
 			} );
 
-			const range = ModelRange.createFromElement( root );
+			const range = ModelRange.createIn( root );
 
 			dispatcher.convertAttribute( 'removeAttribute', range, 'attr', 'value', null );
 
@@ -391,7 +391,7 @@ describe( 'ModelConversionDispatcher', () => {
 		it( 'should prepare correct list of consumable values', () => {
 			doc.enqueueChanges( () => {
 				doc.batch()
-					.setAttribute( ModelRange.createFromElement( root ), 'bold', true )
+					.setAttribute( ModelRange.createIn( root ), 'bold', true )
 					.setAttribute( ModelRange.createFromParentsAndOffsets( root, 4, root, 5 ), 'italic', true );
 			} );
 
@@ -409,7 +409,7 @@ describe( 'ModelConversionDispatcher', () => {
 
 			doc.enqueueChanges( () => {
 				doc.batch()
-					.setAttribute( ModelRange.createFromElement( root ), 'bold', true )
+					.setAttribute( ModelRange.createIn( root ), 'bold', true )
 					.setAttribute( ModelRange.createFromParentsAndOffsets( root, 4, root, 5 ), 'italic', true );
 			} );
 
@@ -428,7 +428,7 @@ describe( 'ModelConversionDispatcher', () => {
 
 			doc.enqueueChanges( () => {
 				doc.batch()
-					.setAttribute( ModelRange.createFromElement( root ), 'bold', true )
+					.setAttribute( ModelRange.createIn( root ), 'bold', true )
 					.setAttribute( ModelRange.createFromParentsAndOffsets( root, 4, root, 5 ), 'italic', true );
 			} );
 

+ 12 - 0
packages/ckeditor5-engine/tests/model/_utils/utils.js

@@ -3,6 +3,7 @@
  * For licensing, see LICENSE.md.
  */
 
+import Range from '/ckeditor5/engine/model/range.js';
 import TreeWalker from '/ckeditor5/engine/model/treewalker.js';
 import Text from '/ckeditor5/engine/model/text.js';
 import TextProxy from '/ckeditor5/engine/model/textproxy.js';
@@ -100,3 +101,14 @@ export function getText( element ) {
 
 	return text;
 }
+
+/**
+ * Creates a range on given {@link engine.model.Element element} only. The range starts directly before that element
+ * and ends before the first child of that element.
+ *
+ * @param {engine.model.Element} element Element on which range should be created.
+ * @returns {engine.model.Range}
+ */
+export function createRangeOnElementOnly( element ) {
+	return Range.createFromParentsAndOffsets( element.parent, element.startOffset, element, 0 );
+}

+ 1 - 1
packages/ckeditor5-engine/tests/model/delta/attributedelta.js

@@ -165,7 +165,7 @@ describe( 'Batch', () => {
 
 		function getCompressedAttrs() {
 			// default: 111---111222---1112------
-			const range = Range.createFromElement( root );
+			const range = Range.createIn( root );
 
 			return Array.from( range.getItems( { singleCharacters: true } ) )
 				.map( item => item.getAttribute( 'a' ) || '-' )

+ 4 - 4
packages/ckeditor5-engine/tests/model/delta/movedelta.js

@@ -39,16 +39,16 @@ describe( 'Batch', () => {
 			batch.move( div, new Position( root, [ 2 ] ) );
 
 			expect( root.maxOffset ).to.equal( 2 );
-			expect( getNodesAndText( Range.createFromElement( root.getChild( 0 ) ) ) ).to.equal( 'abcxyz' );
-			expect( getNodesAndText( Range.createFromElement( root.getChild( 1 ) ) ) ).to.equal( 'PggggPfoobarPhhhhP' );
+			expect( getNodesAndText( Range.createIn( root.getChild( 0 ) ) ) ).to.equal( 'abcxyz' );
+			expect( getNodesAndText( Range.createIn( root.getChild( 1 ) ) ) ).to.equal( 'PggggPfoobarPhhhhP' );
 		} );
 
 		it( 'should move flat range of nodes', () => {
 			let range = new Range( new Position( root, [ 0, 3 ] ), new Position( root, [ 0, 7 ] ) );
 			batch.move( range, new Position( root, [ 1, 3 ] ) );
 
-			expect( getNodesAndText( Range.createFromElement( root.getChild( 0 ) ) ) ).to.equal( 'PggggPfoPhhhhP' );
-			expect( getNodesAndText( Range.createFromElement( root.getChild( 1 ) ) ) ).to.equal( 'abcobarxyz' );
+			expect( getNodesAndText( Range.createIn( root.getChild( 0 ) ) ) ).to.equal( 'PggggPfoPhhhhP' );
+			expect( getNodesAndText( Range.createIn( root.getChild( 1 ) ) ) ).to.equal( 'abcobarxyz' );
 		} );
 
 		it( 'should throw if given range is not flat', () => {

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

@@ -41,14 +41,14 @@ describe( 'Batch', () => {
 
 			expect( root.maxOffset ).to.equal( 1 );
 			expect( root.childCount ).to.equal( 1 );
-			expect( getNodesAndText( Range.createFromElement( root.getChild( 0 ) ) ) ).to.equal( 'abcxyz' );
+			expect( getNodesAndText( Range.createIn( root.getChild( 0 ) ) ) ).to.equal( 'abcxyz' );
 		} );
 
 		it( 'should remove any range of nodes', () => {
 			batch.remove( range );
 
-			expect( getNodesAndText( Range.createFromElement( root.getChild( 0 ) ) ) ).to.equal( 'PggParPhhhhP' );
-			expect( getNodesAndText( Range.createFromElement( root.getChild( 1 ) ) ) ).to.equal( 'abcxyz' );
+			expect( getNodesAndText( Range.createIn( root.getChild( 0 ) ) ) ).to.equal( 'PggParPhhhhP' );
+			expect( getNodesAndText( Range.createIn( root.getChild( 1 ) ) ) ).to.equal( 'abcxyz' );
 		} );
 
 		it( 'should create minimal number of operations when removing a range', () => {

+ 2 - 2
packages/ckeditor5-engine/tests/model/liverange.js

@@ -65,8 +65,8 @@ describe( 'LiveRange', () => {
 		LiveRange.prototype.stopListening.restore();
 	} );
 
-	it( 'createFromElement should return LiveRange', () => {
-		let range = LiveRange.createFromElement( p );
+	it( 'createIn should return LiveRange', () => {
+		let range = LiveRange.createIn( p );
 		expect( range ).to.be.instanceof( LiveRange );
 		range.detach();
 	} );

+ 12 - 5
packages/ckeditor5-engine/tests/model/range.js

@@ -32,6 +32,13 @@ describe( 'Range', () => {
 			expect( range.start.isEqual( start ) ).to.be.true;
 			expect( range.end.isEqual( end ) ).to.be.true;
 		} );
+
+		it( 'should create collapsed range', () => {
+			const collapsed = new Range( start );
+
+			expect( collapsed.start.isEqual( start ) ).to.be.true;
+			expect( collapsed.isCollapsed ).to.be.true;
+		} );
 	} );
 
 	describe( 'root', () => {
@@ -140,21 +147,21 @@ describe( 'Range', () => {
 			root.insertChildren( 0, [ p ] );
 		} );
 
-		describe( 'createFromElement', () => {
+		describe( 'createIn', () => {
 			it( 'should return range', () => {
-				const range = Range.createFromElement( p );
+				const range = Range.createIn( p );
 
 				expect( range.start.path ).to.deep.equal( [ 0, 0 ] );
 				expect( range.end.path ).to.deep.equal( [ 0, 3 ] );
 			} );
 		} );
 
-		describe( 'createOnElement', () => {
+		describe( 'createOn', () => {
 			it( 'should return range', () => {
-				const range = Range.createOnElement( p );
+				const range = Range.createOn( p );
 
 				expect( range.start.path ).to.deep.equal( [ 0 ] );
-				expect( range.end.path ).to.deep.equal( [ 0, 0 ] );
+				expect( range.end.path ).to.deep.equal( [ 1 ] );
 			} );
 		} );
 

+ 15 - 2
packages/ckeditor5-engine/tests/model/utils-tests/utils.js

@@ -8,7 +8,8 @@ import {
 	jsonParseStringify,
 	wrapInDelta,
 	itemAt,
-	getText
+	getText,
+	createRangeOnElementOnly
 } from '/tests/engine/model/_utils/utils.js';
 import Document from '/ckeditor5/engine/model/document.js';
 import Range from '/ckeditor5/engine/model/range.js';
@@ -33,7 +34,7 @@ describe( 'getNodesAndText', () => {
 	} );
 
 	it( 'reads two elements with text', () => {
-		expect( getNodesAndText( Range.createFromElement( root ) ) ).to.equal( 'DIVfoobarDIVPabcxyzP' );
+		expect( getNodesAndText( Range.createIn( root ) ) ).to.equal( 'DIVfoobarDIVPabcxyzP' );
 	} );
 } );
 
@@ -112,3 +113,15 @@ describe( 'getText', () => {
 		expect( getText( div ) ).to.equal( 'aaa bbbcccddd' );
 	} );
 } );
+
+describe( 'createRangeOnElementOnly', () => {
+	it( 'should create a range that contains only the given element', () => {
+		const parent = new Element( 'parent' );
+		const element = new Element( 'elem' );
+		parent.appendChildren( element );
+
+		const range = createRangeOnElementOnly( element );
+
+		expect( Array.from( range.getItems() ) ).to.deep.equal( [ element ] );
+	} );
+} );

+ 21 - 2
packages/ckeditor5-engine/tests/view/range.js

@@ -34,6 +34,14 @@ describe( 'Range', () => {
 			expect( range.start.offset ).to.equal( start.offset );
 			expect( range.end.offset ).to.equal( end.offset );
 		} );
+
+		it( 'creates collapsed range', () => {
+			const start = new Position( {}, 1 );
+			const range = new Range( start );
+
+			expect( range.start.isEqual( start ) ).to.be.true;
+			expect( range.isCollapsed ).to.be.true;
+		} );
 	} );
 
 	describe( 'iterator', () => {
@@ -490,9 +498,9 @@ describe( 'Range', () => {
 			div = new Element( 'div', null, p );
 		} );
 
-		describe( 'createFromElement', () => {
+		describe( 'createIn', () => {
 			it( 'should return range', () => {
-				const range = Range.createFromElement( p );
+				const range = Range.createIn( p );
 
 				expect( range.start.parent ).to.deep.equal( p );
 				expect( range.start.offset ).to.deep.equal( 0 );
@@ -501,6 +509,17 @@ describe( 'Range', () => {
 			} );
 		} );
 
+		describe( 'createOn', () => {
+			it( 'should return range', () => {
+				const range = Range.createOn( p );
+
+				expect( range.start.parent ).to.equal( div );
+				expect( range.start.offset ).to.equal( 0 );
+				expect( range.end.parent ).to.equal( div );
+				expect( range.end.offset ).to.equal( 1 );
+			} );
+		} );
+
 		describe( 'createFromParentsAndOffsets', () => {
 			it( 'should return range', () => {
 				const range = Range.createFromParentsAndOffsets( div, 0, foz, 1 );