-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from ardoq/qualifiers
Namespaces
- Loading branch information
Showing
14 changed files
with
289 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import actionExamples from './actions.tests'; | ||
import namespaceExamples from './namespace.tests'; | ||
|
||
describe('examples', function() { | ||
actionExamples(); | ||
namespaceExamples(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { equal, deepEqual } from 'assert'; | ||
import { of, Subject } from 'rxjs'; | ||
import { reduce } from 'rxjs/operators'; | ||
import { | ||
actionCreator, | ||
namespaceActionCreator, | ||
namespaceActionDispatcher, | ||
} from 'rxbeach'; | ||
import { withNamespace } from 'rxbeach/operators'; | ||
import { AnyAction, mockAction } from 'rxbeach/internal'; | ||
|
||
export default function namespaceExamples() { | ||
describe('namespaces', function() { | ||
const testAction = actionCreator<number>('[test] primitive action'); | ||
const namespaceA = 'A'; | ||
const namespaceB = 'B'; | ||
|
||
describe('namespacing action creators', function() { | ||
const testActionA = namespaceActionCreator(namespaceA, testAction); | ||
const testActionB = namespaceActionCreator(namespaceB, testAction); | ||
const actionObjectA = testActionA(1); | ||
const actionObjectB = testActionB(2); | ||
|
||
let lastActionNamespaceA: AnyAction | undefined; | ||
let lastActionNamespaceB: AnyAction | undefined; | ||
let sumAllNamespaces: number | undefined; | ||
this.afterEach(async function() { | ||
lastActionNamespaceA = undefined; | ||
lastActionNamespaceB = undefined; | ||
sumAllNamespaces = undefined; | ||
}); | ||
|
||
this.beforeEach(async function() { | ||
const action$ = of(actionObjectA, actionObjectB); | ||
const actionA$ = action$.pipe(withNamespace(namespaceA)); | ||
const actionB$ = action$.pipe(withNamespace(namespaceB)); | ||
const sum$ = action$.pipe(reduce((a, b) => a + (b.payload || 0), 0)); | ||
|
||
lastActionNamespaceA = await actionA$.toPromise(); | ||
lastActionNamespaceB = await actionB$.toPromise(); | ||
sumAllNamespaces = await sum$.toPromise(); | ||
}); | ||
|
||
it('can filter namespace A', async function() { | ||
equal(lastActionNamespaceA, actionObjectA); | ||
}); | ||
it('can filter namespace B', async function() { | ||
equal(lastActionNamespaceB, actionObjectB); | ||
}); | ||
it('dispatches to main action$', async function() { | ||
equal(sumAllNamespaces, 3); | ||
}); | ||
}); | ||
|
||
describe('namespacing action dispatchers', function() { | ||
let lastActionNamespaceA: AnyAction | undefined; | ||
let lastActionNamespaceB: AnyAction | undefined; | ||
let sumAllNamespaces: number | undefined; | ||
this.afterEach(function() { | ||
lastActionNamespaceA = undefined; | ||
lastActionNamespaceB = undefined; | ||
sumAllNamespaces = undefined; | ||
}); | ||
|
||
this.beforeEach(async function() { | ||
const action$ = new Subject<AnyAction>(); | ||
const dispatchAction = action$.next.bind(action$); | ||
|
||
const dispatchA = namespaceActionDispatcher(namespaceA, dispatchAction); | ||
const dispatchB = namespaceActionDispatcher(namespaceB, dispatchAction); | ||
|
||
const a_p = action$.pipe(withNamespace(namespaceA)).toPromise(); | ||
const b_p = action$.pipe(withNamespace(namespaceB)).toPromise(); | ||
const sum_p = action$ | ||
.pipe(reduce((a: any, b: any) => a + (b.payload || 0), 0)) | ||
.toPromise(); | ||
|
||
dispatchA(testAction(1)); | ||
dispatchB(testAction(2)); | ||
action$.complete(); | ||
|
||
const [a, b, sum] = await Promise.all([a_p, b_p, sum_p]); | ||
|
||
lastActionNamespaceA = a; | ||
lastActionNamespaceB = b; | ||
sumAllNamespaces = sum; | ||
}); | ||
|
||
it('applies namespace A', function() { | ||
deepEqual( | ||
lastActionNamespaceA, | ||
mockAction(testAction.type, namespaceA, 1) | ||
); | ||
}); | ||
|
||
it('applies namespace B', function() { | ||
deepEqual( | ||
lastActionNamespaceB, | ||
mockAction(testAction.type, namespaceB, 2) | ||
); | ||
}); | ||
|
||
it('dispatches to root action$', function() { | ||
equal(sumAllNamespaces, 3); | ||
}); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,13 @@ | ||
import { ActionWithPayload, ActionWithoutPayload } from 'types/Action'; | ||
import { Action } from 'rxbeach'; | ||
import { VoidPayload } from 'rxbeach/internal'; | ||
|
||
export const actionWithoutPayload = ( | ||
export const mockAction = <P = VoidPayload>( | ||
type: string, | ||
qualifiers: string[] = [] | ||
): ActionWithoutPayload => ({ | ||
meta: { qualifiers }, | ||
type, | ||
}); | ||
|
||
export const actionWithPayload = <P>( | ||
type: string, | ||
payload: P, | ||
qualifiers: string[] = [] | ||
): ActionWithPayload<P> => ({ | ||
...actionWithoutPayload(type, qualifiers), | ||
payload, | ||
}); | ||
namespace?: string, | ||
payload?: P | ||
): Action<P> => | ||
({ | ||
meta: { namespace }, | ||
type, | ||
payload, | ||
} as Action<P>); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { deepEqual } from 'assert'; | ||
import { | ||
namespaceActionCreator, | ||
ActionDispatcher, | ||
namespaceActionDispatcher, | ||
} from 'rxbeach'; | ||
import { mockAction, AnyAction } from 'rxbeach/internal'; | ||
|
||
describe('namespace', function() { | ||
describe('namespaceActionCreator', function() { | ||
const type = 'action type'; | ||
const namespace = 'new namespace'; | ||
const actionCreator = (payload: number) => | ||
mockAction(type, 'old namespace', payload); | ||
actionCreator.type = type; | ||
|
||
const namespacedActionCreator = namespaceActionCreator( | ||
namespace, | ||
actionCreator | ||
); | ||
|
||
const actionObject = namespacedActionCreator(12); | ||
|
||
it('Should create actions with namespace', function() { | ||
deepEqual(actionObject, mockAction(type, namespace, 12)); | ||
}); | ||
}); | ||
|
||
describe('namespaceActionDispatcher', function() { | ||
let dispatchedAction: AnyAction | undefined; | ||
const parentDispatcher: ActionDispatcher = action => | ||
(dispatchedAction = action); | ||
|
||
const namespace = 'new namespace'; | ||
const childDispatcher = namespaceActionDispatcher( | ||
namespace, | ||
parentDispatcher | ||
); | ||
|
||
const actionObject = mockAction('action', 'old namespace'); | ||
|
||
childDispatcher(actionObject); | ||
|
||
it('Should invoke the parent dispatcher with namespaced actions', function() { | ||
deepEqual(dispatchedAction, { | ||
payload: undefined, | ||
...mockAction(actionObject.type, namespace), | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { ActionCreator, ActionDispatcher } from 'rxbeach'; | ||
import { UnknownAction } from 'rxbeach/internal'; | ||
|
||
const _namespaceAction = (namespace: string, action: UnknownAction) => ({ | ||
type: action.type, | ||
payload: action.payload, | ||
meta: { | ||
...action.meta, | ||
namespace, | ||
}, | ||
}); | ||
|
||
/** | ||
* Decorate an action creator so the created actions have the given namespace | ||
* | ||
* The given namespace will replace existing namespaces on the action objects. | ||
* | ||
* In contrast to `namespaceActionDispatcher`, the function returned by this | ||
* function creates an action object instead of dispatching it. | ||
* | ||
* @see namespaceActionDispatcher | ||
* @param namespace The namespace to set for the created actions | ||
* @param actionCreator The action creator to decorate | ||
* @returns An action creator that creates actions using the passed action | ||
* creator, and sets the given namespace | ||
*/ | ||
export const namespaceActionCreator = <Payload>( | ||
namespace: string, | ||
actionCreator: ActionCreator<Payload> | ||
): ActionCreator<Payload> => { | ||
const creator = (payload?: any) => | ||
_namespaceAction(namespace, actionCreator(payload)); | ||
creator.type = actionCreator.type; | ||
|
||
return creator as ActionCreator<Payload>; | ||
}; | ||
|
||
/** | ||
* Decorate an action dispatcher so it dispatches namespaced actions | ||
* | ||
* The given namespace is set as the namespace for each action dispatched with | ||
* this function, before the action is dispatched with the action dispatcher | ||
* from the arguments. | ||
* | ||
* In contrast to `namespaceActionCreator`, the function returned by this | ||
* function dispatches the action, instead of creating it. | ||
* | ||
* @see namespaceActionCreator | ||
* @param parentDispatcher The dispatcher the returned action dispatcher will | ||
* dispatch to | ||
* @param namespace The namespace that will be set for each action before they | ||
* are passed on to the parent dispatcher | ||
* @returns An action dispatcher that sets the namespace before passing the | ||
* actions to the parent dispatcher | ||
*/ | ||
export const namespaceActionDispatcher = ( | ||
namespace: string, | ||
parentDispatcher: ActionDispatcher | ||
): ActionDispatcher => action => | ||
parentDispatcher(_namespaceAction(namespace, action)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export { ofType, extractPayload } from './operators'; | ||
export { ofType, extractPayload, withNamespace } from './operators'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.