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 #72 from ckeditor/t/67
Browse files Browse the repository at this point in the history
Feature: Added support for building plugins and default configs into `Editor` classes. Closes #67.
  • Loading branch information
Reinmar committed Mar 7, 2017
2 parents d9eb547 + 19c8351 commit a1fa64f
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,25 @@ export default class Editor {
* @param {Object} config The editor config.
*/
constructor( config ) {
const availablePlugins = this.constructor.build && this.constructor.build.plugins;

/**
* Holds all configurations specific to this editor instance.
*
* @readonly
* @member {module:utils/config~Config}
*/
this.config = new Config( config );
this.config = new Config( config, this.constructor.build && this.constructor.build.config );

this.config.define( 'plugins', availablePlugins );

/**
* The plugins loaded and in use by this editor instance.
*
* @readonly
* @member {module:core/plugin~PluginCollection}
*/
this.plugins = new PluginCollection( this );
this.plugins = new PluginCollection( this, availablePlugins );

/**
* Commands registered to the editor.
Expand Down
155 changes: 155 additions & 0 deletions tests/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ class PluginA extends Plugin {
this.init = sinon.spy().named( 'A' );
this.afterInit = sinon.spy().named( 'A-after' );
}

static get pluginName() {
return 'A';
}
}

class PluginB extends Plugin {
Expand All @@ -24,6 +28,10 @@ class PluginB extends Plugin {
this.init = sinon.spy().named( 'B' );
this.afterInit = sinon.spy().named( 'B-after' );
}

static get pluginName() {
return 'B';
}
}

class PluginC extends Plugin {
Expand All @@ -33,6 +41,10 @@ class PluginC extends Plugin {
this.afterInit = sinon.spy().named( 'C-after' );
}

static get pluginName() {
return 'C';
}

static get requires() {
return [ PluginB ];
}
Expand All @@ -45,12 +57,20 @@ class PluginD extends Plugin {
this.afterInit = sinon.spy().named( 'D-after' );
}

static get pluginName() {
return 'D';
}

static get requires() {
return [ PluginC ];
}
}

describe( 'Editor', () => {
afterEach( () => {
delete Editor.build;
} );

describe( 'constructor()', () => {
it( 'should create a new editor instance', () => {
const editor = new Editor();
Expand All @@ -61,6 +81,32 @@ describe( 'Editor', () => {
expect( editor.plugins ).to.be.an.instanceof( PluginCollection );
expect( getPlugins( editor ) ).to.be.empty;
} );

it( 'should extend an editor configuration using built in config', () => {
Editor.build = {
config: {
foo: {
a: 1,
b: 2
}
}
};

const editor = new Editor( {
bar: 'foo',
foo: {
c: 3
},
} );

expect( editor.config.get( 'foo' ) ).to.deep.equal( {
a: 1,
b: 2,
c: 3
} );

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

describe( 'plugins', () => {
Expand Down Expand Up @@ -244,6 +290,115 @@ describe( 'Editor', () => {
);
} );
} );

it( 'should load plugins built in the Editor even if the passed config is empty', () => {
Editor.build = {
plugins: [ PluginA, PluginB, PluginC ]
};

const editor = new Editor();

return editor.initPlugins()
.then( () => {
expect( getPlugins( editor ).length ).to.equal( 3 );

expect( editor.plugins.get( PluginA ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginB ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginC ) ).to.be.an.instanceof( Plugin );
} );
} );

it( 'should load plugins provided in the config and should ignore plugins built in the Editor', () => {
Editor.build = {
plugins: [ PluginA, PluginB, PluginC, PluginD ]
};

const editor = new Editor( {
plugins: [
'A'
]
} );

return editor.initPlugins()
.then( () => {
expect( getPlugins( editor ).length ).to.equal( 1 );

expect( editor.plugins.get( PluginA ) ).to.be.an.instanceof( Plugin );
} );
} );

it( 'should load plugins built in the Editor using their names', () => {
class PrivatePlugin extends Plugin {}

Editor.build = {
plugins: [ PluginA, PluginB, PluginC, PluginD ]
};

const editor = new Editor( {
plugins: [
'A',
'B',
'C',
PrivatePlugin
]
} );

return editor.initPlugins()
.then( () => {
expect( getPlugins( editor ).length ).to.equal( 4 );

expect( editor.plugins.get( PluginA ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginB ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginC ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PrivatePlugin ) ).to.be.an.instanceof( PrivatePlugin );
} );
} );

it( 'should load plugins inherited from the base Editor', () => {
Editor.build = {
plugins: [ PluginA, PluginB, PluginC, PluginD ]
};

class CustomEditor extends Editor {}

const editor = new CustomEditor( {
plugins: [
'D'
]
} );

return editor.initPlugins()
.then( () => {
expect( getPlugins( editor ).length ).to.equal( 3 );

expect( editor.plugins.get( PluginB ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginC ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginD ) ).to.be.an.instanceof( Plugin );
} );
} );

it( 'should load plugins build into Editor\'s subclass', () => {
class CustomEditor extends Editor {}

CustomEditor.build = {
plugins: [ PluginA, PluginB, PluginC, PluginD ]
};

const editor = new CustomEditor( {
plugins: [
'D'
]
} );

return editor.initPlugins()
.then( () => {
expect( getPlugins( editor ).length ).to.equal( 3 );

expect( editor.plugins.get( PluginB ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginC ) ).to.be.an.instanceof( Plugin );
expect( editor.plugins.get( PluginD ) ).to.be.an.instanceof( Plugin );
} );
} );
} );
} );

Expand Down

0 comments on commit a1fa64f

Please sign in to comment.