grafana/public/test/core/redux/reduxTester.ts
Josh Hunt 3c6e0e8ef8
Chore: ESlint import order (#44959)
* Add and configure eslint-plugin-import

* Fix the lint:ts npm command

* Autofix + prettier all the files

* Manually fix remaining files

* Move jquery code in jest-setup to external file to safely reorder imports

* Resolve issue caused by circular dependencies within Prometheus

* Update .betterer.results

* Fix missing // @ts-ignore

* ignore iconBundle.ts

* Fix missing // @ts-ignore
2022-04-22 14:33:13 +01:00

155 lines
4.5 KiB
TypeScript

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;
};