Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSW do not intercept GraphQL requests at all #63

Closed
avallonazevedo opened this issue Jul 26, 2021 · 11 comments
Closed

MSW do not intercept GraphQL requests at all #63

avallonazevedo opened this issue Jul 26, 2021 · 11 comments

Comments

@avallonazevedo
Copy link

I've tried every possible solution described on the internet, but nothing seems to help.

I created a mock server and am trying to intercept a GraphQL call:

./setup/setup-server.ts

const handlers = [
graphql.query<GetOperation, GetOperationVariables>(
    'GetOperation'
    (req, res, ctx) => {
      // Nothing showing in console
      console.log(req.variables);
      return res(
        ctx.data({
          operation: [] // mocked operation
        })
      );
    }
  ),
]

./graphql/use-get-operation.ts

export const GET_OPERATION_BY_ID_DEFAULT = gql`
  query GetOperation($idOrContractNumber: String!) {
    operation(input: { idOrContractNumber: $idOrContractNumber }) {
      id
      modality
      totaltaxes
      exchangeRate
    }
  }
`;

The call is not intercepted.

I've already tried:

  • Import jest-fetch-mock in the configuration file;
  • Start the server in setupFiles.js (as exemplified in the documentation);
  • Start the server in the file directly in the test;
  • Use regex instead of string in the operation name;

Nothing seems to work.

I tried to create both queries and mutations and it didn't work.

MSW version used: 0.33.0

@kettanaito
Copy link
Member

Hey, @avallonazevedo.

Could you please share how do you call setupServer in your test/setup?

Also, make sure you don't use any fetch mocks. Using them means you replace fetch with a stub, and fetch calls no longer happen. That's likely why MSW cannot intercept your GraphQL query—it never happens when using the stub.

Notice that fetch stub and polyfill are two different things. You do need a fetch polyfill in order to use it in your tests that run in Node.js. You don't need the stub because MSW allows your code to make requests as it would do in production, increasing your confidence in tests.

@pelhage
Copy link

pelhage commented Jul 27, 2021

+1 been struggling to get mswjs to work for my project

I noticed that with rest you are encouraged to define absolute URLs for nodejs

But don't see any docs on how to configure for graphql;

@kettanaito
Copy link
Member

@pelhage, if you wish to intercept GraphQL operations on a per-endpoint basis you can use graphql.link. See the usage example here. By default, MSW intercepts all matching GraphQL operations regardless of the origin.

@kettanaito
Copy link
Member

kettanaito commented Jul 27, 2021

Please bear in mind that if you experience something not working, you'd have to share your setup and usage—the more the better. Ideally, a reproduction repository is something that helps to resolve the issue really fast. We always prioritize issues that come with reproduction repositories.

@avallonazevedo
Copy link
Author

Hi @kettanaito!

Thank you for the fast response.

As you asked, here is the configuration of how I use setup-server:

./src/setup-tests.js

/* eslint-disable @typescript-eslint/no-var-requires */

require('@testing-library/jest-dom/extend-expect');
const graphqlServer = require('./__tests__/setup-server').default;

beforeAll(() => {
  // This is printed. Server is correctly initializing.
  console.log('Server listening...');
  graphqlServer.listen();
});

afterEach(() => {
  graphqlServer.resetHandlers();
});

afterAll(() => {
  graphqlServer.close();
});

./jest.config.ts

export default {
  setupFilesAfterEnv: ['<rootDir>/src/setup-tests.js'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  moduleDirectories: ['node_modules', 'src'],
  clearMocks: true,
  coverageDirectory: 'coverage',
  coverageProvider: 'v8',
  testEnvironment: 'jsdom',
  preset: 'ts-jest',
  moduleNameMapper: {
    '@/(.*)': '<rootDir>/src/$1',
  },
  transform: {
    '^.+\\.jsx?$': 'babel-jest',
    '^.+\\.tsx?$': 'ts-jest',
  },
  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
};

I'm not using any mock for "fetch". I just tried using some mock package, as exemplified in some internet responses with people with similar problems.

I'm going to try to provide a more concrete example in some tool like Codesandbox, although I'm not allowed to show much code of the application I'm working on.

Thanks again for your help.

@kettanaito
Copy link
Member

Could you double-check that you're providing those handlers in ./__tests__/setup-server?

It should look something like this:

setupServer(...handlers)

Once you do, go to your src/setup-tests.js and add this life-cycle method:

graphqlServer.on('request:start', console.log)

Run the affected test again. Do you see a console log in the output? If you don't, chances are MSW is not running in your test at all due to some setup issue.

@avallonazevedo
Copy link
Author

avallonazevedo commented Jul 27, 2021

My ./src/__tests__/setup-server:

import { graphql } from 'msw';
import { setupServer } from 'msw/node';

const handlers = [
graphql.query<GetOperation, GetOperationVariables>(
    'GetOperation'
    (req, res, ctx) => {
      // Nothing showing in console
      console.log(req.variables);
      return res(
        ctx.data({
          operation: [] // mocked operation
        })
      );
    }
  ),
];

const graphqlServer = setupServer(...handlers);

export default graphqlServer;

on('request:start') doesn't really show anything on the console, but I can't see where the MSW configuration might be wrong.

I also tried to use graphql.link to try to intercept in particular, but I was also unsuccessful.

@maurusrv
Copy link

I also encounter the issue where in msw server seems to not intercept the graphql requests. in my case, it didn't intercept because the fetch object in my apolloClient waits for the client-side fetch and i was using our backend's graphql endpoint. basing on the example: https://github.com/mswjs/examples/blob/master/examples/graphql-react-apollo/src/ApolloClient.js, i've used:

uri: 'http://localhost:3000/graphql',
fetch: nodeFetch // i've used node-fetch here, instead of just waiting for client side fetch: (...args) => fetch(...args),

and it worked!

of course, there might be other factors but, maybe you can double check your apolloClient too.

@kettanaito
Copy link
Member

That's a good point, @maurusrv.

Always make sure you configure your Apollo Client properly. In Node.js you need to specify the fetch option, and you should see the warning from the client about that when the tests run. Using node-fetch or cross-fetch for that option is a good approach.

@avallonazevedo
Copy link
Author

Excellent my dears!

With node-fetch I am now able to intercept my requests. Everything is working perfectly.

Perhaps we should make this more explicit in the documentation?

Thank you both for your help!

@kettanaito
Copy link
Member

@avallonazevedo, that's a configuration to address on your GraphQL client's side (Apollo). I believe that point is written in their docs. I can also see an explicit error whenever I run Apollo in Node.js (test) without specifying the fetch option. This is outside of MSW's scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants