Reputation: 305
I'm trying to test a component that uses graphql, but when using Apollo's MockProvider I never get the data, it just says loading = true every time.
A complete, minimalist example is here
Things I've tried:
export function Component
), but that doesn't work when testing nested componentsUpvotes: 7
Views: 7462
Reputation: 1
Also, make sure that the query that you are importing in component file is the exact same one that you are using in the test file. For example, I had that an issue where my mocks prop wouldn't pass any data to the MockedProvider because I was importing:
import { CURRENT_USER_QUERY } from '../lib/queries';
in PleaseSigin.js, and I was importing:
import { CURRENT_USER_QUERY } from './User';
in PleaseSignin.test.js. Apparently, even though both queries are identical, they are not the same as far as Jest is concerned.
Upvotes: 0
Reputation: 3565
I'm not a fan of the await wait(0)
approach. Looking at the apollo docs:
For more complex UI with heavy calculations, or delays added into its render logic, the wait(0) will not be long enough.
This means that your tests can potentially be flaky. To solve this issue I use the wait-for-expect
package (also covered in the docs: https://www.apollographql.com/docs/guides/testing-react-components.html#Testing-mutation-components):
it('should render the HeroDiv if there is guide data', async () => {
const wrapper = mount(
<MockedProvider mocks={mocksWithGuideData} addTypename={false}>
<Hero {...props} />
</MockedProvider>
);
await waitForExpect(() => {
wrapper.update();
expect(wrapper.find('HeroDiv').exists()).toBeTruthy();
});
})
waitForExpect
will essentially poll until the condition is complete and it times out after 5 seconds. This guarantees that your test will complete, as long as your query completes before 5 seconds, which it absolutely should if you're using MockedProvider.
The docs point out one caveat: The risk of using a package like this everywhere by default is that every test could take up to five seconds to execute (or longer if the default timeout has been increased).
But in my experience this won't ever happen with MockedProvider. Also aside, await wait(0)
would not handle this case consistently anyway.
Upvotes: 2
Reputation: 408
Yup I ran into this issue as well. The funny thing was that if I add console logs to the component itself, I could see that the data ended up getting there just fine. But for some reason the wrapper
would still only contain our "Loading ..." UI.
Turns out you need to call wrapper.update()
to get the wrapper to rerender it's contents.
This is what worked for me, but it seems less than ideal, so if anyone else has a workaround let me know! Right now our tests look something like:
it('should render the HeroDiv if there is guide data', async () => {
const wrapper = mount(
<MockedProvider mocks={mocksWithGuideData} addTypename={false}>
<Hero {...props} />
</MockedProvider>
);
await wait(0);
wrapper.update();
expect(wrapper.find('HeroDiv').exists()).toBeTruthy();
})
Upvotes: 15