jest-fetch-mock icon indicating copy to clipboard operation
jest-fetch-mock copied to clipboard

mockIf does not accept typing given in documentation.

Open Akolyte01 opened this issue 2 years ago • 4 comments

The example usage given for mockIf is

fetchMock.mockIf(/^https?:\/\/example.com.*$/, req => {
      if (req.url.endsWith("/path1")) {
        return "some response body"
      } else if (req.url.endsWith("/path2")) {
        return {
          body: "another response body",
          headers: {
            "X-Some-Response-Header": "Some header value"
          } 
        }
      } else {
        return {
          status: 404,
          body: "Not Found"
        }
      }
  })

However when this is attempted in a TypeScript project it results in a Type error.

No overload matches this call.
  Overload 1 of 2, '(urlOrPredicate: UrlOrPredicate, fn?: MockResponseInitFunction): FetchMock', gave the following error.
    Argument of type '(req: Request) => "some response body" | { body: string; headers: { 'X-Some-Response-Header': string; }; status?: undefined; } | { status: number; body: string; headers?: undefined; }' is not assignable to parameter of type 'MockResponseInitFunction'.
      Type '"some response body" | { body: string; headers: { 'X-Some-Response-Header': string; }; status?: undefined; } | { status: number; body: string; headers?: undefined; }' is not assignable to type 'Promise<string | MockResponseInit>'.
        Type 'string' is not assignable to type 'Promise<string | MockResponseInit>'.
  Overload 2 of 2, '(urlOrPredicate: UrlOrPredicate, response: string, responseInit?: MockParams): FetchMock', gave the following error.
    Argument of type '(req: Request) => "some response body" | { body: string; headers: { 'X-Some-Response-Header': string; }; status?: undefined; } | { status: number; body: string; headers?: undefined; }' is not assignable to parameter of type 'string'.

To give a simpler example

fetchMock.mockIf('url', (req) => {
        return 'some response body';
      });

results in

No overload matches this call.
  Overload 1 of 2, '(urlOrPredicate: UrlOrPredicate, 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, '(urlOrPredicate: UrlOrPredicate, response: string, responseInit?: MockParams): FetchMock', gave the following error.
    Argument of type '(req: Request) => string' is not assignable to parameter of type 'string'.ts(2769)
    ```

Akolyte01 avatar Nov 11 '21 20:11 Akolyte01

Same problem here, I tried converting the callback to an async function, but now the tests just fail with it telling me to wrap in act

fetchMock.mockIf('url', async (req) => {
   return 'some response body';
});
    Warning: An update to Home inside a test was not wrapped in act(...).
    
    When testing, code that causes React state updates should be wrapped into act(...):
    
    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */

veloware avatar Dec 07 '21 16:12 veloware

I ran into the same problem. A quick fix for anyone else that needs it, independent of this library:

jest.spyOn(global, 'fetch').mockImplementation(jest.fn(() => {
  return Promise.resolve({
    json: () => Promise.resolve({ key: 'value' })
  } as Response)
}))

And because it's a spyOn, the changes go away when you call jest.restoreAllMocks(). I ended up turning it into something a little more complex for my project where specific endpoints mapped to specific responses. If you need to do the same, just add an input parameter to the initial jest.fn() and return the promise depending on which endpoint you're calling

hak33m16 avatar Jan 20 '22 21:01 hak33m16

Hi,

sad to see that this issue exists since about 9 months and no fix since then (the proposal by @hak33m16 is nice, however I included this library to not having to do everything manually). currently experience the same problem like @Akolyte01 . Would be great to hear a solution to that specific problem as the library is not usable for me if this doesn't work. I'm using TypeScript 4.7.2 and jest 28.1.0. tsconfig.target is set to es2015...maybe that helps. Thanks

nhebling avatar Aug 13 '22 16:08 nhebling

I also ran into this, just for reference the following typing does work:

import type { MockResponseInitFunction, UrlOrPredicate } from 'jest-fetch-mock';
import fetchMock from 'jest-fetch-mock';

// ...

const url : UrlOrPredicate = 'http://www.example.com';
const fn : MockResponseInitFunction = async req => {
  return new Promise(resolve => {
    resolve({
        body: '<body>Hello World!</body>',
        status: 200,
      });
  });
};

fetchMock.mockIf(url, fn);

roy-t avatar Jul 27 '23 14:07 roy-t