@fetch-mock/jest
Version:
jest wrapper for fetch-mock
113 lines (112 loc) • 4.26 kB
JavaScript
import { expect } from '@jest/globals';
import { FetchMock, } from 'fetch-mock';
function getFetchMockFromInput(input) {
const fetchMock = input['fetchMock']
? input.fetchMock
: input;
if (!fetchMock || !(fetchMock instanceof FetchMock)) {
throw new Error('Unable to get fetchMock instance! Please make sure you passed a patched fetch or fetchMock!');
}
return fetchMock;
}
const methodlessExtensions = {
toHaveFetched: (input, filter, options) => {
const fetchMock = getFetchMockFromInput(input);
if (fetchMock.callHistory.called(filter, options)) {
return { pass: true, message: () => 'fetch was called as expected' };
}
return {
pass: false,
message: () => `fetch should have been called with ${filter} and ${JSON.stringify(options)}`,
};
},
toHaveLastFetched: (input, filter, options) => {
const fetchMock = getFetchMockFromInput(input);
const allCalls = fetchMock.callHistory.calls();
if (!allCalls.length) {
return {
pass: false,
message: () => `No calls made to fetch`,
};
}
const lastCall = [...allCalls].pop();
const lastMatchingCall = [
...fetchMock.callHistory.calls(filter, options),
].pop();
if (lastCall === lastMatchingCall) {
return { pass: true, message: () => 'fetch was last called as expected' };
}
return {
pass: false,
message: () => `Last call to fetch should have matched ${filter} and ${JSON.stringify(options)} but was ${JSON.stringify(lastCall)}`,
};
},
toHaveNthFetched: (input, n, filter, options) => {
const fetchMock = getFetchMockFromInput(input);
const nthCall = fetchMock.callHistory.calls()[n - 1];
const matchingCalls = fetchMock.callHistory.calls(filter, options);
if (matchingCalls.some((call) => call === nthCall)) {
return {
pass: true,
message: () => `fetch's ${n}th call was as expected`,
};
}
return {
pass: false,
message: () => `${n}th call to fetch should have matched ${filter} and ${JSON.stringify(options)} but was ${JSON.stringify(nthCall)}`,
};
},
toHaveFetchedTimes: (input, times, filter, options) => {
const fetchMock = getFetchMockFromInput(input);
const calls = fetchMock.callHistory.calls(filter, options);
if (calls.length === times) {
return {
pass: true,
message: () => `fetch was called ${times} times as expected`,
};
}
return {
pass: false,
message: () => `fetch should have made ${times} calls matching ${filter} and ${JSON.stringify(options)}, but it only made ${calls.length}`,
};
},
};
expect.extend(methodlessExtensions);
expect.extend({
toBeDone: (input, routes) => {
const fetchMock = getFetchMockFromInput(input);
const done = fetchMock.callHistory.done(routes);
if (done) {
return { pass: true, message: () => '' };
}
return {
pass: false,
message: () => `fetch has not been called the expected number of times ${routes ? `for ${routes}` : 'in total'}`,
};
},
});
function scopeExpectationFunctionToMethod(func, method) {
return (...args) => {
const opts = args[func.length - 1] || {};
args[func.length - 1] = { ...opts, method };
return func(...args);
};
}
function scopeExpectationNameToMethod(name, humanVerb) {
return name.replace('Fetched', humanVerb);
}
const expectMethodNameToMethodMap = {
Got: 'get',
Posted: 'post',
Put: 'put',
Deleted: 'delete',
FetchedHead: 'head',
Patched: 'patch',
};
Object.entries(expectMethodNameToMethodMap).forEach(([humanVerb, method]) => {
const extensions = Object.fromEntries(Object.entries(methodlessExtensions).map(([name, func]) => [
scopeExpectationNameToMethod(name, humanVerb),
scopeExpectationFunctionToMethod(func, method),
]));
expect.extend(extensions);
});