import { Record } from "immutable"; import { StateObservable } from "redux-observable"; import { Subject } from "rxjs"; import { TestScheduler } from "rxjs/testing"; import { makeMakeRootEpic } from "./epics"; import { makeCreateMyth } from "./myth"; import { makeRootReducer } from "./reducer"; import { MaybeRootState, MythicAction, MythicPackage, Myths, PackageDefinition, Selector } from "./types"; export const createMythicPackage = (pkg: PKG) => ( packageDefinition: PackageDefinition, ): MythicPackage => { type OurPackage = MythicPackage; const myths: Myths = {}; const packageWIP: Partial = { name: pkg, myths, // for use in typeof expressions: state: undefined as unknown as STATE, initialState: Record( packageDefinition.initialState, )(), makeStateRecord: Record( packageDefinition.initialState, ), makeRootEpic: makeMakeRootEpic(myths), rootReducer: makeRootReducer(myths, packageDefinition.initialState), createMyth: makeCreateMyth(pkg, myths), createSelector: (selector: Selector) => (state?: MaybeRootState) => selector(state?.__private__?.[pkg]), }; packageWIP.testMarbles = ( inputMarbles: string, outputMarbles: string, marblesMapToActions: { [key: string]: MythicAction }, state?: STATE, ) => { const originalState = { __private__: { [packageWIP.name!]: state === undefined ? packageWIP.initialState : packageWIP.makeStateRecord!(state), }, }; const scheduler = new TestScheduler( (actual, expected) => expect(actual).toEqual(expected) ); scheduler.run(helpers => { const { hot, expectObservable } = helpers; const inputAction$ = hot(inputMarbles, marblesMapToActions); const outputAction$ = packageWIP.makeRootEpic!()( inputAction$, new StateObservable(new Subject(), originalState), {}, ); expectObservable(outputAction$) .toBe(outputMarbles, marblesMapToActions); }); }; return packageWIP as OurPackage; };