import * as tape from 'tape'; import * as ActivatableMixin from '@implab/core/components/ActivatableMixin'; import { AsyncComponent } from '@implab/core/components/AsyncComponent'; import { IActivationController } from '@implab/core/components/IActivationController'; import { IActivatable } from '@implab/core/components/IActivatable'; import { ICancellation } from '@implab/core/ICancellation'; import { EmptyCancellation } from '@implab/core/EmptyCancellation'; class SimpleActivatable extends ActivatableMixin(AsyncComponent) { } class MockActivationController implements IActivationController { _active: IActivatable = null; getActive() : IActivatable { return this._active; } async deactivate() { if (this._active) await this._active.deactivate(); this._active = null; } async activate(component: IActivatable) { if (!component || component.isActive()) return; component.setActivationController(this); await component.activate(); } async activating(component: IActivatable, ct: ICancellation = EmptyCancellation.default) { if (component != this._active) await this.deactivate(); } async activated(component: IActivatable, ct: ICancellation = EmptyCancellation.default) { this._active = component; } async deactivating(component: IActivatable, ct: ICancellation = EmptyCancellation.default) { } async deactivated(component: IActivatable, ct: ICancellation = EmptyCancellation.default) { if (this._active == component) this._active = null; } } tape('simple activation',async function(t){ let a = new SimpleActivatable(); t.false(a.isActive()); await a.activate(); t.true(a.isActive()); await a.deactivate(); t.false(a.isActive()); t.end(); }); tape('controller activation', async function(t) { let a = new SimpleActivatable(); let c = new MockActivationController(); t.false(a.isActive(), "the component is not active by default"); t.assert(c.getActive() == null, "the activation controller doesn't have an active component by default"); t.assert(a.getActivationController() == null, "the component doesn't have an activation controller by default"); t.comment("Active the component through the controller"); await c.activate(a); t.true(a.isActive(), "The component should successfully activate"); t.assert(c.getActive() == a, "The controller should point to the activated component"); t.assert(a.getActivationController() == c, "The component should point to the controller"); t.comment("Deactive the component throug the controller"); await c.deactivate(); t.false(a.isActive(), "The component should successfully deactivate"); t.assert(c.getActive() == null, "The controller shouldn't point to any component"); t.assert(a.getActivationController() == c, "The componet should point to it's controller"); t.end(); }); tape('handle error in onActivating', async function(t) { let a = new SimpleActivatable(); a.onActivating = async function() { throw "Should fail"; }; try { await a.activate(); t.fail("activation should fail"); } catch { } t.false(a.isActive(), "the component should remain inactive"); t.end(); });