apollo-feature-requests
apollo-feature-requests copied to clipboard
Ability to use wildcards in mocks / mock a range of requests
Motivation
I am currently developing a prototype / proof of concept for an app where the user searches for an id and gets a view of the product. I want to prepare the GraphQL integration, but for now I want to mock all requests to the backend and return default dummy data to show to the user.
The problem
To use the MockedProvider to mock away the graphql backend, I have to specify exactly which variables the query will be called with. But I have no way to anticipate what the user will try to search for.
Feature Request
Make it possible to use wildcards in mocks or otherwise leave open a part of the query, so it matches regardless of a variable value.
Example / Proposed feature
This matches only one very specific query:
const mocks = [
{
request: {
query: GET_ARTICLE,
variables: { articleNumber: "123456" }
},
result: {
data: { article: testArticle }
}
}
];
Something like this could match all queries to GET_ARTICLE and always return the same result:
const mocks = [
{
request: {
query: GET_ARTICLE
},
result: {
data: { article: testArticle }
}
}
];
Alternatively:
request: {
query: GET_ARTICLE
variables: { articleNumber: ANY_VALUE }
}
where ANY_VALUE would be a wildcard constant that Apollo recognises.
I prefer to avoid MockedProvider entirely and instead go with the approach outlined here: https://medium.com/free-code-camp/a-new-approach-to-mocking-graphql-data-1ef49de3d491
This is the approach I use in all my client-side tests. It automatically provides mock data of the correct type, but you can still specify your own mock data if you wish. You can also choose to only provide some mock data, and allow the rest of the query data to be mocked automatically. The query arguments are provided to your mock function in the second parameter, so you can choose to return different mock data depending on the query arguments (or just ignore the variables entirely)
This article was also helpful: https://www.robinwieruch.de/graphql-server-mock-apollo-client
The downside of this approach is that apollo-link-schema
has a fairly large bundle size, which is why it's usually recommended not to use it in your app. But if you don't mind a large bundle size, I think the apollo-link-schema
approach is much more flexible than the MockedProvider approach.
Released this package which supports wildcards in mocks and a bunch of other nice functionality to help writing tests: https://github.com/insidewhy/wildcard-mock-link
Is documented/tested.
👍 on this
@richardwu you should use reactions instead of comments saying +1 which notify all thread watchers. At any rate wildcard-mock-link already supports this together with all other features of the mock link.
@insidewhy wildcard-mock-link
does not support jest act
, nor does it support Apollo Client Addon for Storybook. Having this functionality inside the apollo MockedProvider would greatly speed up our tests and improve our stories.
Please do not dismiss this use case as solved because there is a workaround.
does not support jest act
It does, you can even pass act
as a constructor argument to avoid having to use it manually if you want.
nor does it support Apollo Client Addon for Storybook
Could you give some details on this?
@insidewhy
you can even pass
act
as a constructor argument
Wow, thank you. I can't believe I missed this after how many times I read the documentation. You just saved my team and tests a lot of time.
Apollo Client Addon details
https://storybook.js.org/addons/storybook-addon-apollo-client
I was hoping to use that as a way of showing parameters of mocked mutations in the stories. I think I can probably hack around it by processing the request callback of my mocks.
@insidewhy
you can even pass
act
as a constructor argumentWow, thank you. I can't believe I missed this after how many times I read the documentation. You just saved my team and tests a lot of time.
Apollo Client Addon details
https://storybook.js.org/addons/storybook-addon-apollo-client
I was hoping to use that as a way of showing parameters of mocked mutations in the stories. I think I can probably hack around it by processing the request callback of my mocks.
Thanks for the link to the addon! I combined it with the Play function to specifically enter data for the variables used on the mock and tell that as a distinct story: https://storybook.js.org/docs/react/writing-stories/play-function.
- https://github.com/apollographql/apollo-client/pull/6701
Thanks for the nudge @RobinTail!
That change will be coming in the next minor 3.9.0 which should release within the next couple weeks. As such, I'm going to go ahead and close out this issue. Feel free to open a new feature request if you need further assistance. Looking forward to getting this one out!
unfortunately this solution only works for 1 call, has anyone else tested this?
Hey @ARkrOSClou 👋
I think you'll find https://github.com/apollographql/apollo-client/pull/11178 useful, which will be released in 3.9 along with the change to dynamically match variables. You can set a maxUsageCount
to tell MockedProvider
to reuse a mock as many times as you need to.
Check out the preview docs if you'd like to try this feature out in 3.9.0-rc.1
before our public release of 3.9 🙂
Hey @ARkrOSClou 👋
I think you'll find apollographql/apollo-client#11178 useful, which will be released in 3.9 along with the change to dynamically match variables. You can set a
maxUsageCount
to tellMockedProvider
to reuse a mock as many times as you need to.Check out the preview docs if you'd like to try this feature out in
3.9.0-rc.1
before our public release of 3.9 🙂
Hey @jerelmiller!
~Not sure if I understand it correctly, but this code throws errors on all subsequent calls:~ Sorry for my ☝️ message, I found a bug in my implementation.
This code works as expected, it accepts any variables for the first and all the subsequent calls!
const mocks = [ {
request: {
query: ...,
},
maxUsageCount: Number.POSITIVE_INFINITY,
variableMatcher: () => true,
result: { ... }
} ]
// ...
<MockedProvider mocks={mocks}>
// ...