Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #132 from ckeditor/t/124
Browse files Browse the repository at this point in the history
Feature: Added the observable `Editor#state` property. Closes #124.
  • Loading branch information
Reinmar authored Jun 27, 2018
2 parents 7dda00a + 4beced2 commit ec89d8d
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 116 deletions.
23 changes: 23 additions & 0 deletions src/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ export default class Editor {
*/
this.t = this.locale.t;

/**
* Indicates the editor life-cycle state.
*
* The editor is in one of the following states:
*
* * `initializing` - during the editor initialization (before {@link module:core/editor/editor~Editor.create `Editor.create()`)
* finished its job,
* * `ready` - after the promise returned by the {@link module:core/editor/editor~Editor.create `Editor.create()`}
* method is resolved,
* * `destroyed` - once the {@link #destroy `editor.destroy()`} method was called.
*
* @observable
* @member {'initializing'|'ready'|'destroyed'} #state
*/
this.set( 'state', 'initializing' );
this.once( 'ready', () => ( this.state = 'ready' ), { priority: 'high' } );
this.once( 'destroy', () => ( this.state = 'destroyed' ), { priority: 'high' } );

/**
* Defines whether this editor is in read-only mode.
*
Expand Down Expand Up @@ -303,13 +321,18 @@ mix( Editor, ObservableMixin );
* In fact, since the first moment when the editor instance is available to you is inside `then()`'s callback,
* you cannot even add a listener to the `editor#ready` event.
*
* See also the {@link #state `editor.state`} property.
*
* @event ready
*/

/**
* Fired when this editor instance is destroyed. The editor at this point is not usable and this event should be used to
* perform the clean-up in any plugin.
*
*
* See also the {@link #state `editor.state`} property.
*
* @event destroy
*/

Expand Down
14 changes: 14 additions & 0 deletions tests/_utils-tests/classictesteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ describe( 'ClassicTestEditor', () => {
} );
} );

it( 'sets proper states', () => {
const editor = new ClassicTestEditor();

expect( editor.state ).to.equal( 'initializing' );

return ClassicTestEditor.create( editorElement ).then( editor => {
expect( editor.state ).to.equal( 'ready' );

return editor.destroy().then( () => {
expect( editor.state ).to.equal( 'destroyed' );
} );
} );
} );

it( 'inserts editor UI next to editor element', () => {
return ClassicTestEditor.create( editorElement )
.then( editor => {
Expand Down
36 changes: 0 additions & 36 deletions tests/_utils-tests/modeltesteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Editor from '../../src/editor/editor';
import EditingController from '@ckeditor/ckeditor5-engine/src/controller/editingcontroller';
import ModelTestEditor from '../../tests/_utils/modeltesteditor';

import Plugin from '../../src/plugin';
import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';
import DataApiMixin from '../../src/editor/utils/dataapimixin';
import RootElement from '@ckeditor/ckeditor5-engine/src/model/rootelement';
Expand Down Expand Up @@ -49,41 +48,6 @@ describe( 'ModelTestEditor', () => {
} );
} );

describe( 'create', () => {
it( 'creates an instance of editor', () => {
return ModelTestEditor.create( { foo: 1 } )
.then( editor => {
expect( editor ).to.be.instanceof( ModelTestEditor );

expect( editor.config.get( 'foo' ) ).to.equal( 1 );
} );
} );

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( 'dataReady', spy );
this.editor.on( 'ready', spy );
}
}

return ModelTestEditor
.create( {
plugins: [ EventWatcher ]
} )
.then( () => {
expect( fired ).to.deep.equal( [ 'pluginsReady', 'dataReady', 'ready' ] );
} );
} );
} );

describe( 'setData', () => {
let editor;

Expand Down
36 changes: 0 additions & 36 deletions tests/_utils-tests/virtualtesteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import Editor from '../../src/editor/editor';
import VirtualTestEditor from '../../tests/_utils/virtualtesteditor';

import Plugin from '../../src/plugin';
import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';
import DataApiMixin from '../../src/editor/utils/dataapimixin';
import RootElement from '@ckeditor/ckeditor5-engine/src/model/rootelement';
Expand Down Expand Up @@ -35,39 +34,4 @@ describe( 'VirtualTestEditor', () => {
expect( testUtils.isMixed( VirtualTestEditor, DataApiMixin ) ).to.true;
} );
} );

