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 #152 from ckeditor/t/148
Browse files Browse the repository at this point in the history
Other: Throw `editor.plugins.get()` error when the plugin is not loaded. Closes #148.

BREAKING CHANGE: The `editor.plugins.get()` will now throw an error if the plugin is not loaded. Use `editor.plugins.has()` to check if plugin is available.
  • Loading branch information
Piotr Jasiun authored Dec 11, 2018
2 parents 9b925fc + f98d113 commit a56b47a
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 14 deletions.
63 changes: 61 additions & 2 deletions src/plugincollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,70 @@ export default class PluginCollection {
/**
* Gets the plugin instance by its constructor or name.
*
* // Check if 'Clipboard' plugin was loaded.
* if ( editor.plugins.has( 'Clipboard' ) ) {
* // Get clipboard plugin instance
* const clipboard = editor.plugins.get( 'Clipboard' );
*
* this.listenTo( clipboard, 'inputTransformation', ( evt, data ) => {
* // Do something on clipboard input.
* } );
* }
*
* **Note**: This method will throw error if plugin is not loaded. Use `{@link #has editor.plugins.has()}`
* to check if plugin is available.
*
* @param {Function|String} key The plugin constructor or {@link module:core/plugin~PluginInterface.pluginName name}.
* @returns {module:core/plugin~PluginInterface}
*/
get( key ) {
return this._plugins.get( key );
const plugin = this._plugins.get( key );

if ( !plugin ) {
/**
* The plugin is not loaded and could not be obtained.
*
* Plugin classes (constructors) need to be provided to the editor and must be loaded before they can be obtained from
* the plugin collection.
* This is usually done in CKEditor 5 builds by setting the {@link module:core/editor/editor~Editor.builtinPlugins}
* property.
*
* **Note**: You can use `{@link module:core/plugincollection~PluginCollection#has editor.plugins.has()}`
* to check if plugin was loaded.
*
* @error plugincollection-plugin-not-loaded
* @param {String} plugin The name of the plugin which is not loaded.
*/
const errorMsg = 'plugincollection-plugin-not-loaded: The requested plugin is not loaded.';

let pluginName = key;

if ( typeof key == 'function' ) {
pluginName = key.pluginName || key.name;
}

throw new CKEditorError( errorMsg, { plugin: pluginName } );
}

return plugin;
}

/**
* Checks if plugin is loaded.
*
* // Check if 'Clipboard' plugin was loaded.
* if ( editor.plugins.has( 'Clipboard' ) ) {
* // Now use clipboard plugin instance:
* const clipboard = editor.plugins.get( 'Clipboard' );
*
* // ...
* }
*
* @param {Function|String} key The plugin constructor or {@link module:core/plugin~PluginInterface.pluginName name}.
* @returns {Boolean}
*/
has( key ) {
return this._plugins.has( key );
}

/**
Expand Down Expand Up @@ -140,7 +199,7 @@ export default class PluginCollection {
}

// The plugin is already loaded or being loaded - do nothing.
if ( that.get( PluginConstructor ) || loading.has( PluginConstructor ) ) {
if ( that._plugins.has( PluginConstructor ) || loading.has( PluginConstructor ) ) {
return;
}

Expand Down
24 changes: 12 additions & 12 deletions tests/pendingactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
* For licensing, see LICENSE.md.
*/

import VirtaulTestEditor from './_utils/virtualtesteditor';
import VirtualTestEditor from './_utils/virtualtesteditor';
import PendingActions from '../src/pendingactions';
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';

let editor, pendingActions;

beforeEach( () => {
return VirtaulTestEditor.create( {
plugins: [ PendingActions ],
} ).then( newEditor => {
editor = newEditor;
pendingActions = editor.plugins.get( PendingActions );
describe( 'PendingActions', () => {
beforeEach( () => {
return VirtualTestEditor.create( {
plugins: [ PendingActions ],
} ).then( newEditor => {
editor = newEditor;
pendingActions = editor.plugins.get( PendingActions );
} );
} );
} );

afterEach( () => {
return editor.destroy();
} );
afterEach( () => {
return editor.destroy();
} );

describe( 'PendingActions', () => {
it( 'should define static pluginName property', () => {
expect( PendingActions ).to.have.property( 'pluginName', 'PendingActions' );
} );
Expand Down
66 changes: 66 additions & 0 deletions tests/plugincollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,72 @@ describe( 'PluginCollection', () => {
expect( plugins.get( SomePlugin ) ).to.be.instanceOf( SomePlugin );
} );
} );

it( 'throws if plugin cannot be retrieved by name', () => {
const plugins = new PluginCollection( editor, availablePlugins );

return plugins.load( [] ).then( () => {
expect( () => plugins.get( 'foo' ) )
.to.throw( CKEditorError, /^plugincollection-plugin-not-loaded:/ )
.with.deep.property( 'data', { plugin: 'foo' } );
} );
} );

it( 'throws if plugin cannot be retrieved by class', () => {
class SomePlugin extends Plugin {}
SomePlugin.pluginName = 'foo';

const plugins = new PluginCollection( editor, availablePlugins );

return plugins.load( [] ).then( () => {
expect( () => plugins.get( SomePlugin ) )
.to.throw( CKEditorError, /^plugincollection-plugin-not-loaded:/ )
.with.deep.property( 'data', { plugin: 'foo' } );
} );
} );

it( 'throws if plugin cannot be retrieved by class (class name in error)', () => {
class SomePlugin extends Plugin {}

const plugins = new PluginCollection( editor, availablePlugins );

return plugins.load( [] ).then( () => {
expect( () => plugins.get( SomePlugin ) )
.to.throw( CKEditorError, /^plugincollection-plugin-not-loaded:/ )
.with.deep.property( 'data', { plugin: 'SomePlugin' } );
} );
} );
} );

describe( 'has()', () => {
let plugins;

beforeEach( () => {
plugins = new PluginCollection( editor, availablePlugins );
} );

it( 'returns false if plugins is not loaded (retrieved by name)', () => {
expect( plugins.has( 'foobar' ) ).to.be.false;
} );

it( 'returns false if plugins is not loaded (retrieved by class)', () => {
class SomePlugin extends Plugin {
}

expect( plugins.has( SomePlugin ) ).to.be.false;
} );

it( 'returns true if plugins is loaded (retrieved by name)', () => {
return plugins.load( [ PluginA ] ).then( () => {
expect( plugins.has( 'A' ) ).to.be.true;
} );
} );

it( 'returns true if plugins is loaded (retrieved by class)', () => {
return plugins.load( [ PluginA ] ).then( () => {
expect( plugins.has( PluginA ) ).to.be.true;
} );
} );
} );

describe( 'destroy()', () => {
Expand Down

0 comments on commit a56b47a

Please sign in to comment.