StarpTech / apollo-datasource-http

Optimized JSON HTTP Data Source for Apollo Server
MIT License
73 stars 32 forks source link

How to intercept HTTP request with jest? #20

Closed AhmedBHameed closed 2 years ago

AhmedBHameed commented 3 years ago

I'm trying to mock the response by intercepting undici request but with no success!

I've implemented the data source and it works fine with real testing. But we are trying to intercept HTTP request with jest for testing purposes.

The following mock configuration found here https://github.com/nodejs/undici/blob/main/docs/api/MockPool.md

import {MockAgent, setGlobalDispatcher} from 'undici';

process.env.BASE_API = 'http://localhost';

const mockAgent = new MockAgent();
setGlobalDispatcher(mockAgent);

// MockPool
const mockHttpClient = mockAgent.get('http://localhost');

// Then later i call in my jest on top
mockHttpClient
  .intercept({
    path: '/api/v3/ui/searchTags',
    method: 'GET',
    headers: {
      accept:
        MAP_SMART_SEARCH_CONTENT_TYPE.listAllTagsQuery.willSendAccept,
    },
  })
  .reply(200, JSON.stringify({data: res.allTags}));

Not sure what is missing? I tried also msw but seems they don't support undici yet https://github.com/mswjs/interceptors/issues/159

UPDATE:

So after digging a bit with undici library, I found that they use a mock agent which can intercept the requset. I applied the following in my testing setupTest.ts.

import {MockAgent, setGlobalDispatcher} from 'undici';

const mockAgent = new MockAgent({connections: 1});
setGlobalDispatcher(mockAgent);

[...]

export {mockAgent}

And in my test code

 mockAgent
          .get('http://localhost')
          .intercept({
            path: '/api/v3/ui/searchTags',
            method: 'GET',
            headers: {
              accept:
                MAP_SMART_SEARCH_CONTENT_TYPE.listAllTagsQuery.willSendAccept,
            },
          })
          .reply(200, {data: res.allTags});

The mock works only when using request client from undici. So the only intersepcted request was the one called using the module not the one from the class context this.METHOD.

[...]
const httpResponse = await req(this.baseUrl + SMART_SEARCH_TAGS_RESOURCE_PATH, {
        method: 'GET',
        headers: {
          accept: MAP_SMART_SEARCH_CONTENT_TYPE.listAllTagsQuery.willSendAccept,
        },
      });
      console.log(await httpResponse.body.json());
[...]

Seems something wrong with wiring request but not sure what is the issue exatly!

Any idea of how to intercept the request? Thanks in advance.

AhmedBHameed commented 2 years ago

Resolved using alternative approache.