UNPKG

jest-mock-action-creators

Version:

Easy mock & test redux action creators with dispatch() in your components

139 lines 6.39 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; } Object.defineProperty(exports, "__esModule", { value: true }); const jest_diff_1 = __importDefault(require("jest-diff")); /** * Auto-Mock given action creators to use them with expect(dispatch).tobeCalledWithActionCreator() * @param actionCreators */ function mockActionCreators(...actionCreators) { const createNewImplementation = (name) => (...args) => { const invokation = { actionCreator: name, args: args }; return invokation; }; const allActionCreators = actionCreators.reduce((prev, curr) => typeof curr === "function" ? prev.concat(curr) : prev.concat(Object.keys(curr).map(k => curr[k])), []); allActionCreators.forEach(f => { if (!f.mock) { throw new Error(`Action creator is not mocked: ${f.name}`); } f.mockImplementation(createNewImplementation(f.name)); }); } exports.mockActionCreators = mockActionCreators; /** * Replace mocked action creators to use them with expect(dispatch).toBeCalledWithActionCreator() * Doesn't automock them (if using babel plugin) so they should be mocked before */ exports.replaceActionCreators = mockActionCreators; /** * Create dispatch implementation with given expectations * @param dispatch Mocked dispatch function * @param expectations Expectations object. Key is the action creator function name, value is the result */ function createDispatchMockImplementation(dispatch, expectations, logWithoutExpectation = true) { dispatch.mockImplementation((action) => { if (action && action.actionCreator) { if (typeof expectations[action.actionCreator] !== "undefined") { return expectations[action.actionCreator]; } else { if (logWithoutExpectation) { console.warn(`Calling dispatch() with action creator without expectation: ${action.actionCreator}`); const err = new Error("Error"); if (err.stack) { const traces = err.stack.split("\n"); if (traces.length > 3) { // Last related call is four or five in the stack const lastCall = traces[0].match(/Error/) ? traces[4] : traces[3]; console.warn(`Last call is: ${lastCall}`); } } } } } return undefined; }); } exports.createDispatchMockImplementation = createDispatchMockImplementation; // Extend expect automatically when importing expect.extend({ toBeCalledWithActionCreator(received, actionCreatorName, ...args) { if (!received || !received.mock) { throw new Error(this.utils.matcherHint("[.not].toBeCalledWithActionCreator", "dispatch", "") + "\n\n" + `${this.utils.RECEIVED_COLOR("dispatch")} value must be a mock function or spy.\n` + this.utils.printWithType("Received", received, val => this.utils.RECEIVED_COLOR(this.utils.stringify(val)))); } if (typeof actionCreatorName !== "string" && typeof actionCreatorName !== "function") { throw new Error(this.utils.matcherHint("[.not].toBeCalledWithActionCreator", "dispatch", "actionCreator") + "\n\n" + `${this.utils.EXPECTED_COLOR("actionCreator")} must be a string or function.\n` + "Received: " + this.utils.printReceived(typeof actionCreatorName)); } const creatorName = typeof actionCreatorName === "function" ? actionCreatorName.name : actionCreatorName; const calls = received.mock.calls .filter((val) => val && val[0] && val[0].actionCreator === creatorName) .map(v => v[0]); const lastInvokation = calls.slice(-1)[0]; const allInvokationArguments = calls.map(c => c.args).filter(a => !!a); let pass = true; if (calls.length === 0) { pass = false; } else if (args.length > 0) { try { expect(allInvokationArguments).toContainEqual(args); } catch (_a) { pass = false; } } const formatExpected = () => { let msg = `Expected dispatch() ${this.utils.printExpected(pass ? "to not call" : "to call")} action creator ${this.utils.printExpected(creatorName)}\n`; if (args.length > 0) { msg += ` With arguments: ${this.utils.EXPECTED_COLOR(this.utils.stringify(args))}\n`; } return msg; }; const formatReceived = () => { if (!pass && calls.length === 0) { return `${this.utils.RECEIVED_COLOR("But it never called it.")}`; } if (!pass && calls.length > 0) { if (allInvokationArguments.length > 0) { let msg = `${this.utils.RECEIVED_COLOR(`But it called it ${calls.length} times with arguments: ` + this.utils.stringify(allInvokationArguments))}`; if (args.length > 0) { const diffStr = jest_diff_1.default(args, allInvokationArguments.slice(-1)[0], { expand: this.expand }); if (diffStr) { msg += `\n\nLast call difference\n\n${diffStr}`; } } return msg; } else { return `${this.utils.RECEIVED_COLOR("But it called it")}`; } } return `${this.utils.RECEIVED_COLOR("But it called it")}`; }; const message = pass ? () => this.utils.matcherHint(".not.toBeCalledWithActionCreator", "dispatch", creatorName) + "\n\n" + `${formatExpected()}\n` + ` ${formatReceived()}` : () => this.utils.matcherHint(".toBeCalledWithActionCreator", "dispatch", creatorName) + "\n\n" + `${formatExpected()}\n` + ` ${formatReceived()}`; return { message, pass }; } }); //# sourceMappingURL=index.js.map