jefflau / jest-fetch-mock

Jest mock for fetch
MIT License
883 stars 116 forks source link

doMockIf is not a function #140

Closed sieira closed 4 years ago

sieira commented 4 years ago

I'm trying to write an utility function that will mock the response of the profile view and the auth refresh of my API user.

I followed the docs for version 3.0.0, which is installed

npm ls | grep jest-fetch-mock
+-- jest-fetch-mock@3.0.0

When I run my tests, I get

    TypeError: fetch.doMockIf is not a function

      1 | export function mockLoggedOut() {
    > 2 |   fetch.doMockIf('api/profile/').mockResponse('UNAUTHORIZED', { status: 401})
        |         ^
      3 |   fetch.doMockIf('api/auth/refresh/').mockResponse('UNAUTHORIZED', { status: 401})
      4 | }
      5 | 

      at mockLoggedOut (src/test-utils/auth.test.tsx:2:9)
      at Object.<anonymous> (src/store/auth/actions.test.tsx:62:5)

fetch seems to be properly mocked, since doing

  ● Auth actions › checkAuth checks auth when logged out

    function mockConstructor(_a, _b) {
            return fn.apply(this, arguments);
          }

      1 | export function mockLoggedOut() {
    > 2 |   throw Error(fetch)
        |         ^
      3 |   fetch.doMockIf('api/profile/').mockResponse('UNAUTHORIZED', { status: 401})
      4 |   fetch.doMockIf('api/auth/refresh/').mockResponse('UNAUTHORIZED', { status: 401})
      5 | }

      at mockLoggedOut (src/test-utils/auth.test.tsx:2:9)
      at Object.<anonymous> (src/store/auth/actions.test.tsx:62:5)

Shows that fetch is a mock (at least it looks like)

On the other hand, doMock is working

  ● Auth actions › checkAuth checks auth when logged out

    TypeError: fetch.doMockIf is not a function

      1 | export function mockLoggedOut() {
      2 |   fetch.doMock('api/profile/').mockResponse('UNAUTHORIZED', { status: 401})
    > 3 |   fetch.doMockIf('api/auth/refresh/').mockResponse('UNAUTHORIZED', { status: 401})
        |         ^
      4 | }
      5 | 

      at mockLoggedOut (src/test-utils/auth.test.tsx:3:9)
      at Object.<anonymous> (src/store/auth/actions.test.tsx:62:5)

So, either I didn't understand the docs, either it is not clear, either doMockIf is not working

yinzara commented 4 years ago

Looks like this was a mistake in synchronizing the readme and index.d.ts however your method for implementing the mocking is not correct. The "doMockIf" function was renamed "mockIf" however looking back, I think for naming consistency it should be "doMockIf" as it goes with "doMock". I'm to open a PR with this fix.

If you want to force two URLs to return a specific mock response, you cannot call "doMock" or "doMockIf" twice. Each call overwrites the prior value so you would have to call it with a regular expression that matched both paths. Additionally the return value from the doMock function is not some builder. It's just a reference to fetch to make for easy chaining of "once" calls. Each call to "mockResponse" will change the value returned for all responses (and overwrite any prior call to mockResponse).

yinzara commented 4 years ago
fetch.doMockIf(/api\/(profile|auth/refresh)\//).mockResponse(req => {
   if (req.url.includes("profile")) {
      return {
       status: 401,
       body: "UNAUTHORIZED"
      }
   } else if (req.url.includes("auth")) {
      return {
          status: 403
          body: "FORBIDDEN"
       }
   }
})
sieira commented 4 years ago

Thank you ! I get it now, I actually expected each "doMockIf" to add an entry in some black magic internal mapping that would map one or the other, that would then be reset with mockReset

This seems easier.

So, 3.0.1 will not be backwards compatible with 3.0.0 with this change ?

jefflau commented 4 years ago

Yeah, technical mistake on our part. Is it working as expected now?

sieira commented 4 years ago

Yes, it does. Thank you