/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; under version 2 * of the License (non-upgradable). * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright (c) 2018 (original work) Open Assessment Technlogies SA * */ /** * Test the module {@link layout/actions} * * @author Bertrand Chevrier */ define(['jquery', 'layout/actions', 'layout/actions/binder'], function($, actionsManager, binder) { 'use strict'; QUnit.module('API'); QUnit.test('module', function(assert) { assert.ok(typeof actionsManager === 'object', 'The module expose a plain object'); }); QUnit.cases.init([ {title: 'on'}, {title: 'off'}, {title: 'trigger'}, {title: 'before'}, {title: 'after'}, {title: 'removeAllListeners'} ]).test('Eventifier API ', function(data, assert) { assert.equal(typeof actionsManager[data.title], 'function', 'The module exposes the eventifier method "' + data.title); }); QUnit.cases.init([ {title: 'init'}, {title: 'updateState'}, {title: 'updateContext'}, {title: 'exec'}, {title: 'getBy'} ]).test('Instance API ', function(data, assert) { assert.equal(typeof actionsManager[data.title], 'function', 'The module exposes the method "' + data.title + '"'); }); QUnit.module('Behavior', { afterEach: function(assert) { actionsManager.removeAllListeners(); } }); QUnit.test('Load actions and update context', function(assert) { assert.expect(10); assert.equal(actionsManager.getBy('foo-new'), null, 'The foo-new action is not bound'); assert.equal(actionsManager.getBy('foo-delete'), null, 'The foo-delete action is not bound'); assert.equal(actionsManager.getBy('foo-special'), null, 'The foo-special action is not bound'); actionsManager.init($('#qunit-fixture')); assert.deepEqual(actionsManager.getBy('foo-new'), { id: 'foo-new', name: 'New Foo', binding: 'addFoo', url: 'https://foo.org/taoFoo/Foo/new', context: 'resource', multiple: false, rights: {id: 'WRITE'}, state: { disabled: false, hidden: true, active: false } }, 'The foo-new action is now bound'); assert.deepEqual(actionsManager.getBy('foo-delete'), { id: 'foo-delete', name: 'Delete', binding: 'deleteFoo', url: 'https://foo.org/taoFoo/Foo/delete', context: 'instance', multiple: false, rights: {id: 'WRITE'}, state: { disabled: false, hidden: true, active: false } }, 'The foo-delete action is now bound'); assert.deepEqual(actionsManager.getBy('foo-special'), { id: 'foo-special', name: 'Special', binding: 'special', url: 'https://foo.org/taoFoo/Foo/special', context: 'class', multiple: false, rights: { }, state: { disabled: true, hidden: true, active: false } }, 'The foo-special action is now bound'); actionsManager.updateContext({ type: 'instance', uri: 'https://foo.org/Foo#123' }); assert.equal(actionsManager.getBy('foo-new').state.hidden, false, 'The new action is now visible'); assert.equal(actionsManager.getBy('foo-delete').state.hidden, false, 'The delete action is now visible'); assert.equal(actionsManager.getBy('foo-special').state.hidden, true, 'The special action is not visible'); assert.equal(actionsManager.getBy('foo-special').state.disabled, true, 'The special action remains disabled'); }); QUnit.test('execute an action', function(assert) { var ready = assert.async(); var context = { type: 'instance', uri: 'https://foo.org/Foo#123' }; assert.expect(4); binder.register('addFoo', function(receivedContext) { assert.deepEqual(this, { id: 'foo-new', name: 'New Foo', binding: 'addFoo', url: 'https://foo.org/taoFoo/Foo/new', context: 'resource', multiple: false, rights: {id: 'WRITE'}, state: { disabled: false, hidden: false, active: true } }, 'The executed action has the actionContext as lexical scope'); assert.deepEqual(context, receivedContext, 'The received context matches the current'); return new Promise(function(resolve) { setTimeout(resolve, 10); }); }); actionsManager.init($('#qunit-fixture')); actionsManager.updateContext(context); actionsManager .on('foo-new', function(receivedContext) { assert.deepEqual(context, receivedContext, 'The received context matches the current'); }) .on('error', function(err) { assert.ok(false, err.message); ready(); }) .exec('foo-new') .then(function() { assert.ok(true, 'exec always return a resolved promise'); ready(); }); }); QUnit.test('cancel an action', function(assert) { var ready = assert.async(); assert.expect(3); binder.register('deleteFoo', function() { return new Promise(function(resolve, reject) { assert.ok(true, 'The delete action is executed'); setTimeout(function() { reject({cancel: true}); }, 10); }); }); actionsManager.init($('#qunit-fixture')); actionsManager .on('foo-delete', function() { assert.ok(false, 'The action is canceled so the event should not be triggered'); ready(); }) .on('error', function() { assert.ok(false, 'The action is canceled so the error event should not be triggered'); ready(); }) .on('cancel', function(actionId) { assert.equal(actionId, 'foo-delete', 'The correct action has been canceled'); }) .exec('foo-delete') .then(function() { assert.ok(true, 'exec always return a resolved promise'); ready(); }); }); QUnit.test('fail an action', function(assert) { var ready = assert.async(); assert.expect(4); binder.register('deleteFoo', function() { return new Promise(function(resolve, reject) { assert.ok(true, 'The delete action is executed'); setTimeout(function() { reject(new TypeError('out of bound')); }, 10); }); }); actionsManager.init($('#qunit-fixture')); actionsManager .on('foo-delete', function() { assert.ok(false, 'The action fail so the action event should not be triggered'); ready(); }) .on('error', function(err) { assert.ok(err instanceof TypeError, 'The action rejects with the correct error.'); assert.equal(err.message, 'out of bound', 'The error message matches.'); }) .on('cancel', function() { assert.ok(false, 'The action should not cancel'); ready(); }) .exec('foo-delete') .then(function() { assert.ok(true, 'exec always return a resolved promise, even if failed'); ready(); }); }); });