Преглед изворни кода

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.
Piotr Jasiun пре 7 година
родитељ
комит
879267fca2

+ 61 - 2
packages/ckeditor5-core/src/plugincollection.js

@@ -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 );
 	}
 
 	/**
@@ -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;
 			}
 

+ 12 - 12
packages/ckeditor5-core/tests/pendingactions.js

@@ -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' );
 	} );

+ 66 - 0
packages/ckeditor5-core/tests/plugincollection.js

@@ -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()', () => {