UNPKG

@fetch-mock/jest

Version:
113 lines (112 loc) 4.26 kB
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); });