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

Merge pull request #39 from cksource/t/38

Added log and ckeditorerror modules.
Piotrek Koszuliński пре 10 година
родитељ
комит
1e94c39e03

+ 54 - 0
packages/ckeditor5-engine/src/ckeditorerror.js

@@ -0,0 +1,54 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * The CKEditor error class.
+ *
+ * All errors will be shortened during the minification process in order to reduce the code size.
+ * Therefore, all error messages should be documented in the same way as those in {@link CKEDITOR.core.log}.
+ *
+ * Read more in the {@link core.log} module.
+ *
+ * @class CKEditorError
+ * @extends Error
+ */
+
+CKEDITOR.define( function() {
+	class CKEditorError extends Error {
+		/**
+		 * Creates an instance of the CKEditorError class.
+		 *
+		 * Read more about error logging in the {@link core.log} module.
+		 *
+		 * @constructor
+		 * @param {String} message The error message in an `error-name: Error message.` format.
+		 * During the minification process the "Error message" part will be removed to limit the code size
+		 * and a link to this error documentation will be added to the `message`.
+		 * @param {Object} [data] Additional data describing the error. A stringified version of this object
+		 * will be appended to the error {@link #message}, so the data are quickly visible in the console. The original
+		 * data object will also be later available under the {@link #data} property.
+		 */
+		constructor( message, data ) {
+			if ( data ) {
+				message += ' ' + JSON.stringify( data );
+			}
+
+			super( message );
+
+			this.name = 'CKEditorError';
+
+			/**
+			 * The additional error data passed to the constructor.
+			 *
+			 * @property {Object} data
+			 */
+			this.data = data;
+		}
+	}
+
+	return CKEditorError;
+} );

+ 74 - 0
packages/ckeditor5-engine/src/log.js

@@ -0,0 +1,74 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals console */
+
+'use strict';
+
+/**
+ * The logging module.
+ *
+ * This object features two functions that should be used across CKEditor code base to log errors and warnings.
+ * Despite being an overridable interface for native `console.*` this module serves also the goal to limit the
+ * code size of a minified CKEditor package. During minification process the messages will be shortened and
+ * links to their documentation will be logged to the console.
+ *
+ * All errors and warning should be documented in the following way (note that block comment should be used instead of `//`):
+ *
+ *		// Error thrown when a plugin cannot be loaded due to JavaScript errors, lack of plugins with a given name, etc.
+ *		//
+ *		// @error plugin-load
+ *		// @param pluginName The name of the plugin that could not be loaded.
+ *		// @param moduleName The name of the module which tried to load this plugin.
+ *		log.error( 'plugin-load: It was not possible to load the "{$pluginName}" plugin in module "{$moduleName}', {
+ *			pluginName: 'foo',
+ *			moduleName: 'bar'
+ *		} );
+ *
+ * ## Warning vs Error vs Throw
+ *
+ * * Whenever a potentially incorrect situation occurs, which does not directly lead to an incorrect behavior,
+ * log a warning.
+ * * Whenever an incorrect situation occurs, but the app may continue working (although perhaps incorrectly),
+ * log an error.
+ * * Whenever it's really bad and it does not make sense to continue working, throw a {@link core.CKEditorError}.
+ *
+ * @class log
+ * @singleton
+ */
+
+CKEDITOR.define( function() {
+	var log = {
+		/**
+		 * Logs an error to the console.
+		 *
+		 * Read more about error logging in the {@link core.log} module.
+		 *
+		 * @param {String} message The error message in an `error-name: Error message.` format.
+		 * During the minification process the "Error message" part will be removed to limit the code size
+		 * and a link to this error documentation will be logged to the console.
+		 * @param {Object} [data] Additional data describing the error.
+		 */
+		error( message, data ) {
+			console.error( message, data );
+		},
+
+		/**
+		 * Logs a warning to the console.
+		 *
+		 * Read more about error logging in the {@link core.log} module.
+		 *
+		 * @param {String} message The warning message in a `warning-name: Warning message.` format.
+		 * During the minification process the "Warning message" part will be removed to limit the code size
+		 * and a link to this error documentation will be logged to the console.
+		 * @param {Object} [data] Additional data describing the warning.
+		 */
+		warn( message, data ) {
+			console.warn( message, data );
+		}
+	};
+
+	return log;
+} );

+ 8 - 3
packages/ckeditor5-engine/src/plugincollection.js

@@ -12,7 +12,7 @@
  * @extends Collection
  */
 
