Преглед на файлове

Renamed BaseCreator to Creator and Creator to StandardCreator.

Piotrek Koszuliński преди 9 години
родител
ревизия
db62156d84

+ 0 - 26
src/creator/basecreator.js

@@ -1,26 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-import Plugin from '../plugin.js';
-
-/**
- * Base creator class.
- *
- * @memberOf ckeditor5.creator
- * @extends ckeditor5.Plugin
- */
-export default class BaseCreator extends Plugin {
-	/**
-	 * The creator's trigger. This method is called by the editor to finalize
-	 * the editor creation.
-	 *
-	 * @returns {Promise}
-	 */
-	create() {
-		return Promise.resolve();
-	}
-}

+ 9 - 144
src/creator/creator.js

@@ -5,157 +5,22 @@
 
 'use strict';
 
-import BaseCreator from './basecreator.js';
-
-import Document from '../engine/treemodel/document.js';
-import DataController from '../engine/treecontroller/datacontroller.js';
-import EditingController from '../engine/treecontroller/editingcontroller.js';
+import Plugin from '../plugin.js';
 
 /**
- * Basic creator class for browser environment.
+ * Base creator class.
  *
  * @memberOf ckeditor5.creator
- * @extends ckeditor5.creator.BaseCreator
+ * @extends ckeditor5.Plugin
  */
