Skip to content

Instantly share code, notes, and snippets.

@gorshkov-leonid
Last active June 25, 2017 22:52
Show Gist options
  • Save gorshkov-leonid/421f6eda8eda0ba11fbf87efec8f5c1e to your computer and use it in GitHub Desktop.
Save gorshkov-leonid/421f6eda8eda0ba11fbf87efec8f5c1e to your computer and use it in GitHub Desktop.
test epics
//way 2: use marbles (http://jsbin.com/pufima/edit?js,output)
describe("way 2: mockStore + marbles", function () {
let saveVnfNameService: SaveVnfNameService & Spied<SaveVnfNameService>;
let saveVnfNameEpic: Epic<Action, AppState>;
let mockStoreFactory: MockStoreCreator<AppState>;
beforeEach(function () {
saveVnfNameService = spy(SaveVnfNameService);
saveVnfNameService.saveVnfName.and.returnValue(Observable.empty());
saveVnfNameEpic = new SaveVnfNameEpicFactory(saveVnfNameService).createEpic();
mockStoreFactory = createMockStore([
createEpicMiddleware(saveVnfNameEpic)
]);
});
it("save vnf name on initial state", function () {
let store = mockStoreFactory(/*initialState*/);
expectEpic(saveVnfNameEpic, {
action: {
marbles: "a", values: {a: setVnfName("abc")}
},
expected: {marbles: ""},
store: store
});
expect(saveVnfNameService.saveVnfName).toHaveBeenCalledWith("abc")
});
it("save vnf name on initial state", function () {
let store = mockStoreFactory(/*initialState*/);
expectEpic(saveVnfNameEpic, {
action: {
marbles: "ab", values: {
get a() {
store.getState().activeSavingSemaphore = 1;
return saveFinished()
},
b: setVnfName("abc")
}
},
expected: {marbles: ""},
store: store
});
expect(saveVnfNameService.saveVnfName).not.toHaveBeenCalledWith("abc")
});
});
//way 2: use marbles (http://jsbin.com/pufima/edit?js,output)
describe("way 2: realStore + marbles", function () {
let store: NgRedux<AppState>;
let saveVnfNameService: Spied<SaveVnfNameService>;
let saveVnfNameEpic: Epic<Action, AppState>;
beforeEach(injectStore((storeData: StoreData<AppState>) => {
store = storeData.store;
store.select(error).subscribe((e) => e && fail(e.cause));
saveVnfNameService = spy(SaveVnfNameService);
saveVnfNameService.saveVnfName.and.returnValue(Observable.empty());
saveVnfNameEpic = new SaveVnfNameEpicFactory(saveVnfNameService).createEpic();
store.configureStore(rootReducer, {}, [createEpicMiddleware(saveVnfNameEpic), createLogger()], [...(storeData.devToolsExtension.isEnabled() && [storeData.devToolsExtension.enhancer()] || [])]);
}));
it("save vnf name on initial state", function () {
store.dispatch( setVnfName("abc"));
expect(saveVnfNameService.saveVnfName).toHaveBeenCalledWith("abc")
});
it("vnf name should be buffered if exists active savings", function () {
store.dispatch(saveStarted());
store.dispatch(saveStarted());
store.dispatch(saveFinished());
store.dispatch(setVnfName("abc"));
store.dispatch(setVnfName("cde"));
expect(saveVnfNameService.saveVnfName).not.toHaveBeenCalledWith("abc");
store.dispatch(saveFinished());
expect(saveVnfNameService.saveVnfName).toHaveBeenCalledTimes(1);
expect(saveVnfNameService.saveVnfName).toHaveBeenCalledWith("cde");
});
});
//way 2: use marbles (http://jsbin.com/pufima/edit?js,output)
// describe("way 2: use marbles", function () {
// /*should be injected to real implementation*/
// const delay = 50;
// const fetchFooEpic = (action$, store) =>
// action$.ofType("FETCH_FOO")
// .switchMap(a =>
// /*delay and testScheduler should be injected to real implementation*/
// Observable.of({type: "FETCH_RESULT"}).delay(delay, testScheduler)
// );
//
// it("aaa", function () {
// expectEpic(fetchFooEpic, {
// action: {
// marbles: "(a|)",
// values: {
// a: {type: "FETCH_FOO"}
// }
// },
// expected: {
// marbles: "-----(a|)",
// values: {
// a: {type: "FETCH_RESULT"}
// }
// },
// })
// });
// });
//create epic with injection
// let injector = ReflectiveInjector.resolveAndCreate([
// {provide: SaveVnfNameService, useValue: saveVnfNameService},
// SaveVnfNameEpicFactory
// ]);
// let saveVnfNameEpicFactory: SaveVnfNameEpicFactory = injector.get(SaveVnfNameEpicFactory);
export function injectStore<State>(callback: (storeData: StoreData<State>) => void) {
return withModule({providers: [...NG_REDUX_SPY_PROVIDERS]}).inject(
[NgRedux, DevToolsExtension],
(store: NgRedux<State>, devToolsExtension: DevToolsExtension) => callback({store, devToolsExtension})
);
}
export type StoreData<State> = {
store: NgRedux<State>,
devToolsExtension: DevToolsExtension
}
//https://stackoverflow.com/questions/42732988/how-do-i-test-a-function-that-returns-an-observable-using-timed-intervals-in-rxj
export const testScheduler = new TestScheduler((actual, expected) => {
console.debug("Test scheduler", "compare", actual, expected);
expect(actual).toEqual(expected);
});
export const expectEpic = <State>(epic: Epic<Action, State>, {expected, action, store}: EpicTestArgs<State>) => {
const action$ = new ActionsObservable(
testScheduler.createHotObservable(action.marbles, action.values)
);
let test$ = epic(action$, store);
testScheduler.expectObservable(test$).toBe(expected.marbles, expected.values);
testScheduler.flush();
};
export interface EpicTestArgs<State> {
expected: MarblesArgs,
action: MarblesArgs
store?: Store<State>
}
export interface MarblesArgs {
marbles: string,
values?: any,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment