From d123fbf02d6aee37c1d9e7ea12cc4c600b183e69 Mon Sep 17 00:00:00 2001 From: azu Date: Sun, 20 Nov 2016 20:34:04 +0900 Subject: [PATCH] feat(Dispatcher): Introduce DispatcherPayloadMeta - Add DispatcherPayloadMeta.js - Dispatcher User dispatch `payload` and `meta`. refs #61 --- src/Context.js | 35 ++++++++--------- src/Dispatcher.js | 28 +++++++++----- src/DispatcherPayloadMeta.js | 37 ++++++++++++++++++ src/Store.js | 6 +-- src/UILayer/QueuedStoreGroup.js | 6 +-- src/UseCase.js | 7 +++- src/UseCaseExecutor.js | 38 ++++++++++-------- test/Context-test.js | 66 ++++++++++++++++---------------- test/Dispatcher-test.js | 16 ++++---- test/QueuedStoreGroup-test.js | 48 +++++++++++------------ test/Store-test.js | 8 ++-- test/StoreGroup-test.js | 28 +++++++------- test/StoreGroupValidator-test.js | 16 ++++---- test/UseCase-test.js | 33 ++++++++-------- test/UseCaseExecutor-test.js | 18 ++++----- 15 files changed, 223 insertions(+), 167 deletions(-) create mode 100644 src/DispatcherPayloadMeta.js diff --git a/src/Context.js b/src/Context.js index fbe527814..cc466a078 100755 --- a/src/Context.js +++ b/src/Context.js @@ -25,7 +25,7 @@ export default class Context { * @param {QueuedStoreGroup|StoreGroup|Store} store store is either Store or StoreGroup * @public */ - constructor({dispatcher, store}) { + constructor({ dispatcher, store }) { StoreGroupValidator.validateInstance(store); // central dispatcher this._dispatcher = dispatcher; @@ -82,13 +82,13 @@ export default class Context { /** * called the {@link handler} with useCase when the useCase will do. - * @param {function(useCase: UseCase, args: *)} handler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @public */ onWillExecuteEachUseCase(handler) { - const releaseHandler = this._dispatcher.onDispatch(payload => { + const releaseHandler = this._dispatcher.onDispatch((payload, meta) => { if (payload.type === ActionTypes.ON_WILL_EXECUTE_EACH_USECASE) { - handler(payload.useCase, payload.args); + handler(payload, meta); } }); this._releaseHandlers.push(releaseHandler); @@ -100,16 +100,16 @@ export default class Context { * This `onDispatch` is not called at built-in event. It is filtered by Context. * If you want to *All* dispatched event and use listen directly your `dispatcher` object. * In other word, listen the dispatcher of `new Context({dispatcher})`. - * @param {function(payload: DispatcherPayload)} handler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @returns {Function} * @public */ onDispatch(handler) { - const releaseHandler = this._dispatcher.onDispatch(payload => { + const releaseHandler = this._dispatcher.onDispatch((payload, meta) => { // call handler, if payload's type is not built-in event. // It means that `onDispatch` is called when dispatching user event. if (ActionTypes[payload.type] === undefined) { - handler(payload); + handler(payload, meta); } }); this._releaseHandlers.push(releaseHandler); @@ -118,13 +118,13 @@ export default class Context { /** * called the `handler` with useCase when the useCase is executed.. - * @param {function(useCase: UseCase)} handler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @public */ onDidExecuteEachUseCase(handler) { - const releaseHandler = this._dispatcher.onDispatch(payload => { + const releaseHandler = this._dispatcher.onDispatch((payload, meta) => { if (payload.type === ActionTypes.ON_DID_EXECUTE_EACH_USECASE) { - handler(payload.useCase); + handler(payload, meta); } }); this._releaseHandlers.push(releaseHandler); @@ -133,13 +133,13 @@ export default class Context { /** * called the `handler` with useCase when the useCase is completed. - * @param {function(useCase: UseCase)} handler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @public */ onCompleteEachUseCase(handler) { - const releaseHandler = this._dispatcher.onDispatch(payload => { + const releaseHandler = this._dispatcher.onDispatch((payload, meta) => { if (payload.type === ActionTypes.ON_COMPLETE_EACH_USECASE) { - handler(payload.useCase); + handler(payload, meta); } }); this._releaseHandlers.push(releaseHandler); @@ -147,17 +147,16 @@ export default class Context { } - /** * called the `errorHandler` with error when error is occurred. - * @param {function(payload: UseCaseErrorPayload)} errorHandler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @returns {function(this:Dispatcher)} * @public */ - onErrorDispatch(errorHandler) { - const releaseHandler = this._dispatcher.onDispatch(payload => { + onErrorDispatch(handler) { + const releaseHandler = this._dispatcher.onDispatch((payload, meta) => { if (payload.type === ActionTypes.ON_ERROR) { - errorHandler(payload); + handler(payload, meta); } }); this._releaseHandlers.push(releaseHandler); diff --git a/src/Dispatcher.js b/src/Dispatcher.js index eadd8ed22..94c80475d 100755 --- a/src/Dispatcher.js +++ b/src/Dispatcher.js @@ -2,11 +2,13 @@ "use strict"; const assert = require("assert"); const EventEmitter = require("events"); +import DispatcherPayloadMeta from "./DispatcherPayloadMeta"; export const ON_DISPATCH = "__ON_DISPATCH__"; /** - * payload The payload object that must have `type` property. + * DispatcherPayload is an object. + * The payload object that must have `type` property. + * `type` property is a good idea to use string constants or Symbol for dispatch types. * @typedef {Object} DispatcherPayload - * @property {*} type The event type to dispatch. * @public */ /** @@ -52,27 +54,33 @@ export default class Dispatcher extends EventEmitter { /** * add onAction handler and return unbind function - * @param {function(payload: DispatcherPayload)} payloadHandler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @returns {Function} call the function and release handler * @public */ - onDispatch(payloadHandler) { - this.on(ON_DISPATCH, payloadHandler); - return this.removeListener.bind(this, ON_DISPATCH, payloadHandler); + onDispatch(handler) { + this.on(ON_DISPATCH, handler); + return this.removeListener.bind(this, ON_DISPATCH, handler); } /** * dispatch action object. * StoreGroups receive this action and reduce state. * @param {DispatcherPayload} payload + * @param {DispatcherPayloadMeta} [meta] * @public */ - dispatch(payload) { + dispatch(payload, meta) { if (process.env.NODE_ENV !== "production") { assert(payload !== undefined && payload !== null, "payload should not null or undefined"); assert(typeof payload.type !== "undefined", "payload's `type` should be required"); } - this.emit(ON_DISPATCH, payload); + if (meta === undefined) { + const dispatchOnlyMeta = new DispatcherPayloadMeta(); + this.emit(ON_DISPATCH, payload, dispatchOnlyMeta); + } else { + this.emit(ON_DISPATCH, payload, meta); + } } /** @@ -85,9 +93,9 @@ export default class Dispatcher extends EventEmitter { const fromName = this.constructor.name; const toName = toDispatcher.constructor.name; const displayName = `delegate-payload:${fromName}-to-${toName}`; - const delegatePayload = function delegatePayload(payload) { + const delegatePayload = function delegatePayload(payload, meta) { delegatePayload.displayName = displayName; - toDispatcher.dispatch(payload); + toDispatcher.dispatch(payload, meta); }; return this.onDispatch(delegatePayload); } diff --git a/src/DispatcherPayloadMeta.js b/src/DispatcherPayloadMeta.js new file mode 100644 index 000000000..fab4d5a44 --- /dev/null +++ b/src/DispatcherPayloadMeta.js @@ -0,0 +1,37 @@ +// LICENSE : MIT +"use strict"; +/** + * DispatcherPayloadMeta is a meta object for dispatcher. + * This object is always created by System(= Almin). + * The user can get this meta object together with dispatched `payload` object + * @example + * context.onDispatch((payload, meta) => {}); + */ +export default class DispatcherPayloadMeta { + /** + * @param {UseCase} [useCase] + * @param {UseCase|Dispatcher} [parentDispatcher] + */ + constructor({ + useCase, + parentDispatcher + } = {}) { + /** + * @param {UseCase|Dispatcher|null|undefined} useCase A reference to the useCase/dispatcher to which the payload was originally dispatched. + * @public + */ + this.useCase = useCase; + /** + * Parent dispatcher/useCase of the `this.useCase`, + * @param {UseCase|Dispatcher|null|undefined} + * @public + */ + this.parentDispatcher = parentDispatcher; + /** + * timeStamp is created time of the meta. + * @type {number} + * @public + */ + this.timeStamp = Date.now(); + } +} \ No newline at end of file diff --git a/src/Store.js b/src/Store.js index cd972770a..9ea60eb14 100755 --- a/src/Store.js +++ b/src/Store.js @@ -68,7 +68,7 @@ export default class Store extends Dispatcher { /** * invoke `handler` when UseCase throw error events. - * @param {function(payload: UseCaseErrorPayload)} handler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @returns {Function} call the function and release handler * @public * @example @@ -80,9 +80,9 @@ export default class Store extends Dispatcher { * }): */ onError(handler) { - return this.onDispatch(payload => { + return this.onDispatch((payload, meta) => { if (payload.type === ActionTypes.ON_ERROR) { - handler(payload); + handler(payload, meta); } }); } diff --git a/src/UILayer/QueuedStoreGroup.js b/src/UILayer/QueuedStoreGroup.js index c510b93a0..a207f010a 100644 --- a/src/UILayer/QueuedStoreGroup.js +++ b/src/UILayer/QueuedStoreGroup.js @@ -95,7 +95,7 @@ export default class QueuedStoreGroup extends Dispatcher { this._stateCache = new LRU(100); // `this` can catch the events of dispatchers // Because context delegate dispatched events to **this** - const tryToEmitChange = (payload) => { + const tryToEmitChange = (payload, meta) => { // check stores, if payload's type is not built-in event. // It means that `onDispatch` is called when dispatching user event. if (ActionTypes[payload.type] === undefined) { @@ -107,7 +107,7 @@ export default class QueuedStoreGroup extends Dispatcher { this.emitChange(); } } else if (payload.type === ActionTypes.ON_DID_EXECUTE_EACH_USECASE) { - const parent = payload.parent; + const parent = meta.parentDispatcher; // when {asap: false}, emitChange when root useCase is executed if (!asap && parent) { return; @@ -116,7 +116,7 @@ export default class QueuedStoreGroup extends Dispatcher { this.emitChange(); } } else if (payload.type === ActionTypes.ON_COMPLETE_EACH_USECASE) { - const parent = payload.parent; + const parent = meta.parentDispatcher; // when {asap: false}, emitChange when root useCase is executed if (!asap && parent) { return; diff --git a/src/UseCase.js b/src/UseCase.js index 690da01dc..70b5876cd 100644 --- a/src/UseCase.js +++ b/src/UseCase.js @@ -3,6 +3,7 @@ import Dispatcher from "./Dispatcher"; import UseCaseContext from "./UseCaseContext"; import {ActionTypes} from "./Context"; +import DispatcherPayloadMeta from "./DispatcherPayloadMeta"; /** * @type {string} * @private @@ -97,14 +98,16 @@ export default class UseCase extends Dispatcher { * @public */ throwError(error) { + const meta = new DispatcherPayloadMeta({ + useCase: this + }); /** * @type {UseCaseErrorPayload} */ const payload = { type: ActionTypes.ON_ERROR, - useCase: this, error: error }; - this.dispatch(payload); + this.dispatch(payload, meta); } } \ No newline at end of file diff --git a/src/UseCaseExecutor.js b/src/UseCaseExecutor.js index 3797301f2..84f9a0265 100644 --- a/src/UseCaseExecutor.js +++ b/src/UseCaseExecutor.js @@ -4,6 +4,7 @@ const assert = require("assert"); import {ActionTypes} from "./Context"; import Dispatcher from "./Dispatcher"; import UseCase from "./UseCase"; +import DispatcherPayloadMeta from "./DispatcherPayloadMeta"; /** * UseCaseExecutor is a helper class for executing UseCase. * @public @@ -61,12 +62,15 @@ export default class UseCaseExecutor { */ willExecute(args) { // emit event for System - this.disptcher.dispatch({ - type: ActionTypes.ON_WILL_EXECUTE_EACH_USECASE, + const meta = new DispatcherPayloadMeta({ useCase: this.useCase, - parent: this.parentUseCase, + parentDispatcher: this.parentUseCase, args }); + this.disptcher.dispatch({ + type: ActionTypes.ON_WILL_EXECUTE_EACH_USECASE, + args + }, meta); } /** @@ -74,11 +78,13 @@ export default class UseCaseExecutor { * @private */ didExecute() { - this.disptcher.dispatch({ - type: ActionTypes.ON_DID_EXECUTE_EACH_USECASE, + const meta = new DispatcherPayloadMeta({ useCase: this.useCase, - parent: this.parentUseCase + parentDispatcher: this.parentUseCase }); + this.disptcher.dispatch({ + type: ActionTypes.ON_DID_EXECUTE_EACH_USECASE + }, meta); } /** @@ -86,11 +92,13 @@ export default class UseCaseExecutor { * @private */ complete() { - this.disptcher.dispatch({ - type: ActionTypes.ON_COMPLETE_EACH_USECASE, + const meta = new DispatcherPayloadMeta({ useCase: this.useCase, - parent: this.parentUseCase + parentDispatcher: this.parentUseCase }); + this.disptcher.dispatch({ + type: ActionTypes.ON_COMPLETE_EACH_USECASE + }, meta); } /** @@ -110,13 +118,13 @@ export default class UseCaseExecutor { /** * called the `handler` with useCase when the useCase is executed. - * @param {function(useCase: UseCase)} handler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @public */ onDidExecuteEachUseCase(handler) { - const releaseHandler = this.disptcher.onDispatch(function onDidExecuted(payload) { + const releaseHandler = this.disptcher.onDispatch(function onDidExecuted(payload, meta) { if (payload.type === ActionTypes.ON_DID_EXECUTE_EACH_USECASE) { - handler(payload.useCase); + handler(payload, meta); } }); this._releaseHandlers.push(releaseHandler); @@ -125,14 +133,14 @@ export default class UseCaseExecutor { /** * called the `handler` with useCase when the useCase is completed. - * @param {function(useCase: UseCase)} handler + * @param {function(payload: DispatcherPayload, meta: DispatcherPayloadMeta)} handler * @returns {Function} * @public */ onCompleteExecuteEachUseCase(handler) { - const releaseHandler = this.disptcher.onDispatch(function onCompleted(payload) { + const releaseHandler = this.disptcher.onDispatch(function onCompleted(payload, meta) { if (payload.type === ActionTypes.ON_COMPLETE_EACH_USECASE) { - handler(payload.useCase); + handler(payload, meta); } }); this._releaseHandlers.push(releaseHandler); diff --git a/test/Context-test.js b/test/Context-test.js index dae503c7a..6df1da1e7 100644 --- a/test/Context-test.js +++ b/test/Context-test.js @@ -22,9 +22,9 @@ class ThrowUseCase extends UseCase { this.throwError(new Error("test")); } } -describe("Context", function () { - describe("dispatch in UseCase", function () { - it("should dispatch Store", function (done) { +describe("Context", function() { + describe("dispatch in UseCase", function() { + it("should dispatch Store", function(done) { const dispatcher = new Dispatcher(); const DISPATCHED_EVENT = { type: "update", @@ -56,13 +56,13 @@ describe("Context", function () { appContext.useCase(new DispatchUseCase()).execute(); }); }); - describe("#getStates", function () { - it("should get a single state from State", function () { + describe("#getStates", function() { + it("should get a single state from State", function() { const dispatcher = new Dispatcher(); const expectedMergedObject = { "1": 1 }; - const store = createEchoStore({echo: {"1": 1}}); + const store = createEchoStore({ echo: { "1": 1 } }); const appContext = new Context({ dispatcher, store @@ -71,10 +71,10 @@ describe("Context", function () { assert.deepEqual(states, expectedMergedObject); }); }); - describe("#onChange", function () { - it("should called when change some State", function (done) { + describe("#onChange", function() { + it("should called when change some State", function(done) { const dispatcher = new Dispatcher(); - const testStore = createEchoStore({echo: {"1": 1}}); + const testStore = createEchoStore({ echo: { "1": 1 } }); const storeGroup = new StoreGroup([testStore]); const appContext = new Context({ dispatcher, @@ -87,10 +87,10 @@ describe("Context", function () { }); testStore.emitChange(); }); - it("should thin change events are happened at same time", function (done) { + it("should thin change events are happened at same time", function(done) { const dispatcher = new Dispatcher(); - const aStore = createEchoStore({name: "AStore", echo: {"1": 1}}); - const bStore = createEchoStore({name: "BStore", echo: {"1": 1}}); + const aStore = createEchoStore({ name: "AStore", echo: { "1": 1 } }); + const bStore = createEchoStore({ name: "BStore", echo: { "1": 1 } }); const storeGroup = new StoreGroup([aStore, bStore]); const appContext = new Context({ dispatcher, @@ -105,8 +105,8 @@ describe("Context", function () { bStore.emitChange(); }); }); - describe("#onWillExecuteEachUseCase", function () { - it("should called before UseCase will execute", function (done) { + describe("#onWillExecuteEachUseCase", function() { + it("should called before UseCase will execute", function(done) { const dispatcher = new Dispatcher(); const appContext = new Context({ dispatcher, @@ -114,16 +114,16 @@ describe("Context", function () { }); const testUseCase = new TestUseCase(); // then - appContext.onWillExecuteEachUseCase(useCase => { - assert.equal(useCase, testUseCase); + appContext.onWillExecuteEachUseCase((payload, meta) => { + assert.equal(meta.useCase, testUseCase); done(); }); // when appContext.useCase(testUseCase).execute(); }); }); - describe("#onDispatch", function () { - it("should called the other of built-in event", function (done) { + describe("#onDispatch", function() { + it("should called the other of built-in event", function(done) { const dispatcher = new Dispatcher(); const appContext = new Context({ dispatcher, @@ -139,23 +139,23 @@ describe("Context", function () { } const eventUseCase = new EventUseCase(); // then - appContext.onWillExecuteEachUseCase(useCase => { - assert.equal(useCase, eventUseCase); + appContext.onWillExecuteEachUseCase((payload, meta) => { + assert.equal(meta.useCase, eventUseCase); }); // onDispatch should not called when UseCase will/did execute. appContext.onDispatch(payload => { assert.equal(payload, expectedPayload); }); - appContext.onDidExecuteEachUseCase(useCase => { - assert.equal(useCase, eventUseCase); + appContext.onDidExecuteEachUseCase((payload, meta) => { + assert.equal(meta.useCase, eventUseCase); done(); }); // when appContext.useCase(eventUseCase).execute(); }); }); - describe("#onDidExecuteEachUseCase", function () { - it("should called after UseCase did execute", function (done) { + describe("#onDidExecuteEachUseCase", function() { + it("should called after UseCase did execute", function(done) { const dispatcher = new Dispatcher(); const appContext = new Context({ dispatcher, @@ -163,16 +163,16 @@ describe("Context", function () { }); const testUseCase = new TestUseCase(); // then - appContext.onDidExecuteEachUseCase(useCase => { - assert.equal(useCase, testUseCase); + appContext.onDidExecuteEachUseCase((payload, meta) => { + assert.equal(meta.useCase, testUseCase); done(); }); // when appContext.useCase(testUseCase).execute(); }); }); - describe("#onError", function () { - it("should called after UseCase did execute", function (done) { + describe("#onError", function() { + it("should called after UseCase did execute", function(done) { const dispatcher = new Dispatcher(); const appContext = new Context({ dispatcher, @@ -180,21 +180,21 @@ describe("Context", function () { }); const throwUseCase = new ThrowUseCase(); // then - appContext.onErrorDispatch(payload => { + appContext.onErrorDispatch((payload, meta) => { assert(payload.error instanceof Error); - assert.equal(payload.useCase, throwUseCase); + assert.equal(meta.useCase, throwUseCase); done(); }); // when appContext.useCase(throwUseCase).execute(); }); }); - describe("#useCase", function () { - it("should return UseCaseExecutor", function () { + describe("#useCase", function() { + it("should return UseCaseExecutor", function() { const dispatcher = new Dispatcher(); const appContext = new Context({ dispatcher, - store: createEchoStore({echo: {"1": 1}}) + store: createEchoStore({ echo: { "1": 1 } }) }); const useCaseExecutor = appContext.useCase(new ThrowUseCase()); assert(useCaseExecutor instanceof UseCaseExecutor); diff --git a/test/Dispatcher-test.js b/test/Dispatcher-test.js index 1c37f5588..1265c9bd5 100644 --- a/test/Dispatcher-test.js +++ b/test/Dispatcher-test.js @@ -2,9 +2,9 @@ "use strict"; const assert = require("assert"); import Dispatcher from "../src/Dispatcher"; -describe("Dispatcher", function () { - describe("#onDispatch", function () { - it("should return un-listen function", function () { +describe("Dispatcher", function() { + describe("#onDispatch", function() { + it("should return un-listen function", function() { const dispatcher = new Dispatcher(); const unListen = dispatcher.onDispatch(() => { // should not called @@ -13,11 +13,11 @@ describe("Dispatcher", function () { // when unListen(); // then - dispatcher.dispatch({type: "???"}); + dispatcher.dispatch({ type: "???" }); }); }); - describe("#dispatch", function () { - it("should dispatch with payload object, otherwise throw error", function () { + describe("#dispatch", function() { + it("should dispatch with payload object, otherwise throw error", function() { const dispatcher = new Dispatcher(); try { dispatcher.dispatch("it is not payload"); @@ -26,7 +26,7 @@ describe("Dispatcher", function () { assert(error.message !== "UNREACHED"); } }); - it("should dispatch with payload object that has type propery", function (done) { + it("should dispatch with payload object that has type propery", function(done) { const dispatcher = new Dispatcher(); const expectedPayload = { type: { /* string Symbol anything */ } @@ -37,7 +37,7 @@ describe("Dispatcher", function () { }); dispatcher.dispatch(expectedPayload); }); - it("should pass payload object to listening handler", function (done) { + it("should pass payload object to listening handler", function(done) { const dispatcher = new Dispatcher(); const expectedPayload = { type: "pay", diff --git a/test/QueuedStoreGroup-test.js b/test/QueuedStoreGroup-test.js index fc9d558e3..147d7d2e8 100644 --- a/test/QueuedStoreGroup-test.js +++ b/test/QueuedStoreGroup-test.js @@ -30,7 +30,7 @@ describe("QueuedStoreGroup", function() { context("when StoreGroup#emitChange()", function() { context("some store is changed", function() { it("should be called by sync", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isCalled = false; // then @@ -45,7 +45,7 @@ describe("QueuedStoreGroup", function() { }); context("any store is not changed", function() { it("should be called by sync", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isCalled = false; // then @@ -61,7 +61,7 @@ describe("QueuedStoreGroup", function() { }); context("when UseCase never change any store", function() { it("should not be called", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isCalled = false; // then @@ -86,7 +86,7 @@ describe("QueuedStoreGroup", function() { // sync context("when SyncUseCase change the store", function() { it("should be called by sync", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isCalled = false; // then @@ -107,7 +107,7 @@ describe("QueuedStoreGroup", function() { // async context("when ASyncUseCase change the store", function() { it("should be called by async", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isCalled = false; storeGroup.onChange(() => { @@ -131,8 +131,8 @@ describe("QueuedStoreGroup", function() { context("when UseCase is nesting", function() { context("{ asap: true }", function() { it("should be called by all usecase", function() { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new QueuedStoreGroup([aStore, bStore], { asap: true }); @@ -163,8 +163,8 @@ describe("QueuedStoreGroup", function() { }); context("{ asap: false }", function() { it("should be called only once", function() { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new QueuedStoreGroup([aStore, bStore]); let onChangeCounter = 0; storeGroup.onChange((changedStores) => { @@ -194,7 +194,7 @@ describe("QueuedStoreGroup", function() { }); context("when UseCase#dispatch is called", function() { it("should not be called - no changing store", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isChanged = false; let dispatchedPayload = null; @@ -231,7 +231,7 @@ describe("QueuedStoreGroup", function() { return resultPromise }); it("should be called by sync", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isCalled = false; storeGroup.onChange(() => { @@ -263,7 +263,7 @@ describe("QueuedStoreGroup", function() { return resultPromise }); it("should be called each dispatch", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let calledCount = 0; storeGroup.onChange(() => { @@ -298,7 +298,7 @@ describe("QueuedStoreGroup", function() { }); context("when UseCase is failing", function() { it("should be called", function() { - const aStore = createEchoStore({name: "AStore"}); + const aStore = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([aStore]); let onChangeCounter = 0; storeGroup.onChange((changedStores) => { @@ -326,7 +326,7 @@ describe("QueuedStoreGroup", function() { }); context("when UseCase call `throwError()", function() { it("should be called", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); let isCalled = false; // then @@ -352,8 +352,8 @@ describe("QueuedStoreGroup", function() { }); context("WhiteBox testing", function() { it("should thin out change events at once", function() { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new QueuedStoreGroup([aStore, bStore]); class ChangeABUseCase extends UseCase { execute() { @@ -383,7 +383,7 @@ describe("QueuedStoreGroup", function() { }); context("Sync Change and Async Change in Edge case", function() { it("should emit Change twice", function() { - const store = createEchoStore({name: "AStore"}); + const store = createEchoStore({ name: "AStore" }); const storeGroup = new QueuedStoreGroup([store]); const asyncUseCase = createAsyncChangeStoreUseCase(store); class ChangeTheStoreUseCase extends UseCase { @@ -413,9 +413,9 @@ describe("QueuedStoreGroup", function() { }); context("Flow example", function() { it("should output", function() { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); - const cStore = createEchoStore({name: "CStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); + const cStore = createEchoStore({ name: "CStore" }); const storeGroup = new QueuedStoreGroup([aStore, bStore, cStore]); class ParentUseCase extends UseCase { execute() { @@ -481,12 +481,12 @@ describe("QueuedStoreGroup", function() { it("should return a single state object", function() { class AStore extends Store { getState() { - return {a: "a value"}; + return { a: "a value" }; } } class BStore extends Store { getState() { - return {b: "b value"}; + return { b: "b value" }; } } const aStore = new AStore(); @@ -535,8 +535,8 @@ describe("QueuedStoreGroup", function() { }); describe("#release", function() { it("release onChange handler", function() { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new QueuedStoreGroup([aStore, bStore]); // then - called change handler a one-time let isCalled = false; diff --git a/test/Store-test.js b/test/Store-test.js index 3fd7c5603..3d0a847d1 100644 --- a/test/Store-test.js +++ b/test/Store-test.js @@ -80,8 +80,8 @@ describe("Store", function() { // delegate testUseCase.pipe(store); // then - store.onError(payload => { - assert(payload.useCase instanceof TestUseCase); + store.onError((payload, meta) => { + assert(meta.useCase instanceof TestUseCase); assert.equal(payload.error.name, "DomainError"); done(); }); @@ -102,8 +102,8 @@ describe("Store", function() { // delegate testUseCase.pipe(store); // then - store.onError((payload) => { - assert(payload.useCase instanceof TestUseCase); + store.onError((payload, meta) => { + assert(meta.useCase instanceof TestUseCase); assert.equal(payload.error.name, "DomainError"); done(); }); diff --git a/test/StoreGroup-test.js b/test/StoreGroup-test.js index df6dd7c10..e12f4c5f9 100644 --- a/test/StoreGroup-test.js +++ b/test/StoreGroup-test.js @@ -9,8 +9,8 @@ describe("StoreGroup", function() { describe("#onChange", function() { context("when some store emitChange()", function() { it("should async called StoreGroup#onChange", function(done) { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new StoreGroup([aStore, bStore]); // Should be failure, if emit -> onChange **sync**. // But it is called async @@ -27,8 +27,8 @@ describe("StoreGroup", function() { it("should async called onChange after 2nd", function(done) { // it should work cache temporary. // test _prunePreviousCache - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new StoreGroup([aStore, bStore]); const test1 = (callback) => { // Should be failure, if emit -> onChange **sync**. @@ -62,8 +62,8 @@ describe("StoreGroup", function() { }) }); it("should thin out change events at once", function(done) { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new StoreGroup([aStore, bStore]); // then - called change handler a one-time storeGroup.onChange((changedStores) => { @@ -80,12 +80,12 @@ describe("StoreGroup", function() { it("should return a single state object", function() { class AStore extends Store { getState() { - return {a: "a value"}; + return { a: "a value" }; } } class BStore extends Store { getState() { - return {b: "b value"}; + return { b: "b value" }; } } const aStore = new AStore(); @@ -137,7 +137,7 @@ describe("StoreGroup", function() { let aCalledCount = 0; let bCalledCount = 0; class AState { - constructor({count}) { + constructor({ count }) { this.count = count; } } @@ -146,12 +146,12 @@ describe("StoreGroup", function() { getState() { aCalledCount = aCalledCount + 1; return { - AState: new AState({count: aCalledCount}) + AState: new AState({ count: aCalledCount }) } } } class BState { - constructor({count}) { + constructor({ count }) { this.count = count; } } @@ -159,7 +159,7 @@ describe("StoreGroup", function() { getState() { bCalledCount = bCalledCount + 1; return { - BState: new BState({count: bCalledCount}) + BState: new BState({ count: bCalledCount }) }; } } @@ -183,8 +183,8 @@ describe("StoreGroup", function() { }); describe("#release", function() { it("release onChange handler", function() { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new StoreGroup([aStore, bStore]); // then - called change handler a one-time let isCalled = false; diff --git a/test/StoreGroupValidator-test.js b/test/StoreGroupValidator-test.js index e8a1888b5..ae1c3b0de 100644 --- a/test/StoreGroupValidator-test.js +++ b/test/StoreGroupValidator-test.js @@ -5,18 +5,18 @@ import Store from "../src/Store"; import StoreGroup from "../src/UILayer/StoreGroup"; import StoreGroupValidator from "../src/UILayer/StoreGroupValidator"; import createEchoStore from "./helper/EchoStore"; -describe("StoreGroupValidator", function () { - describe("validateInstance", function () { - context("when store is argument", function () { - it("should not throw", function () { +describe("StoreGroupValidator", function() { + describe("validateInstance", function() { + context("when store is argument", function() { + it("should not throw", function() { const store = new Store(); StoreGroupValidator.validateInstance(store); }); }); - context("when storeGroup is argument", function () { - it("should not throw", function () { - const aStore = createEchoStore({name: "AStore"}); - const bStore = createEchoStore({name: "BStore"}); + context("when storeGroup is argument", function() { + it("should not throw", function() { + const aStore = createEchoStore({ name: "AStore" }); + const bStore = createEchoStore({ name: "BStore" }); const storeGroup = new StoreGroup([aStore, bStore]); StoreGroupValidator.validateInstance(storeGroup); }); diff --git a/test/UseCase-test.js b/test/UseCase-test.js index 63a1f03e0..20085614f 100644 --- a/test/UseCase-test.js +++ b/test/UseCase-test.js @@ -4,11 +4,11 @@ const assert = require("power-assert"); import UseCase from "../src/UseCase"; import Dispatcher from "../src/Dispatcher"; import Store from "../src/Store"; -import Context from "../src/Context"; +import Context, {ActionTypes} from "../src/Context"; import UseCaseContext from "../src/UseCaseContext"; -describe("UseCase", function () { - context("when execute B UseCase in A UseCase", function () { - it("should execute A:will -> B:will -> B:did -> A:did", function () { +describe("UseCase", function() { + context("when execute B UseCase in A UseCase", function() { + it("should execute A:will -> B:will -> B:did -> A:did", function() { class BUseCase extends UseCase { execute() { return "b" @@ -26,8 +26,9 @@ describe("UseCase", function () { const bUseCase = new BUseCase(); const callStack = []; const expectedCallStackOfAUseCase = [ - `ON_WILL_EXECUTE_EACH_USECASE`, - `ON_DID_EXECUTE_EACH_USECASE` + ActionTypes.ON_WILL_EXECUTE_EACH_USECASE, + ActionTypes.ON_DID_EXECUTE_EACH_USECASE, + ActionTypes.ON_COMPLETE_EACH_USECASE ]; const expectedCallStack = [ `${aUseCase.name}:will`, @@ -46,18 +47,18 @@ describe("UseCase", function () { const expectedType = expectedCallStackOfAUseCase.shift(); assert.equal(type, expectedType); }); - context.onWillExecuteEachUseCase(useCase => { - callStack.push(`${useCase.name}:will`); + context.onWillExecuteEachUseCase((payload, meta) => { + callStack.push(`${meta.useCase.name}:will`); }); - context.onDidExecuteEachUseCase(useCase => { - callStack.push(`${useCase.name}:did`); + context.onDidExecuteEachUseCase((payload, meta) => { + callStack.push(`${meta.useCase.name}:did`); }); // when return context.useCase(aUseCase).execute().then(() => { assert.deepEqual(callStack, expectedCallStack); }); }); - it("UseCase should have `context` that is Context instance", function () { + it("UseCase should have `context` that is Context instance", function() { class TestUseCase extends UseCase { execute() { // then @@ -75,8 +76,8 @@ describe("UseCase", function () { context.useCase(useCase).execute(); }); }); - context("when not implemented execute()", function () { - it("should assert error on constructor", function () { + context("when not implemented execute()", function() { + it("should assert error on constructor", function() { class TestUseCase extends UseCase { } try { @@ -88,8 +89,8 @@ describe("UseCase", function () { } }); }); - describe("#throwError", function () { - it("should dispatch thought onDispatch event", function (done) { + describe("#throwError", function() { + it("should dispatch thought onDispatch event", function(done) { class TestUseCase extends UseCase { execute() { this.throwError(new Error("error")); @@ -97,7 +98,7 @@ describe("UseCase", function () { } const testUseCase = new TestUseCase(); // then - testUseCase.onDispatch(({type, error}) => { + testUseCase.onDispatch(({ type, error }) => { assert(error instanceof Error); done(); }); diff --git a/test/UseCaseExecutor-test.js b/test/UseCaseExecutor-test.js index 9541f6d0d..2bd82020c 100644 --- a/test/UseCaseExecutor-test.js +++ b/test/UseCaseExecutor-test.js @@ -28,7 +28,7 @@ describe("UseCaseExecutor", function() { executor.onWillExecuteEachUseCase(() => { callStack.push(1); }); - dispatcher.onDispatch(({type, value}) => { + dispatcher.onDispatch(({ type, value }) => { if (type === expectedPayload.type) { callStack.push(2); } @@ -60,7 +60,7 @@ describe("UseCaseExecutor", function() { } // then // 4 - dispatcher.onDispatch(({type, value}) => { + dispatcher.onDispatch(({ type, value }) => { if (type === expectedPayload.type) { assert.equal(value, expectedPayload.value); done(); @@ -96,9 +96,9 @@ describe("UseCaseExecutor", function() { let isCalledDidExecuted = false; let isCalledCompleted = false; // 4 - dispatcher.onDispatch(({type, value}) => { - if (type === expectedPayload.type) { - assert.equal(value, value); + dispatcher.onDispatch((payload) => { + if (payload.type === expectedPayload.type) { + assert.equal(payload.value, expectedPayload.value); isCalledUseCase = true; } }); @@ -107,13 +107,13 @@ describe("UseCaseExecutor", function() { useCase: new AsyncUseCase(), dispatcher }); - executor.onDidExecuteEachUseCase(useCase => { - if (useCase instanceof AsyncUseCase) { + executor.onDidExecuteEachUseCase((payload, meta) => { + if (meta.useCase instanceof AsyncUseCase) { isCalledDidExecuted = true; } }); - executor.onCompleteExecuteEachUseCase(useCase => { - if (useCase instanceof AsyncUseCase) { + executor.onCompleteExecuteEachUseCase((payload, meta) => { + if (meta.useCase instanceof AsyncUseCase) { isCalledCompleted = true; } });