describe( 'create', () => {
it( 'creates an instance of editor', () => {
return VirtualTestEditor.create( { foo: 1 } )
.then( editor => {
expect( editor ).to.be.instanceof( VirtualTestEditor );

expect( editor.config.get( 'foo' ) ).to.equal( 1 );
} );
} );

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( 'dataReady', spy );
this.editor.on( 'ready', spy );
}
}

return VirtualTestEditor
.create( {
plugins: [ EventWatcher ]
} )
.then( () => {
expect( fired ).to.deep.equal( [ 'pluginsReady', 'dataReady', 'ready' ] );
} );
} );
} );
} );
1 change: 1 addition & 0 deletions tests/_utils/classictesteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export default class ClassicTestEditor extends Editor {
.then( () => editor.data.init( getDataFromElement( element ) ) )
.then( () => {
editor.fire( 'dataReady' );
editor.state = 'ready';
editor.fire( 'ready' );
} )
.then( () => editor )
Expand Down
22 changes: 0 additions & 22 deletions tests/_utils/modeltesteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,6 @@ export default class ModelTestEditor extends Editor {
// Create the ("main") root element of the model tree.
this.model.document.createRoot();
}

/**
* Creates a virtual, element-less editor instance.
*
* @param {Object} config See {@link core.editor.Editor}'s param.
* @returns {Promise} Promise resolved once editor is ready.
* @returns {core.editor.VirtualTestEditor} return.editor The editor instance.
*/
static create( config ) {
return new Promise( resolve => {
const editor = new this( config );

resolve(
editor.initPlugins()
.then( () => {
editor.fire( 'dataReady' );
editor.fire( 'ready' );
} )
.then( () => editor )
);
} );
}
}

mix( ModelTestEditor, DataApiMixin );
22 changes: 0 additions & 22 deletions tests/_utils/virtualtesteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,6 @@ export default class VirtualTestEditor extends Editor {
// Create the ("main") root element of the model tree.
this.model.document.createRoot();
}

/**
* Creates a virtual, element-less editor instance.
*
* @param {Object} config See {@link core.editor.Editor}'s param.
* @returns {Promise} Promise resolved once editor is ready.
* @returns {core.editor.VirtualTestEditor} return.editor The editor instance.
*/
static create( config ) {
return new Promise( resolve => {
const editor = new this( config );

resolve(
editor.initPlugins()
.then( () => {
editor.fire( 'dataReady' );
editor.fire( 'ready' );
} )
.then( () => editor )
);
} );
}
}

mix( VirtualTestEditor, DataApiMixin );
61 changes: 61 additions & 0 deletions tests/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,67 @@ describe( 'Editor', () => {
} );
} );

describe( 'state', () => {
it( 'is `initializing` initially', () => {
const editor = new Editor();

expect( editor.state ).to.equal( 'initializing' );
} );

it( 'is `ready` after initialization chain', () => {
return Editor.create().then( editor => {
expect( editor.state ).to.equal( 'ready' );

return editor.destroy();
} );
} );

it( 'is `destroyed` after editor destroy', () => {
const editor = new Editor();

return editor.destroy().then( () => {
expect( editor.state ).to.equal( 'destroyed' );
} );
} );

it( 'is observable', () => {
const editor = new Editor();
const spy = sinon.spy();

editor.on( 'change:state', spy );

editor.state = 'ready';

sinon.assert.calledOnce( spy );
} );

it( 'reacts on #ready event', done => {
const editor = new Editor();

expect( editor.state ).to.equal( 'initializing' );

editor.on( 'ready', () => {
expect( editor.state ).to.equal( 'ready' );
done();
} );

editor.fire( 'ready' );
} );

it( 'reacts on #destroy event', done => {
const editor = new Editor();

expect( editor.state ).to.equal( 'initializing' );

editor.on( 'destroy', () => {
expect( editor.state ).to.equal( 'destroyed' );
done();
} );

editor.fire( 'destroy' );
} );
} );

describe( 'isReadOnly', () => {
it( 'is false initially', () => {
const editor = new Editor();
Expand Down

0 comments on commit ec89d8d

Please sign in to comment.