jefflau / jest-fetch-mock

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

Feature request: fetchMock.mockIf() collects mocks to stack #171

Open alexey2baranov opened 3 years ago

alexey2baranov commented 3 years ago

Hello!

Problem

We use mockIf() to mocking some hard api. Unfortunately setting all routes in one callback in beforeEach is not agaile and not convenient. Because some routes are common for all tests. But the others are differing from one test to another. So there is no possible to setup common routes in beforeEach. And raises many code dublications into each test.

Decision

I suggest fetch.mockIf() collects new mock into a stack until resetMocks() will be called next time. So each time fetch() is performed mockIf's stack items match the url until first match and execute matched mock. This makes possible to make test structure which uses beforeEach for common mocks setup like this.

beforeEach(()=>{
  fetch.resetMocks()
  fetch.mockIf(/common_routes_url/, (req)=>{
    // commont routes mocking
  })
})

it('test of specific route 1', ()=>{
  fetch.mockIf(/secific_route_1/, (req)=>{
    // specific_route_1 mocking
  })
   // do test with setted mocks for /common_routes_url/ and /secific_route_1/
})

it('test of specific route 2', ()=>{
  fetch.mockIf(/secific_route_2/, (req)=>{
    // specific_route_2 mocking
  })
  // do test with setted  mocks for /common_routes_url/ and /secific_route_2/
})
yinzara commented 3 years ago

Unfortunately this would be a pretty major change to how the library functions and would require us to produce a new major version as it would break existing implementations.

While I understand using a single mockIf call for each test can reduce your flexibility, the mockIf function can also accept a function callback (that accepts a URL object) that can determine if it's mocked or not.

This can allow you to build your own dynamic determination that can utilize a shared function

For example:

const commonMockedPatterns = [
   /common_routes_url/
]
function shouldMockIf(...urls) {
   return url => {
      return !!commonMockedPatterns.find(u => u.test(url.href)) || !!urls.find(u => u.test(url.href))
   }
}

beforeEach(()=>{
  fetch.resetMocks()
})

it('test of specific route 1', ()=>{
  fetch.mockIf(shouldMockIf(/secific_route_1/), (req)=>{
    // specific_route_1 mocking
  })
   // do test with setted mocks for /common_routes_url/ and /secific_route_1/
})

it('test of specific route 2', ()=>{
  fetch.mockIf(shouldMockIf(/secific_route_2/), (req)=>{
    // specific_route_2 mocking
  })
  // do test with setted  mocks for /common_routes_url/ and /secific_route_2/
})