-CKEDITOR.define( [ 'collection', 'promise' ], function( Collection, Promise ) {
+CKEDITOR.define( [ 'collection', 'promise', 'ckeditorerror' ], function( Collection, Promise, CKEditorError ) {
 	class PluginCollection extends Collection {
 		/**
 		 * Creates an instance of the PluginCollection class, initializing it with a set of plugins.
@@ -77,8 +77,13 @@ CKEDITOR.define( [ 'collection', 'promise' ], function( Collection, Promise ) {
 						},
 						// Error callback.
 						function() {
-							var err = new Error( 'It was not possible to load the "' + plugin + '" plugin.' );
-							err.name = 'CKEditor Error';
+							/**
+							 * It was not possible to load the plugin.
+							 *
+							 * @error plugincollection-load
+							 * @param {String} plugin The name of the plugin that could not be loaded.
+							 */
+							var err = new CKEditorError( 'plugincollection-load: It was not possible to load the plugin.', { plugin: plugin } );
 							reject( err );
 						}
 					);

+ 63 - 0
packages/ckeditor5-engine/tests/ckeditorerror/ckeditorerror.js

@@ -0,0 +1,63 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals document */
+
+'use strict';
+
+var modules = bender.amd.require( 'ckeditorerror' );
+
+describe( 'CKEditorError', function() {
+	it( 'inherits from Error', function() {
+		var CKEditorError = modules.ckeditorerror;
+		var error = new CKEditorError( 'foo' );
+
+		expect( error ).to.be.an.instanceOf( Error );
+		expect( error ).to.be.an.instanceOf( CKEditorError );
+	} );
+
+	it( 'sets the name', function() {
+		var CKEditorError = modules.ckeditorerror;
+		var error = new CKEditorError( 'foo' );
+
+		expect( error ).to.have.property( 'name', 'CKEditorError' );
+	} );
+
+	it( 'sets the message', function() {
+		var CKEditorError = modules.ckeditorerror;
+		var error = new CKEditorError( 'foo' );
+
+		expect( error ).to.have.property( 'message', 'foo' );
+		expect( error.data ).to.be.undefined;
+	} );
+
+	it( 'sets the message and data', function() {
+		var CKEditorError = modules.ckeditorerror;
+		var data = { bar: 1 };
+		var error = new CKEditorError( 'foo', data );
+
+		expect( error ).to.have.property( 'message', 'foo {"bar":1}' );
+		expect( error ).to.have.property( 'data', data );
+	} );
+
+	it( 'appends stringified data to the message', function() {
+		class Foo {
+			constructor() {
+				this.x = 1;
+			}
+		}
+
+		var CKEditorError = modules.ckeditorerror;
+		var data = {
+			bar: 'a',
+			bom: new Foo(),
+			bim: document.body
+		};
+		var error = new CKEditorError( 'foo', data );
+
+		expect( error ).to.have.property( 'message', 'foo {"bar":"a","bom":{"x":1},"bim":{}}' );
+		expect( error ).to.have.property( 'data', data );
+	} );
+} );

+ 51 - 0
packages/ckeditor5-engine/tests/log/log.js

@@ -0,0 +1,51 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals console */
+
+'use strict';
+
+var modules = bender.amd.require( 'log' );
+var spy;
+
+beforeEach( function() {
+	if ( spy ) {
+		spy.restore();
+	}
+} );
+
+describe( 'warn()', function() {
+	it( 'logs the message to the console using console.warn()', function() {
+		var log = modules.log;
+		var spy = sinon.stub( console, 'warn' );
+		var data = { bar: 1 };
+
+		log.warn( 'foo', data );
+
+		sinon.assert.calledOnce( spy );
+		sinon.assert.calledWith( spy, 'foo', data );
+
+		log.warn( 'bar' );
+		sinon.assert.calledTwice( spy );
+		sinon.assert.calledWith( spy, 'bar' );
+	} );
+} );
+
+describe( 'error()', function() {
+	it( 'logs the message to the console using console.error()', function() {
+		var log = modules.log;
+		var spy = sinon.stub( console, 'error' );
+		var data = { bar: 1 };
+
+		log.error( 'foo', data );
+
+		sinon.assert.calledOnce( spy );
+		sinon.assert.calledWith( spy, 'foo', data );
+
+		log.error( 'bar' );
+		sinon.assert.calledTwice( spy );
+		sinon.assert.calledWith( spy, 'bar' );
+	} );
+} );

+ 4 - 3
packages/ckeditor5-engine/tests/plugincollection/plugincollection.js

@@ -7,7 +7,7 @@
 
 'use strict';
 
-var modules = bender.amd.require( 'plugincollection', 'plugin', 'editor' );
+var modules = bender.amd.require( 'plugincollection', 'plugin', 'editor', 'ckeditorerror' );
 var editor;
 var PluginA, PluginB;
 
@@ -169,6 +169,7 @@ describe( 'load', function() {
 
 	it( 'should throw an error for invalid plugins', function() {
 		var PluginCollection = modules.plugincollection;
+		var CKEditorError = modules.ckeditorerror;
 
 		var plugins = new PluginCollection( editor );
 
@@ -177,8 +178,8 @@ describe( 'load', function() {
 				throw new Error( 'Test error: this promise should not be resolved successfully' );
 			} )
 			.catch( function( err ) {
-				expect( err ).to.be.an.instanceof( Error );
-				expect( err.name ).to.equal( 'CKEditor Error' );
+				expect( err ).to.be.an.instanceof( CKEditorError );
+				expect( err.data ).to.have.property( 'plugin', 'BAD' );
 			} );
 	} );
 } );