123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- import {
- AnyAction,
- configureStore,
- EnhancedStore,
- Reducer,
- getDefaultMiddleware,
- CombinedState,
- PreloadedState,
- } from '@reduxjs/toolkit';
- import { NoInfer } from '@reduxjs/toolkit/dist/tsHelpers';
- import { Dispatch, Middleware, MiddlewareAPI } from 'redux';
- import thunk, { ThunkMiddleware } from 'redux-thunk';
- import { setStore } from '../../../app/store/store';
- import { StoreState } from '../../../app/types';
- export interface ReduxTesterGiven<State> {
- givenRootReducer: (rootReducer: Reducer<State>) => ReduxTesterWhen<State>;
- }
- export interface ReduxTesterWhen<State> {
- whenActionIsDispatched: (
- action: any,
- clearPreviousActions?: boolean
- ) => ReduxTesterWhen<State> & ReduxTesterThen<State>;
- whenAsyncActionIsDispatched: (
- action: any,
- clearPreviousActions?: boolean
- ) => Promise<ReduxTesterWhen<State> & ReduxTesterThen<State>>;
- }
- export interface ReduxTesterThen<State> {
- thenDispatchedActionsShouldEqual: (...dispatchedActions: AnyAction[]) => ReduxTesterWhen<State>;
- thenDispatchedActionsPredicateShouldEqual: (
- predicate: (dispatchedActions: AnyAction[]) => boolean
- ) => ReduxTesterWhen<State>;
- thenNoActionsWhereDispatched: () => ReduxTesterWhen<State>;
- }
- export interface ReduxTesterArguments<State> {
- preloadedState?: PreloadedState<CombinedState<NoInfer<State>>>;
- debug?: boolean;
- }
- export const reduxTester = <State>(args?: ReduxTesterArguments<State>): ReduxTesterGiven<State> => {
- const dispatchedActions: AnyAction[] = [];
- const logActionsMiddleWare: Middleware<{}, Partial<StoreState>> =
- (store: MiddlewareAPI<Dispatch, Partial<StoreState>>) => (next: Dispatch) => (action: AnyAction) => {
- // filter out thunk actions
- if (action && typeof action !== 'function') {
- dispatchedActions.push(action);
- }
- return next(action);
- };
- const preloadedState = args?.preloadedState ?? ({} as unknown as PreloadedState<CombinedState<NoInfer<State>>>);
- const debug = args?.debug ?? false;
- let store: EnhancedStore<State, AnyAction, []> | null = null;
- const defaultMiddleware = getDefaultMiddleware<State>({
- thunk: false,
- serializableCheck: false,
- immutableCheck: false,
- } as any);
- const givenRootReducer = (rootReducer: Reducer<State>): ReduxTesterWhen<State> => {
- store = configureStore<State, AnyAction, Array<Middleware<State>>>({
- reducer: rootReducer,
- middleware: [...defaultMiddleware, logActionsMiddleWare, thunk] as unknown as [ThunkMiddleware<State>],
- preloadedState,
- });
- setStore(store as any);
- return instance;
- };
- const whenActionIsDispatched = (
- action: any,
- clearPreviousActions?: boolean
- ): ReduxTesterWhen<State> & ReduxTesterThen<State> => {
- if (clearPreviousActions) {
- dispatchedActions.length = 0;
- }
- if (store === null) {
- throw new Error('Store was not setup properly');
- }
- store.dispatch(action);
- return instance;
- };
- const whenAsyncActionIsDispatched = async (
- action: any,
- clearPreviousActions?: boolean
- ): Promise<ReduxTesterWhen<State> & ReduxTesterThen<State>> => {
- if (clearPreviousActions) {
- dispatchedActions.length = 0;
- }
- if (store === null) {
- throw new Error('Store was not setup properly');
- }
- await store.dispatch(action);
- return instance;
- };
- const thenDispatchedActionsShouldEqual = (...actions: AnyAction[]): ReduxTesterWhen<State> => {
- if (debug) {
- console.log('Dispatched Actions', JSON.stringify(dispatchedActions, null, 2));
- }
- if (!actions.length) {
- throw new Error('thenDispatchedActionShouldEqual has to be called with at least one action');
- }
- expect(dispatchedActions).toEqual(actions);
- return instance;
- };
- const thenDispatchedActionsPredicateShouldEqual = (
- predicate: (dispatchedActions: AnyAction[]) => boolean
- ): ReduxTesterWhen<State> => {
- if (debug) {
- console.log('Dispatched Actions', JSON.stringify(dispatchedActions, null, 2));
- }
- expect(predicate(dispatchedActions)).toBe(true);
- return instance;
- };
- const thenNoActionsWhereDispatched = (): ReduxTesterWhen<State> => {
- if (debug) {
- console.log('Dispatched Actions', JSON.stringify(dispatchedActions, null, 2));
- }
- expect(dispatchedActions.length).toBe(0);
- return instance;
- };
- const instance = {
- givenRootReducer,
- whenActionIsDispatched,
- whenAsyncActionIsDispatched,
- thenDispatchedActionsShouldEqual,
- thenDispatchedActionsPredicateShouldEqual,
- thenNoActionsWhereDispatched,
- };
- return instance;
- };
|