Closed pastinepolenta closed 3 years ago
The "Mock*If" functions determine if it mocks or not, not the content of the response. You're just looking for a single call to mockResponse.
fetch.mockResponse(req => {
if (req.url.endsWith("/isLogged")) {
return "true" // must be a string response
} else if (req.url.endsWith("/token")) {
return (Math.random() * 100000).toString()
} else if (req.url.endsWith("/info")) {
return infoStub
} else {
return "default mock response"
}
})
If you wanted to say "if the URL matches any of my valid 3 cases, mock the response as specified, otherwise, use the real fetch implementation" you would do:
fetch.doMockIf(/^.*(\/isLogged|\/token|\/info)$/, req => {
if (req.url.endsWith("/isLogged")) {
return "true" // must be a string response
} else if (req.url.endsWith("/token")) {
return (Math.random() * 100000).toString()
} else if (req.url.endsWith("/info")) {
return infoStub
} else {
// should never happen
return ""
}
})
@yinzara Thanks for the help! I've noticed that your first example trips up the Typescript compiler:
fetchMock.mockResponse((req) => {
if (req.url.match(/urlPattern1/)) {
return JSON.stringify(response1);
} else if (req.url.match(/urlPattern2/)) {
return JSON.stringify(response2);
} else {
return "default mock response";
}
});
Results in:
TS2769: No overload matches this call.
Overload 1 of 2, '(fn: MockResponseInitFunction): FetchMock', gave the following error.
Argument of type '(req: Request) => string' is not assignable to parameter of type 'MockResponseInitFunction'.
Type 'string' is not assignable to type 'Promise<string | MockResponseInit>'.
Overload 2 of 2, '(response: string, responseInit?: MockParams | undefined): FetchMock', gave the following error.
Argument of type '(req: Request) => string' is not assignable to parameter of type 'string'.
Inspecting the mockResponse
type definition:
mockResponse(fn: MockResponseInitFunction): FetchMock;
mockResponse(response: string, responseInit?: MockParams): FetchMock;
And MockResponseInitFunction
looks like:
export type MockResponseInitFunction = (request: Request) => Promise<MockResponseInit | string>;
So it's looking for a Promise. In short, changing my initial code sample to pass an async
function resolves the issue, but there really isn't any need for the function to be async:
fetchMock.mockResponse(async (req) => {
if (req.url.match(/urlPattern1/)) {
return JSON.stringify(response1);
} else if (req.url.match(/urlPattern2/)) {
return JSON.stringify(response2);
} else {
return "default mock response";
}
});
Would it be possible to modify the type declaration (and the implementation) to simply accept a string response? I'm happy to put together a PR.
Would love this added! The No overload matches this call.
error for the examples were tripping me up in my Typescript project for a bit too long.
I thought the need of mocking specific requests with specific responses and leave the other to the default behavior is a pretty common need and it was expressed by https://github.com/jefflau/jest-fetch-mock/issues/95 and I though it was solved by https://github.com/jefflau/jest-fetch-mock/pull/128 introducing
doMockIf
anddoMockOnceIf
.I still fail to understand though how to properly mock 3 API calls no matter the order while leaving the other mocked by default.
/token
mocked with "randomtoken"/info
mocked with some stub data/islogged
mocked withtrue
I tried a chain like
But that seems to mock properly only if the order of the calls is known and the calls are executed in sequence.
Am I missing something?