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

Commit a56b47a

Browse files
author
Piotr Jasiun
authored
Merge pull request #152 from ckeditor/t/148
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.
2 parents 9b925fc + f98d113 commit a56b47a

File tree

3 files changed

+139
-14
lines changed

3 files changed

+139
-14
lines changed

src/plugincollection.js

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,70 @@ export default class PluginCollection {
7272
/**
7373
* Gets the plugin instance by its constructor or name.
7474
*
75+
* // Check if 'Clipboard' plugin was loaded.
76+
* if ( editor.plugins.has( 'Clipboard' ) ) {
77+
* // Get clipboard plugin instance
78+
* const clipboard = editor.plugins.get( 'Clipboard' );
79+
*
80+
* this.listenTo( clipboard, 'inputTransformation', ( evt, data ) => {
81+
* // Do something on clipboard input.
82+
* } );
83+
* }
84+
*
85+
* **Note**: This method will throw error if plugin is not loaded. Use `{@link #has editor.plugins.has()}`
86+
* to check if plugin is available.
87+
*
7588
* @param {Function|String} key The plugin constructor or {@link module:core/plugin~PluginInterface.pluginName name}.
7689
* @returns {module:core/plugin~PluginInterface}
7790
*/
7891
get( key ) {
79-
return this._plugins.get( key );
92+
const plugin = this._plugins.get( key );
93+
94+
if ( !plugin ) {
95+
/**
96+
* The plugin is not loaded and could not be obtained.
97+
*
98+
* Plugin classes (constructors) need to be provided to the editor and must be loaded before they can be obtained from
99+
* the plugin collection.
100+
* This is usually done in CKEditor 5 builds by setting the {@link module:core/editor/editor~Editor.builtinPlugins}
101+
* property.
102+
*
103+
* **Note**: You can use `{@link module:core/plugincollection~PluginCollection#has editor.plugins.has()}`
104+
* to check if plugin was loaded.
105+
*
106+
* @error plugincollection-plugin-not-loaded
107+
* @param {String} plugin The name of the plugin which is not loaded.
108+
*/
109+
const errorMsg = 'plugincollection-plugin-not-loaded: The requested plugin is not loaded.';
110+
111+
let pluginName = key;
112+
113+
if ( typeof key == 'function' ) {
114+
pluginName = key.pluginName || key.name;
115+
}
116+
117+
throw new CKEditorError( errorMsg, { plugin: pluginName } );
118+
}
119+
120+
return plugin;
121+
}
122+
123+
/**
124+
* Checks if plugin is loaded.
125+
*
126+
* // Check if 'Clipboard' plugin was loaded.
127+
* if ( editor.plugins.has( 'Clipboard' ) ) {
128+
* // Now use clipboard plugin instance:
129+
* const clipboard = editor.plugins.get( 'Clipboard' );
130+
*
131+
* // ...
132+
* }
133+
*
134+
* @param {Function|String} key The plugin constructor or {@link module:core/plugin~PluginInterface.pluginName name}.
135+
* @returns {Boolean}
136+
*/
137+
has( key ) {
138+
return this._plugins.has( key );
80139
}
81140

82141
/**
@@ -140,7 +199,7 @@ export default class PluginCollection {
140199
}
141200

142201
// The plugin is already loaded or being loaded - do nothing.
143-
if ( that.get( PluginConstructor ) || loading.has( PluginConstructor ) ) {
202+
if ( that._plugins.has( PluginConstructor ) || loading.has( PluginConstructor ) ) {
144203
return;
145204
}
146205

tests/pendingactions.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,26 @@
33
* For licensing, see LICENSE.md.
44
*/
55

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

1010
let editor, pendingActions;
1111

12-
beforeEach( () => {
13-
return VirtaulTestEditor.create( {
14-
plugins: [ PendingActions ],
15-
} ).then( newEditor => {
16-
editor = newEditor;
17-
pendingActions = editor.plugins.get( PendingActions );
12+
describe( 'PendingActions', () => {
13+
beforeEach( () => {
14+
return VirtualTestEditor.create( {
15+
plugins: [ PendingActions ],
16+
} ).then( newEditor => {
17+
editor = newEditor;
18+
pendingActions = editor.plugins.get( PendingActions );
19+
} );
1820
} );
19-
} );
2021

21-
afterEach( () => {
22-
return editor.destroy();
23-
} );
22+
afterEach( () => {
23+
return editor.destroy();
24+
} );
2425

25-
describe( 'PendingActions', () => {
2626
it( 'should define static pluginName property', () => {
2727
expect( PendingActions ).to.have.property( 'pluginName', 'PendingActions' );
2828
} );

tests/plugincollection.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,72 @@ describe( 'PluginCollection', () => {
448448
expect( plugins.get( SomePlugin ) ).to.be.instanceOf( SomePlugin );
449449
} );
450450
} );
451+
452+
it( 'throws if plugin cannot be retrieved by name', () => {
453+
const plugins = new PluginCollection( editor, availablePlugins );
454+
455+
return plugins.load( [] ).then( () => {
456+
expect( () => plugins.get( 'foo' ) )
457+
.to.throw( CKEditorError, /^plugincollection-plugin-not-loaded:/ )
458+
.with.deep.property( 'data', { plugin: 'foo' } );
459+
} );
460+
} );
461+
462+
it( 'throws if plugin cannot be retrieved by class', () => {
463+
class SomePlugin extends Plugin {}
464+
SomePlugin.pluginName = 'foo';
465+
466+
const plugins = new PluginCollection( editor, availablePlugins );
467+
468+
return plugins.load( [] ).then( () => {
469+
expect( () => plugins.get( SomePlugin ) )
470+
.to.throw( CKEditorError, /^plugincollection-plugin-not-loaded:/ )
471+
.with.deep.property( 'data', { plugin: 'foo' } );
472+
} );
473+
} );
474+
475+
it( 'throws if plugin cannot be retrieved by class (class name in error)', () => {
476+
class SomePlugin extends Plugin {}
477+
478+
const plugins = new PluginCollection( editor, availablePlugins );
479+
480+
return plugins.load( [] ).then( () => {
481+
expect( () => plugins.get( SomePlugin ) )
482+
.to.throw( CKEditorError, /^plugincollection-plugin-not-loaded:/ )
483+
.with.deep.property( 'data', { plugin: 'SomePlugin' } );
484+
} );
485+
} );
486+
} );
487+
488+
describe( 'has()', () => {
489+
let plugins;
490+
491+
beforeEach( () => {
492+
plugins = new PluginCollection( editor, availablePlugins );
493+
} );
494+
495+
it( 'returns false if plugins is not loaded (retrieved by name)', () => {
496+
expect( plugins.has( 'foobar' ) ).to.be.false;
497+
} );
498+
499+
it( 'returns false if plugins is not loaded (retrieved by class)', () => {
500+
class SomePlugin extends Plugin {
501+
}
502+
503+
expect( plugins.has( SomePlugin ) ).to.be.false;
504+
} );
505+
506+
it( 'returns true if plugins is loaded (retrieved by name)', () => {
507+
return plugins.load( [ PluginA ] ).then( () => {
508+
expect( plugins.has( 'A' ) ).to.be.true;
509+
} );
510+
} );
511+
512+
it( 'returns true if plugins is loaded (retrieved by class)', () => {
513+
return plugins.load( [ PluginA ] ).then( () => {
514+
expect( plugins.has( PluginA ) ).to.be.true;
515+
} );
516+
} );
451517
} );
452518

453519
describe( 'destroy()', () => {

0 commit comments

Comments
 (0)