jest-mock-action-creators
Version:
Easy mock & test redux action creators with dispatch() in your components
139 lines • 6.39 kB
JavaScript
;
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