| Name | Version |
| ---- | ------- |
| msw | 0.21.3 |
| node | 14.15.0 |
| OS | MacOS 10.15.7 (19H2) |
| Relay Hooks | 3.5.2 |
| Jest | 24.9.0 |
// Example of declaration. Provide your code here.
import { setupServer } from 'msw/node'
import { graphql } from 'msw'
const server = setupServer(
graphql.query('SponsorAddressesQuery', (req, res, ctx) => {
return res(
ctx.data({
"sponsor": {
"__typename": "CompanySponsor",
"addresses": [
{
"id": "126cf883-ca26-4b5e-ad7f-4389a0faaf98",
"number": "1231",
"city": "S脙O PAULO",
"state": "SP",
"neighborhood": "PINHEIROS",
"zipCode": "05404013",
"additionalInfo": "1114",
"street": "RUA ARTUR DE AZEVEDO 123"
}
],
"id": "04a427b5-172e-42b6-8638-7bc0f246cc7c"
}
})
);
})
)
server.listen()
I'm dealing with GraphQL using Relay
// Example of making a request. Provide your code here.
// my query file
import graphql from 'babel-plugin-relay/macro';
export const getQuery = () => {
return graphql`
query SponsorAddressesQuery($id: ID!) {
addresses { ... }
}
`;
};
// how do I use it
import { useQuery } from 'relay-hooks';
useQuery(getQuery(), { id: '123' });
Currently my setup is working on the browser, but it seems not intercepting during my Jest test.
It's returning nothing in the test, even errors.
Expect to return mocked data.
Hey, @lai-caju. Thanks for reporting this.
Please, could you elaborate some more:
setupServer module with your testing framework? That module needs to execute as a part of your tests.@kettanaito , sure:
@testing-library/[email protected].beforeAll like:import { server } from '/mocks/server';
beforeAll(() => server.listen());
afterAll(() => server.close());
test('my test here', () => { .... });
And my server.js looks like this:
import { setupServer } from 'msw/node';
import handlers from './handlers';
export { rest, graphql } from 'msw';
export const server = setupServer(...handlers);
Could you provide your jest config please?
The weird thing is, I have some REST endpoint in the system and I'm able to mock REST endpoint in tests, but GraphQL are not working
@aganglada , my jest config is this:
const { pathsToModuleNameMapper } = require('ts-jest/utils')
const { compilerOptions } = require('./tsconfig')
module.exports = {
preset: 'ts-jest',
roots: ['<rootDir>'],
modulePaths: ['<rootDir>'],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
testEnvironment: 'node',
};
This is my src/setupTest.js:
import '@testing-library/jest-dom/extend-expect';
import MutationObserver from '@sheerun/mutationobserver-shim'
window.MutationObserver = MutationObserver;
I have a similar problem with Apollo, it usually happens when I don't provide all the query fields in the mock. E.g. say you request this data in your query:
query product {
id
type
price
color
}
In your graphql handler you have to mock the data contain all the fields from the above:
graphql.query('product', (_, res, ctx) =>
res(
ctx.data({
product: {
id: 1,
type: 'basic',
price: 100,
color: 'red',
},
}),
),
),
If just any of those fields is missing, msw won't return anything, staying silent.
@kettanaito I'd prefer to have some error output in this case. It will save me time debugging why there's no mocked response in my test.
@eugeneoshepkov I think that is Apollo's behavior. MSW will set any given ctx.data as a GraphQL response payload. There's no query-compliance validation whatsoever. When a GraphQL client receives a partial response payload according to a query it's up to it to handle this scenario. It's a _server_'s responsibility to validate a payload against a query, as the server produces errors that may contain useful hints alike "cannot return null for non-nullable "price" field". As to why you receive an empty payload that I'm not sure, you should get exactly what you specified in the response resolver.
You can type guard your mocks if you are using TypeScript and have GraphQL operation types generated. graphql.* request handlers accept generic types that will validate your returned payload on build time, alerting you if you're responding with a partial payload. Take a look at the GraphQL request handlers with TypeScript usage example.
@lai-caju, If other request handlers from the same setup work that may imply that either a GraphQL handler doesn't match an actual request or an actual request is somehow not considered to be GraphQL by MSW. Let's narrow down both of these possibilities.
Try attaching a transparent handler to your mock definition _before_ you have your graphql.* handler. This will catch _any_ requests and you can inspect if your GraphQL request is there.
import { rest } from 'msw'
setupServer(
// Use the right REST handler: rest.post or rest.get, depending on how
// your GraphQL request is issued (both ways are allowed, check what you have).
rest.post('*', (req) => console.log(req.href.url),
// Your current handler after.
graphql.query(...)
)
If you see the request URL logged out when the request happens鈥攇ood. Dive deeper and inspect more reqproperties, such as req.headers, req.body, req.url.searchParams. Post their values in this thread. Be extra cautious to use a proper REST handler according to how your request is made (GraphQL requests still partially follow REST specification in terms of methods, headers, body, etc.).
GET request, look up the query definition in req.url.searchParams.POST request, look up the query definition in req.body.Thanks @kettanaito for support! I'll close this issue, since that we figured out the problem was in my application.
It wasn't about MSW or Relay, my application was having some exception before the request.