@jedmao/redux-mock-store
Version:
A mock store for testing your redux async action creators and middleware
71 lines (70 loc) • 2.81 kB
JavaScript
import { applyMiddleware, } from 'redux';
import { isFunction, isPlainObject } from './utils';
/**
* A mock store for testing Redux async action creators and middleware.
*/
export function configureMockStore(middlewares = []) {
return mockStore;
/**
* @returns An instance of the configured mock store.
* @note Call this function to reset your store after every test.
*/
function mockStore(getState = {}) {
return applyMiddleware(...middlewares)(creator)(undefined);
function creator() {
let actions = [];
const listeners = [];
return {
getState() {
return isFunction(getState) ? getState(actions) : getState;
},
getActions() {
return actions;
},
clearActions() {
actions = [];
},
dispatch(action) {
if (!isPlainObject(action)) {
throw new TypeError('Actions must be plain objects. ' +
'Use custom middleware for async actions.');
}
if (typeof action.type === 'undefined') {
throw new TypeError('Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant? ' +
'Action: ' +
JSON.stringify(action));
}
actions.push(action);
for (const listener of listeners) {
listener(action);
}
return action;
},
subscribe(listener) {
if (!isFunction(listener)) {
throw new TypeError('Listener must be a function.');
}
listeners.push(listener);
return unsubscribe;
function unsubscribe() {
const index = listeners.indexOf(listener);
if (index === -1) {
return;
}
listeners.splice(index, 1);
}
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
replaceReducer(_nextReducer) {
throw new Error('Mock stores do not support reducers. ' +
'Try supplying a function to getStore instead.');
},
/* istanbul ignore next */
[Symbol.observable]() {
throw new Error('Not implemented');
},
};
}
}
}