-export default class Creator extends BaseCreator {
-	constructor( editor, dataProcessor ) {
-		super( editor );
-
-		editor.document = new Document();
-		editor.editing = new EditingController( editor.document );
-		editor.data = new DataController( editor.document, dataProcessor );
-
-		/**
-		 * The elements replaced by {@link ckeditor5.creator.Creator#_replaceElement} and their replacements.
-		 *
-		 * @private
-		 * @member {Array.<Object>} ckeditor5.creator.Creator#_replacedElements
-		 */
-		this._replacedElements = [];
-	}
-
-	destroy() {
-		const editor = this.editor;
-
-		super.destroy();
-
-		editor.document.destroy();
-		editor.editing.destroy();
-		editor.data.destroy();
-
-		this._restoreElements();
-	}
-
+export default class Creator extends Plugin {
 	/**
-	 * Updates the {@link ckeditor5.Editor#element editor element}'s content with the data.
+	 * The creator's trigger. This method is called by the editor to finalize
+	 * the editor creation.
 	 *
-	 * @param [elementName] If not specified, the first element will be used.
+	 * @returns {Promise}
 	 */
-	updateEditorElement( elementName ) {
-		if ( !elementName ) {
-			elementName = this.editor.firstElementName;
-		}
-
-		Creator.setDataInElement( this.editor.elements.get( elementName ), this.editor.getData( elementName ) );
-	}
-
-	/**
-	 * Updates all {@link ckeditor5.Editor#element editor elements} content with the data taken from
-	 * their corresponding editables.
-	 */
-	updateEditorElements() {
-		this.editor.elements.forEach( ( editorElement, elementName ) => {
-			this.updateEditorElement( elementName );
-		} );
-	}
-
-	/**
-	 * Loads the data from the given {@link ckeditor5.Editor#element editor element} to the editable.
-	 *
-	 * @param [elementName] If not specified, the first element will be used.
-	 */
-	loadDataFromEditorElement( elementName ) {
-		if ( !elementName ) {
-			elementName = this.editor.firstElementName;
-		}
-
-		this.editor.setData( Creator.getDataFromElement( this.editor.elements.get( elementName ) ), elementName );
-	}
-
-	/**
-	 * Loads the data from all {@link ckeditor5.Editor#element editor elements} to their corresponding editables.
-	 */
-	loadDataFromEditorElements() {
-		this.editor.elements.forEach( ( editorElement, elementName ) => {
-			this.loadDataFromEditorElement( elementName );
-		} );
-	}
-
-	/**
-	 * Gets data from a given source element.
-	 *
-	 * @param {HTMLElement} el The element from which the data will be retrieved.
-	 * @returns {String} The data string.
-	 */
-	static getDataFromElement( el ) {
-		if ( el instanceof HTMLTextAreaElement ) {
-			return el.value;
-		}
-
-		return el.innerHTML;
-	}
-
-	/**
-	 * Sets data in a given element.
-	 *
-	 * @param {HTMLElement} el The element in which the data will be set.
-	 * @param {String} data The data string.
-	 */
-	static setDataInElement( el, data ) {
-		if ( el instanceof HTMLTextAreaElement ) {
-			el.value = data;
-		}
-
-		el.innerHTML = data;
-	}
-
-	/**
-	 * Hides one of the {@link ckeditor5.Editor#elements editor elements} and, if specified, inserts the the given element
-	 * (e.g. the editor's UI main element) next to it.
-	 *
-	 * The effect of this method will be automatically reverted by {@link ckeditor5.creator.Creator#destroy destroy}.
-	 *
-	 * The second argument may not be passed and then the element will be replaced by nothing, so in other words it will
-	 * be hidden.
-	 *
-	 * @protected
-	 * @param {HTMLElement} element The element to replace.
-	 * @param {HTMLElement} [newElement] The replacement element. If not passed, then the `element` will just be hidden.
-	 */
-	_replaceElement( element, newElement ) {
-		this._replacedElements.push( { element, newElement } );
-
-		element.style.display = 'none';
-
-		if ( newElement ) {
-			element.parentNode.insertBefore( newElement, element.nextSibling );
-		}
-	}
-
-	/**
-	 * Restores what the {@link ckeditor5.creator.Creator#_replaceElement _replaceElement} did.
-	 *
-	 * @protected
-	 */
-	_restoreElements() {
-		this._replacedElements.forEach( ( { element, newElement } ) => {
-			element.style.display = '';
-
-			if ( newElement ) {
-				newElement.remove();
-			}
-		} );
-
-		this._replacedElements = [];
+	create() {
+		return Promise.resolve();
 	}
 }

+ 161 - 0
src/creator/standardcreator.js

@@ -0,0 +1,161 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import Creator from './creator.js';
+
+import Document from '../engine/treemodel/document.js';
+import DataController from '../engine/treecontroller/datacontroller.js';
+import EditingController from '../engine/treecontroller/editingcontroller.js';
+
+/**
+ * Standard creator for browser environment.
+ *
+ * @memberOf ckeditor5.creator
+ * @extends ckeditor5.creator.Creator
+ */
+export default class StandardCreator extends Creator {
+	constructor( editor, dataProcessor ) {
+		super( editor );
+
+		editor.document = new Document();
+		editor.editing = new EditingController( editor.document );
+		editor.data = new DataController( editor.document, dataProcessor );
+
+		/**
+		 * The elements replaced by {@link ckeditor5.creator.StandardCreator#_replaceElement} and their replacements.
+		 *
+		 * @private
+		 * @member {Array.<Object>} ckeditor5.creator.StandardCreator#_replacedElements
+		 */
+		this._replacedElements = [];
+	}
+
+	destroy() {
+		const editor = this.editor;
+
+		super.destroy();
+
+		editor.document.destroy();
+		editor.editing.destroy();
+		editor.data.destroy();
+
+		this._restoreElements();
+	}
+
+	/**
+	 * Updates the {@link ckeditor5.Editor#element editor element}'s content with the data.
+	 *
+	 * @param [elementName] If not specified, the first element will be used.
+	 */
+	updateEditorElement( elementName ) {
+		if ( !elementName ) {
+			elementName = this.editor.firstElementName;
+		}
+
+		StandardCreator.setDataInElement( this.editor.elements.get( elementName ), this.editor.getData( elementName ) );
+	}
+
+	/**
+	 * Updates all {@link ckeditor5.Editor#element editor elements} content with the data taken from
+	 * their corresponding editables.
+	 */
+	updateEditorElements() {
+		this.editor.elements.forEach( ( editorElement, elementName ) => {
+			this.updateEditorElement( elementName );
+		} );
+	}
+
+	/**
+	 * Loads the data from the given {@link ckeditor5.Editor#element editor element} to the editable.
+	 *
+	 * @param [elementName] If not specified, the first element will be used.
+	 */
+	loadDataFromEditorElement( elementName ) {
+		if ( !elementName ) {
+			elementName = this.editor.firstElementName;
+		}
+
+		this.editor.setData( StandardCreator.getDataFromElement( this.editor.elements.get( elementName ) ), elementName );
+	}
+
+	/**
+	 * Loads the data from all {@link ckeditor5.Editor#element editor elements} to their corresponding editables.
+	 */
+	loadDataFromEditorElements() {
+		this.editor.elements.forEach( ( editorElement, elementName ) => {
+			this.loadDataFromEditorElement( elementName );
+		} );
+	}
+
+	/**
+	 * Gets data from a given source element.
+	 *
+	 * @param {HTMLElement} el The element from which the data will be retrieved.
+	 * @returns {String} The data string.
+	 */
+	static getDataFromElement( el ) {
+		if ( el instanceof HTMLTextAreaElement ) {
+			return el.value;
+		}
+
+		return el.innerHTML;
+	}
+
+	/**
+	 * Sets data in a given element.
+	 *
+	 * @param {HTMLElement} el The element in which the data will be set.
+	 * @param {String} data The data string.
+	 */
+	static setDataInElement( el, data ) {
+		if ( el instanceof HTMLTextAreaElement ) {
+			el.value = data;
+		}
+
+		el.innerHTML = data;
+	}
+
+	/**
+	 * Hides one of the {@link ckeditor5.Editor#elements editor elements} and, if specified, inserts the the given element
+	 * (e.g. the editor's UI main element) next to it.
+	 *
+	 * The effect of this method will be automatically reverted by {@link ckeditor5.creator.StandardCreator#destroy destroy}.
+	 *
+	 * The second argument may not be passed and then the element will be replaced by nothing, so in other words it will
+	 * be hidden.
+	 *
+	 * @protected
+	 * @param {HTMLElement} element The element to replace.
+	 * @param {HTMLElement} [newElement] The replacement element. If not passed, then the `element` will just be hidden.
+	 */
+	_replaceElement( element, newElement ) {
+		this._replacedElements.push( { element, newElement } );
+
+		element.style.display = 'none';
+
+		if ( newElement ) {
+			element.parentNode.insertBefore( newElement, element.nextSibling );
+		}
+	}
+
+	/**
+	 * Restores what the {@link ckeditor5.creator.StandardCreator#_replaceElement _replaceElement} did.
+	 *
+	 * @protected
+	 */
+	_restoreElements() {
+		this._replacedElements.forEach( ( { element, newElement } ) => {
+			element.style.display = '';
+
+			if ( newElement ) {
+				newElement.remove();
+			}
+		} );
+
+		this._replacedElements = [];
+	}
+}

+ 4 - 4
src/editor.js

@@ -101,7 +101,7 @@ export default class Editor {
 		/**
 		 * Tree Model document managed by this editor.
 		 *
-		 * This property is set by the {@link ckeditor5.Creator}.
+		 * This property is set by the {@link ckeditor5.creator.Creator}.
 		 *
 		 * @readonly
 		 * @member {engine.treeModel.Document} ckeditor5.Editor#document
@@ -110,7 +110,7 @@ export default class Editor {
 		/**
 		 * Instance of the {@link engine.treecontroller.EditingController editing controller}.
 		 *
-		 * This property is set by the {@link ckeditor5.Creator}.
+		 * This property is set by the {@link ckeditor5.creator.Creator}.
 		 *
 		 * @readonly
 		 * @member {engine.treecontroller.EditingController} ckeditor5.Editor#editing
@@ -119,7 +119,7 @@ export default class Editor {
 		/**
 		 * Instance of the {@link engine.treecontroller.DataController data controller}.
 		 *
-		 * This property is set by the {@link ckeditor5.Creator}.
+		 * This property is set by the {@link ckeditor5.creator.Creator}.
 		 *
 		 * @readonly
 		 * @member {engine.treecontroller.DataController} ckeditor5.Editor#data
@@ -129,7 +129,7 @@ export default class Editor {
 		 * The chosen creator.
 		 *
 		 * @protected
-		 * @member {ckeditor5.Creator} ckeditor5.Editor#_creator
+		 * @member {ckeditor5.creator.Creator} ckeditor5.Editor#_creator
 		 */
 	}
 

+ 0 - 36
tests/creator/basecreator.js

@@ -1,36 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* bender-tags: creator */
-
-'use strict';
-
-import testUtils from '/tests/ckeditor5/_utils/utils.js';
-import BaseCreator from '/ckeditor5/creator/basecreator.js';
-import Plugin from '/ckeditor5/plugin.js';
-import Editor from '/ckeditor5/editor.js';
-
-testUtils.createSinonSandbox();
-
-describe( 'BaseCreator', () => {
-	let creator, editor;
-
-	beforeEach( () => {
-		editor = new Editor();
-		creator = new BaseCreator( editor );
-	} );
-
-	describe( 'constructor', () => {
-		it( 'inherits from the Plugin', () => {
-			expect( creator ).to.be.instanceof( Plugin );
-		} );
-	} );
-
-	describe( 'create', () => {
-		it( 'returns a promise', () => {
-			expect( creator.create() ).to.be.instanceof( Promise );
-		} );
-	} );
-} );

+ 5 - 197
tests/creator/creator.js

@@ -8,13 +8,9 @@
 'use strict';
 
 import testUtils from '/tests/ckeditor5/_utils/utils.js';
-import BaseCreator from '/ckeditor5/creator/basecreator.js';
 import Creator from '/ckeditor5/creator/creator.js';
+import Plugin from '/ckeditor5/plugin.js';
 import Editor from '/ckeditor5/editor.js';
-import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
-import Document from '/ckeditor5/engine/treemodel/document.js';
-import EditingController from '/ckeditor5/engine/treecontroller/editingcontroller.js';
-import DataController from '/ckeditor5/engine/treecontroller/datacontroller.js';
 
 testUtils.createSinonSandbox();
 
@@ -22,26 +18,13 @@ describe( 'Creator', () => {
 	let creator, editor;
 
 	beforeEach( () => {
-		const firstElement = document.createElement( 'div' );
-		document.body.appendChild( firstElement );
-
-		const secondElement = document.createElement( 'div' );
-		document.body.appendChild( secondElement );
-
-		editor = new Editor( { first: firstElement, second: secondElement } );
-		creator = new Creator( editor, new HtmlDataProcessor() );
+		editor = new Editor();
+		creator = new Creator( editor );
 	} );
 
 	describe( 'constructor', () => {
-		it( 'inherits from the BaseCreator', () => {
-			expect( creator ).to.be.instanceof( BaseCreator );
-		} );
-
-		it( 'creates the engine', () => {
-			expect( editor.document ).to.be.instanceof( Document );
-			expect( editor.editing ).to.be.instanceof( EditingController );
-			expect( editor.data ).to.be.instanceof( DataController );
-			expect( editor.data.processor ).to.be.instanceof( HtmlDataProcessor );
+		it( 'inherits from the Plugin', () => {
+			expect( creator ).to.be.instanceof( Plugin );
 		} );
 	} );
 
@@ -50,179 +33,4 @@ describe( 'Creator', () => {
 			expect( creator.create() ).to.be.instanceof( Promise );
 		} );
 	} );
-
-	describe( 'destroy', () => {
-		it( 'calls super.destroy', () => {
-			const baseCreatorSpy = testUtils.sinon.spy( BaseCreator.prototype, 'destroy' );
-
-			creator.destroy();
-
-			expect( baseCreatorSpy.called ).to.be.true;
-		} );
-
-		it( 'should destroy the engine', () => {
-			const spy = editor.document.destroy = editor.data.destroy = editor.editing.destroy = sinon.spy();
-
-			creator.destroy();
-
-			expect( spy.callCount ).to.equal( 3 );
-		} );
-
-		it( 'should restore the replaced element', () => {
-			const spy = testUtils.sinon.stub( creator, '_restoreElements' );
-
-			creator.destroy();
-
-			expect( spy.calledOnce ).to.be.true;
-		} );
-	} );
-
-	describe( 'updateEditorElement', () => {
-		it( 'should pass data to the first element when element name not specified', () => {
-			editor.getData = ( rootName ) => {
-				expect( rootName ).to.equal( 'first' );
-
-				return 'foo';
-			};
-
-			creator.updateEditorElement();
-
-			expect( editor.firstElement.innerHTML ).to.equal( 'foo' );
-		} );
-
-		it( 'should pass data to the given element', () => {
-			editor.elements.set( 'second', document.createElement( 'div' ) );
-
-			editor.getData = ( rootName ) => {
-				expect( rootName ).to.equal( 'second' );
-
-				return 'foo';
-			};
-
-			creator.updateEditorElement( 'second' );
-
-			expect( editor.elements.get( 'second' ).innerHTML ).to.equal( 'foo' );
-		} );
-	} );
-
-	describe( 'updateEditorElements', () => {
-		it( 'updates all editor elements', () => {
-			const spy = sinon.stub( creator, 'updateEditorElement' );
-
-			creator.updateEditorElements();
-
-			expect( spy.calledTwice ).to.be.true;
-			expect( spy.calledWith( 'first' ) ).to.be.true;
-			expect( spy.calledWith( 'second' ) ).to.be.true;
-		} );
-	} );
-
-	describe( 'loadDataFromEditorElement', () => {
-		it( 'should pass data to the first element', () => {
-			editor.setData = sinon.spy();
-
-			editor.elements.get( 'first' ).innerHTML = 'foo';
-			creator.loadDataFromEditorElement();
-
-			expect( editor.setData.calledWithExactly( 'foo', 'first' ) ).to.be.true;
-		} );
-
-		it( 'should pass data to the given element', () => {
-			const element = document.createElement( 'div' );
-			element.innerHTML = 'foo';
-
-			editor.elements.set( 'second', element );
-
-			editor.setData = sinon.spy();
-
-			creator.loadDataFromEditorElement( 'second' );
-
-			expect( editor.setData.calledWithExactly( 'foo', 'second' ) ).to.be.true;
-		} );
-	} );
-
-	describe( 'loadDataFromEditorElements', () => {
-		it( 'updates all editor elements', () => {
-			const spy = sinon.stub( creator, 'loadDataFromEditorElement' );
-
-			creator.loadDataFromEditorElements();
-
-			expect( spy.calledTwice ).to.be.true;
-			expect( spy.calledWith( 'first' ) ).to.be.true;
-			expect( spy.calledWith( 'second' ) ).to.be.true;
-		} );
-	} );
-
-	describe( 'getDataFromElement', () => {
-		[ 'textarea', 'template', 'div' ].forEach( ( elementName ) => {
-			it( 'should return the content of a ' + elementName, function() {
-				const data = Creator.getDataFromElement( document.getElementById( 'getData-' + elementName ) );
-				expect( data ).to.equal( '<b>foo</b>' );
-			} );
-		} );
-	} );
-
-	describe( 'setDataInElement', () => {
-		[ 'textarea', 'template', 'div' ].forEach( ( elementName ) => {
-			it( 'should set the content of a ' + elementName, () => {
-				const el = document.createElement( elementName );
-				const expectedData = '<b>foo</b>';
-
-				Creator.setDataInElement( el, expectedData );
-
-				const actualData = Creator.getDataFromElement( el );
-				expect( actualData ).to.equal( actualData );
-			} );
-		} );
-	} );
-
-	describe( '_replaceElement', () => {
-		it( 'should hide the element', () => {
-			const el = editor.elements.get( 'first' );
-
-			creator._replaceElement( el );
-
-			expect( el.style.display ).to.equal( 'none' );
-		} );
-
-		it( 'should inserts the replacement next to the element being hidden', () => {
-			const el = editor.elements.get( 'first' );
-			const replacement = document.createElement( 'div' );
-
-			creator._replaceElement( el, replacement );
-
-			expect( el.nextSibling ).to.equal( replacement );
-		} );
-	} );
-
-	describe( '_restoreElements', () => {
-		it( 'should restore all elements', () => {
-			const el1 = editor.elements.get( 'first' );
-			const replacement1 = document.createElement( 'div' );
-			const el2 = editor.elements.get( 'second' );
-			const replacement2 = document.createElement( 'div' );
-
-			creator._replaceElement( el1, replacement1 );
-			creator._replaceElement( el2, replacement2 );
-
-			creator._restoreElements();
-
-			expect( replacement1.parentNode ).to.be.null;
-			expect( replacement2.parentNode ).to.be.null;
-			expect( el2.style.display ).to.not.equal( 'none' );
-		} );
-
-		it( 'should not try to remove replacement elements', () => {
-			const el1 = editor.elements.get( 'first' );
-			const el2 = editor.elements.get( 'second' );
-
-			creator._replaceElement( el1 );
-			creator._replaceElement( el2 );
-
-			creator._restoreElements();
-
-			expect( el1.style.display ).to.not.equal( 'none' );
-			expect( el2.style.display ).to.not.equal( 'none' );
-		} );
-	} );
 } );

+ 2 - 2
tests/creator/manual/_utils/creator/classiccreator.js

@@ -5,7 +5,7 @@
 
 'use strict';
 
-import Creator from '/ckeditor5/creator/creator.js';
+import StandardCreator from '/ckeditor5/creator/standardcreator.js';
 
 import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
 import Editable from '/ckeditor5/editable.js';
@@ -22,7 +22,7 @@ import ToolbarView from '/ckeditor5/ui/toolbar/toolbarview.js';
 
 import { imitateFeatures, imitateDestroyFeatures } from '../imitatefeatures.js';
 
-export default class ClassicCreator extends Creator {
+export default class ClassicCreator extends StandardCreator {
 	constructor( editor ) {
 		super( editor, new HtmlDataProcessor() );
 

+ 2 - 2
tests/creator/manual/_utils/creator/inlinecreator.js

@@ -5,7 +5,7 @@
 
 'use strict';
 
-import Creator from '/ckeditor5/creator/creator.js';
+import StandardCreator from '/ckeditor5/creator/standardcreator.js';
 
 import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
 import Editable from '/ckeditor5/editable.js';
@@ -21,7 +21,7 @@ import FloatingToolbar from '/tests/ckeditor5/_utils/ui/floatingtoolbar/floating
 import FloatingToolbarView from '/tests/ckeditor5/_utils/ui/floatingtoolbar/floatingtoolbarview.js';
 import { imitateFeatures, imitateDestroyFeatures } from '../imitatefeatures.js';
 
-export default class InlineCreator extends Creator {
+export default class InlineCreator extends StandardCreator {
 	constructor( editor ) {
 		super( editor, new HtmlDataProcessor() );
 

+ 2 - 2
tests/creator/manual/_utils/creator/multicreator.js

@@ -5,7 +5,7 @@
 
 'use strict';
 
-import Creator from '/ckeditor5/creator/creator.js';
+import StandardCreator from '/ckeditor5/creator/standardcreator.js';
 
 import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
 import Editable from '/ckeditor5/editable.js';
@@ -21,7 +21,7 @@ import Toolbar from '/ckeditor5/ui/bindings/toolbar.js';
 import ToolbarView from '/ckeditor5/ui/toolbar/toolbarview.js';
 import { imitateFeatures, imitateDestroyFeatures } from '../imitatefeatures.js';
 
-export default class MultiCreator extends Creator {
+export default class MultiCreator extends StandardCreator {
 	constructor( editor ) {
 		super( editor, new HtmlDataProcessor() );
 

tests/creator/creator.html → tests/creator/standardcreator.html


+ 228 - 0
tests/creator/standardcreator.js

@@ -0,0 +1,228 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* bender-tags: creator */
+
+'use strict';
+
+import testUtils from '/tests/ckeditor5/_utils/utils.js';
+import Creator from '/ckeditor5/creator/creator.js';
+import StandardCreator from '/ckeditor5/creator/standardcreator.js';
+import Editor from '/ckeditor5/editor.js';
+import HtmlDataProcessor from '/ckeditor5/engine/dataprocessor/htmldataprocessor.js';
+import Document from '/ckeditor5/engine/treemodel/document.js';
+import EditingController from '/ckeditor5/engine/treecontroller/editingcontroller.js';
+import DataController from '/ckeditor5/engine/treecontroller/datacontroller.js';
+
+testUtils.createSinonSandbox();
+
+describe( 'Creator', () => {
+	let creator, editor;
+
+	beforeEach( () => {
+		const firstElement = document.createElement( 'div' );
+		document.body.appendChild( firstElement );
+
+		const secondElement = document.createElement( 'div' );
+		document.body.appendChild( secondElement );
+
+		editor = new Editor( { first: firstElement, second: secondElement } );
+		creator = new StandardCreator( editor, new HtmlDataProcessor() );
+	} );
+
+	describe( 'constructor', () => {
+		it( 'inherits from the Creator', () => {
+			expect( creator ).to.be.instanceof( Creator );
+		} );
+
+		it( 'creates the engine', () => {
+			expect( editor.document ).to.be.instanceof( Document );
+			expect( editor.editing ).to.be.instanceof( EditingController );
+			expect( editor.data ).to.be.instanceof( DataController );
+			expect( editor.data.processor ).to.be.instanceof( HtmlDataProcessor );
+		} );
+	} );
+
+	describe( 'create', () => {
+		it( 'returns a promise', () => {
+			expect( creator.create() ).to.be.instanceof( Promise );
+		} );
+	} );
+
+	describe( 'destroy', () => {
+		it( 'calls super.destroy', () => {
+			const creatorSpy = testUtils.sinon.spy( Creator.prototype, 'destroy' );
+
+			creator.destroy();
+
+			expect( creatorSpy.called ).to.be.true;
+		} );
+
+		it( 'should destroy the engine', () => {
+			const spy = editor.document.destroy = editor.data.destroy = editor.editing.destroy = sinon.spy();
+
+			creator.destroy();
+
+			expect( spy.callCount ).to.equal( 3 );
+		} );
+
+		it( 'should restore the replaced element', () => {
+			const spy = testUtils.sinon.stub( creator, '_restoreElements' );
+
+			creator.destroy();
+
+			expect( spy.calledOnce ).to.be.true;
+		} );
+	} );
+
+	describe( 'updateEditorElement', () => {
+		it( 'should pass data to the first element when element name not specified', () => {
+			editor.getData = ( rootName ) => {
+				expect( rootName ).to.equal( 'first' );
+
+				return 'foo';
+			};
+
+			creator.updateEditorElement();
+
+			expect( editor.firstElement.innerHTML ).to.equal( 'foo' );
+		} );
+
+		it( 'should pass data to the given element', () => {
+			editor.elements.set( 'second', document.createElement( 'div' ) );
+
+			editor.getData = ( rootName ) => {
+				expect( rootName ).to.equal( 'second' );
+
+				return 'foo';
+			};
+
+			creator.updateEditorElement( 'second' );
+
+			expect( editor.elements.get( 'second' ).innerHTML ).to.equal( 'foo' );
+		} );
+	} );
+
+	describe( 'updateEditorElements', () => {
+		it( 'updates all editor elements', () => {
+			const spy = sinon.stub( creator, 'updateEditorElement' );
+
+			creator.updateEditorElements();
+
+			expect( spy.calledTwice ).to.be.true;
+			expect( spy.calledWith( 'first' ) ).to.be.true;
+			expect( spy.calledWith( 'second' ) ).to.be.true;
+		} );
+	} );
+
+	describe( 'loadDataFromEditorElement', () => {
+		it( 'should pass data to the first element', () => {
+			editor.setData = sinon.spy();
+
+			editor.elements.get( 'first' ).innerHTML = 'foo';
+			creator.loadDataFromEditorElement();
+
+			expect( editor.setData.calledWithExactly( 'foo', 'first' ) ).to.be.true;
+		} );
+
+		it( 'should pass data to the given element', () => {
+			const element = document.createElement( 'div' );
+			element.innerHTML = 'foo';
+
+			editor.elements.set( 'second', element );
+
+			editor.setData = sinon.spy();
+
+			creator.loadDataFromEditorElement( 'second' );
+
+			expect( editor.setData.calledWithExactly( 'foo', 'second' ) ).to.be.true;
+		} );
+	} );
+
+	describe( 'loadDataFromEditorElements', () => {
+		it( 'updates all editor elements', () => {
+			const spy = sinon.stub( creator, 'loadDataFromEditorElement' );
+
+			creator.loadDataFromEditorElements();
+
+			expect( spy.calledTwice ).to.be.true;
+			expect( spy.calledWith( 'first' ) ).to.be.true;
+			expect( spy.calledWith( 'second' ) ).to.be.true;
+		} );
+	} );
+
+	describe( 'getDataFromElement', () => {
+		[ 'textarea', 'template', 'div' ].forEach( ( elementName ) => {
+			it( 'should return the content of a ' + elementName, function() {
+				const data = StandardCreator.getDataFromElement( document.getElementById( 'getData-' + elementName ) );
+				expect( data ).to.equal( '<b>foo</b>' );
+			} );
+		} );
+	} );
+
+	describe( 'setDataInElement', () => {
+		[ 'textarea', 'template', 'div' ].forEach( ( elementName ) => {
+			it( 'should set the content of a ' + elementName, () => {
+				const el = document.createElement( elementName );
+				const expectedData = '<b>foo</b>';
+
+				StandardCreator.setDataInElement( el, expectedData );
+
+				const actualData = StandardCreator.getDataFromElement( el );
+				expect( actualData ).to.equal( actualData );
+			} );
+		} );
+	} );
+
+	describe( '_replaceElement', () => {
+		it( 'should hide the element', () => {
+			const el = editor.elements.get( 'first' );
+
+			creator._replaceElement( el );
+
+			expect( el.style.display ).to.equal( 'none' );
+		} );
+
+		it( 'should inserts the replacement next to the element being hidden', () => {
+			const el = editor.elements.get( 'first' );
+			const replacement = document.createElement( 'div' );
+
+			creator._replaceElement( el, replacement );
+
+			expect( el.nextSibling ).to.equal( replacement );
+		} );
+	} );
+
+	describe( '_restoreElements', () => {
+		it( 'should restore all elements', () => {
+			const el1 = editor.elements.get( 'first' );
+			const replacement1 = document.createElement( 'div' );
+			const el2 = editor.elements.get( 'second' );
+			const replacement2 = document.createElement( 'div' );
+
+			creator._replaceElement( el1, replacement1 );
+			creator._replaceElement( el2, replacement2 );
+
+			creator._restoreElements();
+
+			expect( replacement1.parentNode ).to.be.null;
+			expect( replacement2.parentNode ).to.be.null;
+			expect( el2.style.display ).to.not.equal( 'none' );
+		} );
+
+		it( 'should not try to remove replacement elements', () => {
+			const el1 = editor.elements.get( 'first' );
+			const el2 = editor.elements.get( 'second' );
+
+			creator._replaceElement( el1 );
+			creator._replaceElement( el2 );
+
+			creator._restoreElements();
+
+			expect( el1.style.display ).to.not.equal( 'none' );
+			expect( el2.style.display ).to.not.equal( 'none' );
+		} );
+	} );
+} );