grafana/public/test/core/redux/reduxTester.ts
Alex Khomenko 6d95f2f1db
Chore: Update typescript to v4.2.4 (#33297)
* Update typescript to v4.2.4

* Update @types/slate

* Fix QueryVariableEditor.test.tsx

* Fix search-related type errors

* Fix Plugin pages type errors

* Fix missing initializer errors

* Update snapshot

* Revert tsconfig changes
2021-04-28 15:40:01 +03:00

147 lines
4.3 KiB
TypeScript

import { Dispatch, Middleware, MiddlewareAPI } from 'redux';
import thunk, { ThunkMiddleware } from 'redux-thunk';
import { AnyAction, configureStore, EnhancedStore, Reducer, getDefaultMiddleware } from '@reduxjs/toolkit';
import { StoreState } from '../../../app/types';
import { setStore } from '../../../app/store/store';
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?: 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 State);
const debug = args?.debug ?? false;
let store: EnhancedStore<State> | null = null;
const defaultMiddleware = getDefaultMiddleware<State>({
thunk: false,
serializableCheck: false,
immutableCheck: false,
} as any);
const givenRootReducer = (rootReducer: Reducer<State>): ReduxTesterWhen<State> => {
store = configureStore<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;
};