|
|
@@ -3,6 +3,8 @@
|
|
|
* For licensing, see LICENSE.md.
|
|
|
*/
|
|
|
|
|
|
+/* globals document */
|
|
|
+
|
|
|
import DecoupledEditorUI from '../src/decouplededitorui';
|
|
|
import DecoupledEditorUIView from '../src/decouplededitoruiview';
|
|
|
|
|
|
@@ -19,16 +21,19 @@ import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
|
|
|
|
|
|
testUtils.createSinonSandbox();
|
|
|
|
|
|
-describe( 'DecoupledEditor', () => {
|
|
|
- let editor, editorData;
|
|
|
+const editorData = '<p><strong>foo</strong> bar</p>';
|
|
|
|
|
|
- beforeEach( () => {
|
|
|
- editorData = '<p><strong>foo</strong> bar</p>';
|
|
|
- } );
|
|
|
+describe( 'DecoupledEditor', () => {
|
|
|
+ let editor;
|
|
|
|
|
|
describe( 'constructor()', () => {
|
|
|
beforeEach( () => {
|
|
|
editor = new DecoupledEditor();
|
|
|
+ editor.ui.init();
|
|
|
+ } );
|
|
|
+
|
|
|
+ afterEach( () => {
|
|
|
+ return editor.destroy();
|
|
|
} );
|
|
|
|
|
|
it( 'uses HTMLDataProcessor', () => {
|
|
|
@@ -52,173 +57,220 @@ describe( 'DecoupledEditor', () => {
|
|
|
} );
|
|
|
|
|
|
describe( 'create()', () => {
|
|
|
- beforeEach( () => {
|
|
|
- return DecoupledEditor
|
|
|
- .create( editorData, {
|
|
|
- plugins: [ Paragraph, Bold ]
|
|
|
- } )
|
|
|
- .then( newEditor => {
|
|
|
- editor = newEditor;
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
afterEach( () => {
|
|
|
return editor.destroy();
|
|
|
} );
|
|
|
|
|
|
- it( 'creates an instance which inherits from the DecoupledEditor', () => {
|
|
|
- expect( editor ).to.be.instanceof( DecoupledEditor );
|
|
|
- } );
|
|
|
+ describe( 'editor with data', () => {
|
|
|
+ beforeEach( () => {
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( editorData, {
|
|
|
+ plugins: [ Paragraph, Bold ]
|
|
|
+ } )
|
|
|
+ .then( newEditor => {
|
|
|
+ editor = newEditor;
|
|
|
+ } );
|
|
|
+ } );
|
|
|
|
|
|
- it( 'loads the initial data', () => {
|
|
|
- expect( editor.getData() ).to.equal( '<p><strong>foo</strong> bar</p>' );
|
|
|
+ test( () => editorData );
|
|
|
} );
|
|
|
|
|
|
- // #53
|
|
|
- it( 'creates an instance of a DecoupledEditor child class', () => {
|
|
|
- class CustomDecoupledEditor extends DecoupledEditor {}
|
|
|
+ describe( 'editor with editable element', () => {
|
|
|
+ let editableElement;
|
|
|
|
|
|
- return CustomDecoupledEditor
|
|
|
- .create( editorData, {
|
|
|
- plugins: [ Paragraph, Bold ]
|
|
|
- } )
|
|
|
- .then( newEditor => {
|
|
|
- expect( newEditor ).to.be.instanceof( CustomDecoupledEditor );
|
|
|
- expect( newEditor ).to.be.instanceof( DecoupledEditor );
|
|
|
+ beforeEach( () => {
|
|
|
+ editableElement = document.createElement( 'div' );
|
|
|
+ editableElement.innerHTML = editorData;
|
|
|
|
|
|
- expect( newEditor.getData() ).to.equal( '<p><strong>foo</strong> bar</p>' );
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( editableElement, {
|
|
|
+ plugins: [ Paragraph, Bold ]
|
|
|
+ } )
|
|
|
+ .then( newEditor => {
|
|
|
+ editor = newEditor;
|
|
|
+ } );
|
|
|
+ } );
|
|
|
|
|
|
- return newEditor.destroy();
|
|
|
- } );
|
|
|
+ test( () => editableElement );
|
|
|
} );
|
|
|
|
|
|
- // https://github.com/ckeditor/ckeditor5-editor-decoupled/issues/3
|
|
|
- it( 'initializes the data controller', () => {
|
|
|
- let dataInitSpy;
|
|
|
+ function test( getElementOrData ) {
|
|
|
+ it( 'creates an instance which inherits from the DecoupledEditor', () => {
|
|
|
+ expect( editor ).to.be.instanceof( DecoupledEditor );
|
|
|
+ } );
|
|
|
|
|
|
- class DataInitAssertPlugin extends Plugin {
|
|
|
- constructor( editor ) {
|
|
|
- super();
|
|
|
+ it( 'loads the initial data', () => {
|
|
|
+ expect( editor.getData() ).to.equal( '<p><strong>foo</strong> bar</p>' );
|
|
|
+ } );
|
|
|
|
|
|
- this.editor = editor;
|
|
|
- }
|
|
|
+ // https://github.com/ckeditor/ckeditor5-editor-classic/issues/53
|
|
|
+ it( 'creates an instance of a DecoupledEditor child class', () => {
|
|
|
+ class CustomDecoupledEditor extends DecoupledEditor {}
|
|
|
|
|
|
- init() {
|
|
|
- dataInitSpy = sinon.spy( this.editor.data, 'init' );
|
|
|
- }
|
|
|
- }
|
|
|
+ return CustomDecoupledEditor
|
|
|
+ .create( getElementOrData(), {
|
|
|
+ plugins: [ Paragraph, Bold ]
|
|
|
+ } )
|
|
|
+ .then( newEditor => {
|
|
|
+ expect( newEditor ).to.be.instanceof( CustomDecoupledEditor );
|
|
|
+ expect( newEditor ).to.be.instanceof( DecoupledEditor );
|
|
|
|
|
|
- return DecoupledEditor
|
|
|
- .create( editorData, {
|
|
|
- plugins: [ Paragraph, Bold, DataInitAssertPlugin ]
|
|
|
- } )
|
|
|
- .then( newEditor => {
|
|
|
- sinon.assert.calledOnce( dataInitSpy );
|
|
|
+ expect( newEditor.getData() ).to.equal( '<p><strong>foo</strong> bar</p>' );
|
|
|
|
|
|
- return newEditor.destroy();
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'ui', () => {
|
|
|
- it( 'attaches editable UI as view\'s DOM root', () => {
|
|
|
- expect( editor.editing.view.getDomRoot() ).to.equal( editor.ui.view.editable.element );
|
|
|
+ return newEditor.destroy();
|
|
|
+ } );
|
|
|
} );
|
|
|
- } );
|
|
|
- } );
|
|
|
|
|
|
- describe( 'create - events', () => {
|
|
|
- afterEach( () => {
|
|
|
- return editor.destroy();
|
|
|
- } );
|
|
|
+ // https://github.com/ckeditor/ckeditor5-editor-decoupled/issues/3
|
|
|
+ it( 'initializes the data controller', () => {
|
|
|
+ let dataInitSpy;
|
|
|
|
|
|
- it( 'fires all events in the right order', () => {
|
|
|
- const fired = [];
|
|
|
+ class DataInitAssertPlugin extends Plugin {
|
|
|
+ constructor( editor ) {
|
|
|
+ super();
|
|
|
|
|
|
- function spy( evt ) {
|
|
|
- fired.push( evt.name );
|
|
|
- }
|
|
|
+ this.editor = editor;
|
|
|
+ }
|
|
|
|
|
|
- class EventWatcher extends Plugin {
|
|
|
- init() {
|
|
|
- this.editor.on( 'pluginsReady', spy );
|
|
|
- this.editor.on( 'uiReady', spy );
|
|
|
- this.editor.on( 'dataReady', spy );
|
|
|
- this.editor.on( 'ready', spy );
|
|
|
+ init() {
|
|
|
+ dataInitSpy = sinon.spy( this.editor.data, 'init' );
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- return DecoupledEditor
|
|
|
- .create( editorData, {
|
|
|
- plugins: [ EventWatcher ]
|
|
|
- } )
|
|
|
- .then( newEditor => {
|
|
|
- expect( fired ).to.deep.equal( [ 'pluginsReady', 'uiReady', 'dataReady', 'ready' ] );
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( getElementOrData(), {
|
|
|
+ plugins: [ Paragraph, Bold, DataInitAssertPlugin ]
|
|
|
+ } )
|
|
|
+ .then( newEditor => {
|
|
|
+ sinon.assert.calledOnce( dataInitSpy );
|
|
|
+
|
|
|
+ return newEditor.destroy();
|
|
|
+ } );
|
|
|
+ } );
|
|
|
|
|
|
- editor = newEditor;
|
|
|
+ describe( 'events', () => {
|
|
|
+ it( 'fires all events in the right order', () => {
|
|
|
+ const fired = [];
|
|
|
+
|
|
|
+ function spy( evt ) {
|
|
|
+ fired.push( evt.name );
|
|
|
+ }
|
|
|
+
|
|
|
+ class EventWatcher extends Plugin {
|
|
|
+ init() {
|
|
|
+ this.editor.on( 'pluginsReady', spy );
|
|
|
+ this.editor.on( 'uiReady', spy );
|
|
|
+ this.editor.on( 'dataReady', spy );
|
|
|
+ this.editor.on( 'ready', spy );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( getElementOrData(), {
|
|
|
+ plugins: [ EventWatcher ]
|
|
|
+ } )
|
|
|
+ .then( newEditor => {
|
|
|
+ expect( fired ).to.deep.equal( [ 'pluginsReady', 'uiReady', 'dataReady', 'ready' ] );
|
|
|
+
|
|
|
+ return newEditor.destroy();
|
|
|
+ } );
|
|
|
} );
|
|
|
- } );
|
|
|
|
|
|
- it( 'fires dataReady once data is loaded', () => {
|
|
|
- let data;
|
|
|
+ it( 'fires dataReady once data is loaded', () => {
|
|
|
+ let data;
|
|
|
+
|
|
|
+ class EventWatcher extends Plugin {
|
|
|
+ init() {
|
|
|
+ this.editor.on( 'dataReady', () => {
|
|
|
+ data = this.editor.getData();
|
|
|
+ } );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( getElementOrData(), {
|
|
|
+ plugins: [ EventWatcher, Paragraph, Bold ]
|
|
|
+ } )
|
|
|
+ .then( newEditor => {
|
|
|
+ expect( data ).to.equal( '<p><strong>foo</strong> bar</p>' );
|
|
|
+
|
|
|
+ return newEditor.destroy();
|
|
|
+ } );
|
|
|
+ } );
|
|
|
|
|
|
- class EventWatcher extends Plugin {
|
|
|
- init() {
|
|
|
- this.editor.on( 'dataReady', () => {
|
|
|
- data = this.editor.getData();
|
|
|
- } );
|
|
|
- }
|
|
|
- }
|
|
|
+ it( 'fires uiReady once UI is rendered', () => {
|
|
|
+ let isReady;
|
|
|
+
|
|
|
+ class EventWatcher extends Plugin {
|
|
|
+ init() {
|
|
|
+ this.editor.on( 'uiReady', () => {
|
|
|
+ isReady = this.editor.ui.view.isRendered;
|
|
|
+ } );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( getElementOrData(), {
|
|
|
+ plugins: [ EventWatcher ]
|
|
|
+ } )
|
|
|
+ .then( newEditor => {
|
|
|
+ expect( isReady ).to.be.true;
|
|
|
+
|
|
|
+ return newEditor.destroy();
|
|
|
+ } );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
+ }
|
|
|
+ } );
|
|
|
|
|
|
- return DecoupledEditor
|
|
|
- .create( editorData, {
|
|
|
- plugins: [ EventWatcher, Paragraph, Bold ]
|
|
|
- } )
|
|
|
- .then( newEditor => {
|
|
|
- expect( data ).to.equal( '<p><strong>foo</strong> bar</p>' );
|
|
|
+ describe( 'destroy', () => {
|
|
|
+ describe( 'editor with data', () => {
|
|
|
+ beforeEach( function() {
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( editorData, { plugins: [ Paragraph ] } )
|
|
|
+ .then( newEditor => {
|
|
|
+ editor = newEditor;
|
|
|
+ } );
|
|
|
+ } );
|
|
|
|
|
|
- editor = newEditor;
|
|
|
- } );
|
|
|
+ test( () => editorData );
|
|
|
} );
|
|
|
|
|
|
- it( 'fires uiReady once UI is rendered', () => {
|
|
|
- let isReady;
|
|
|
+ describe( 'editor with editable element', () => {
|
|
|
+ let editableElement;
|
|
|
+
|
|
|
+ beforeEach( function() {
|
|
|
+ editableElement = document.createElement( 'div' );
|
|
|
+ editableElement.innerHTML = editorData;
|
|
|
|
|
|
- class EventWatcher extends Plugin {
|
|
|
- init() {
|
|
|
- this.editor.on( 'uiReady', () => {
|
|
|
- isReady = this.editor.ui.view.isRendered;
|
|
|
+ return DecoupledEditor
|
|
|
+ .create( editableElement, { plugins: [ Paragraph ] } )
|
|
|
+ .then( newEditor => {
|
|
|
+ editor = newEditor;
|
|
|
} );
|
|
|
- }
|
|
|
- }
|
|
|
+ } );
|
|
|
|
|
|
- return DecoupledEditor
|
|
|
- .create( editorData, {
|
|
|
- plugins: [ EventWatcher ]
|
|
|
- } )
|
|
|
- .then( newEditor => {
|
|
|
- expect( isReady ).to.be.true;
|
|
|
+ it( 'sets data back to the element', () => {
|
|
|
+ editor.setData( '<p>foo</p>' );
|
|
|
|
|
|
- editor = newEditor;
|
|
|
- } );
|
|
|
- } );
|
|
|
- } );
|
|
|
+ return editor.destroy()
|
|
|
+ .then( () => {
|
|
|
+ expect( editableElement.innerHTML ).to.equal( '<p>foo</p>' );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
|
|
|
- describe( 'destroy', () => {
|
|
|
- beforeEach( function() {
|
|
|
- return DecoupledEditor
|
|
|
- .create( editorData, { plugins: [ Paragraph ] } )
|
|
|
- .then( newEditor => {
|
|
|
- editor = newEditor;
|
|
|
- } );
|
|
|
+ test( () => editableElement );
|
|
|
} );
|
|
|
|
|
|
- it( 'destroys the UI', () => {
|
|
|
- const spy = sinon.spy( editor.ui, 'destroy' );
|
|
|
+ function test() {
|
|
|
+ it( 'destroys the UI', () => {
|
|
|
+ const spy = sinon.spy( editor.ui, 'destroy' );
|
|
|
|
|
|
- return editor.destroy()
|
|
|
- .then( () => {
|
|
|
- sinon.assert.calledOnce( spy );
|
|
|
- } );
|
|
|
- } );
|
|
|
+ return editor.destroy()
|
|
|
+ .then( () => {
|
|
|
+ sinon.assert.calledOnce( spy );
|
|
|
+ } );
|
|
|
+ } );
|
|
|
+ }
|
|
|
} );
|
|
|
} );
|