浏览代码

Feature: Introduced PendingActions plugin.

Oskar Wróbel 7 年之前
父节点
当前提交
55589610f4
共有 2 个文件被更改,包括 188 次插入0 次删除
  1. 85 0
      packages/ckeditor5-core/src/pendingactions.js
  2. 103 0
      packages/ckeditor5-core/tests/pendingactions.js

+ 85 - 0
packages/ckeditor5-core/src/pendingactions.js

@@ -0,0 +1,85 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module core/pendingactions
+ */
+
+import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
+import Collection from '@ckeditor/ckeditor5-utils/src/collection';
+import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
+
+/**
+ * @extends module:core/plugin~Plugin
+ */
+export default class PendingActions extends Plugin {
+	/**
+	 * @inheritDoc
+	 */
+	static get pluginName() {
+		return 'PendingActions';
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	init() {
+		/**
+		 * Defines whether there is any registered pending action or not.
+		 *
+		 * @readonly
+		 * @observable
+		 * @type {Boolean} #isPending
+		 */
+		this.set( 'isPending', false );
+
+		/**
+		 * List of pending actions.
+		 *
+		 * @private
+		 * @type {module:utils/collection~Collection}
+		 */
+		this._actions = new Collection( { idProperty: '_id' } );
+	}
+
+	/**
+	 * Adds action to the list of pending actions.
+	 *
+	 * @param {String} message
+	 */
+	add( message ) {
+		if ( typeof message !== 'string' ) {
+			throw new CKEditorError( 'pendingactions-add-invalid-message: Message has to be a string.' );
+		}
+
+		const observable = Object.create( ObservableMixin );
+
+		observable.set( 'message', message );
+		this._actions.add( observable );
+		this.isPending = true;
+
+		return observable;
+	}
+
+	/**
+	 * Removes action from the list of pending actions.
+	 *
+	 * @param {Object} action Action object.
+	 */
+	remove( action ) {
+		this._actions.remove( action );
+		this.isPending = !!this._actions.length;
+	}
+
+	/**
+	 * Iterable interface.
+	 *
+	 * @returns {Iterable.<*>}
+	 */
+	[ Symbol.iterator ]() {
+		return this._actions[ Symbol.iterator ]();
+	}
+}

+ 103 - 0
packages/ckeditor5-core/tests/pendingactions.js

@@ -0,0 +1,103 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import VirtaulTestEditor 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 );
+	} );
+} );
+
+afterEach( () => {
+	return editor.destroy();
+} );
+
+describe( 'PendingActions', () => {
+	it( 'should define static pluginName property', () => {
+		expect( PendingActions ).to.have.property( 'pluginName', 'PendingActions' );
+	} );
+
+	describe( 'init()', () => {
+		it( 'should have isPending observable', () => {
+			const spy = sinon.spy();
+
+			pendingActions.on( 'change:isPending', spy );
+
+			expect( pendingActions ).to.have.property( 'isPending', false );
+
+			pendingActions.isPending = true;
+
+			sinon.assert.calledOnce( spy );
+		} );
+	} );
+
+	describe( 'add()', () => {
+		it( 'should register and return pending action', () => {
+			const action = pendingActions.add( 'Action' );
+
+			expect( action ).be.an( 'object' );
+			expect( action.message ).to.equal( 'Action' );
+		} );
+
+		it( 'should return observable', () => {
+			const spy = sinon.spy();
+			const action = pendingActions.add( 'Action' );
+
+			action.on( 'change:message', spy );
+
+			action.message = 'New message';
+
+			sinon.assert.calledOnce( spy );
+		} );
+
+		it( 'should update isPending observable', () => {
+			expect( pendingActions ).to.have.property( 'isPending', false );
+
+			pendingActions.add( 'Action' );
+
+			expect( pendingActions ).to.have.property( 'isPending', true );
+		} );
+
+		it( 'should throw an error when invalid message is given', () => {
+			expect( () => {
+				pendingActions.add( {} );
+			} ).to.throw( CKEditorError, /^pendingactions-add-invalid-message/ );
+		} );
+	} );
+
+	describe( 'remove()', () => {
+		it( 'should remove given pending action and update observable', () => {
+			const action1 = pendingActions.add( 'Action 1' );
+			const action2 = pendingActions.add( 'Action 2' );
+
+			expect( pendingActions ).to.have.property( 'isPending', true );
+
+			pendingActions.remove( action1 );
+
+			expect( pendingActions ).to.have.property( 'isPending', true );
+
+			pendingActions.remove( action2 );
+
+			expect( pendingActions ).to.have.property( 'isPending', false );
+		} );
+	} );
+
+	describe( 'iterator', () => {
+		it( 'should return all panding actions', () => {
+			pendingActions.add( 'Action 1' );
+			pendingActions.add( 'Action 2' );
+
+			expect( Array.from( pendingActions, action => action.message ) ).to.have.members( [ 'Action 1', 'Action 2' ] );
+		} );
+	} );
+} );