reducerTester.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import { Reducer } from 'redux';
  2. import { ActionOf } from 'app/core/redux/actionCreatorFactory';
  3. export interface Given<State> {
  4. givenReducer: (reducer: Reducer<State, ActionOf<any>>, state: State) => When<State>;
  5. }
  6. export interface When<State> {
  7. whenActionIsDispatched: (action: ActionOf<any>) => Then<State>;
  8. }
  9. export interface Then<State> {
  10. thenStateShouldEqual: (state: State) => When<State>;
  11. }
  12. interface ObjectType extends Object {
  13. [key: string]: any;
  14. }
  15. const deepFreeze = <T>(obj: T): T => {
  16. Object.freeze(obj);
  17. const isNotException = (object: any, propertyName: any) =>
  18. typeof object === 'function'
  19. ? propertyName !== 'caller' && propertyName !== 'callee' && propertyName !== 'arguments'
  20. : true;
  21. const hasOwnProp = Object.prototype.hasOwnProperty;
  22. if (obj && obj instanceof Object) {
  23. const object: ObjectType = obj;
  24. Object.getOwnPropertyNames(object).forEach(propertyName => {
  25. const objectProperty: any = object[propertyName];
  26. if (
  27. hasOwnProp.call(object, propertyName) &&
  28. isNotException(object, propertyName) &&
  29. objectProperty &&
  30. (typeof objectProperty === 'object' || typeof objectProperty === 'function') &&
  31. Object.isFrozen(objectProperty) === false
  32. ) {
  33. deepFreeze(objectProperty);
  34. }
  35. });
  36. }
  37. return obj;
  38. };
  39. interface ReducerTester<State> extends Given<State>, When<State>, Then<State> {}
  40. export const reducerTester = <State>(): Given<State> => {
  41. let reducerUnderTest: Reducer<State, ActionOf<any>>;
  42. let resultingState: State;
  43. let initialState: State;
  44. const givenReducer = (reducer: Reducer<State, ActionOf<any>>, state: State): When<State> => {
  45. reducerUnderTest = reducer;
  46. initialState = { ...state };
  47. initialState = deepFreeze(initialState);
  48. return instance;
  49. };
  50. const whenActionIsDispatched = (action: ActionOf<any>): Then<State> => {
  51. resultingState = reducerUnderTest(resultingState || initialState, action);
  52. return instance;
  53. };
  54. const thenStateShouldEqual = (state: State): When<State> => {
  55. expect(state).toEqual(resultingState);
  56. return instance;
  57. };
  58. const instance: ReducerTester<State> = { thenStateShouldEqual, givenReducer, whenActionIsDispatched };
  59. return instance;
  60. };