-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Updates testing docs to use Testing Library #9888
Updates testing docs to use Testing Library #9888
Conversation
2eb45bd
to
2c80922
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good with small copy suggestions! I assume the pure removals of certain paragraphs are all appropriate (I'm not familiar enough with the content here to know which pieces might no longer be relevant due to the changes)
Co-authored-by: Stephen Barlow <stephen@apollographql.com>
<ExpansionPanel title="Click to expand 🐶"> | ||
|
||
```jsx | ||
import TestRenderer from "react-test-renderer"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test was combined with testing the loading state. If we don't, we'll see an act warning since the DOM updates again on success (it made sense to test these separately with react test renderer when we were manually advancing the event loop, much less so with RTL). The two tests are also mostly duplicates of each other with only a one line assertion difference.
|
||
Remember that the mock's value for `result` can also be a function, so you can perform arbitrary logic (like setting a boolean to indicate that the mutation completed) before returning its result. | ||
|
||
[Testing error states](#testing-error-states) for mutations is identical to testing them for queries.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo
await new Promise((resolve) => setTimeout(resolve, 0)); // wait for response | ||
|
||
const tree = component.toJSON(); | ||
expect(tree.children).toContain("An error occurred"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before we were not rendering the error message in the component code so this test was also failing.
}); | ||
``` | ||
|
||
If your component performs complex calculations or includes delays in its render logic, you can increase the timeout's duration accordingly. You can also use a package like [`wait-for-expect`](https://npm.im/wait-for-expect) to delay until the render has occurred. The risk of using a package like this everywhere is that _every_ test might take up to five seconds to execute (or longer if the default timeout is increased). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove all references to the setTimeout "trick" which is no longer necessary.
bd96aa5
to
9623ea3
Compare
9623ea3
to
eac52bd
Compare
This PR updates the Apollo Client testing docs by removing references to
react-test-renderer
in favor of React Testing Library, the UI testing library recommended in the official React docs. The goal is to improve the readability of our example tests while ensuring they pass, ideally without emitting any warnings.These changes were the outcome of a quick look at #9887: copying + pasting one of the tests from our current docs results in a warning which may cause some confusion. Other tests outright fail when copy + pasted, like the one in Testing the Success State.
Let's look at the test from the "success state" section:
When I run this test locally, I first see that the test failed:
...followed by the act warning:
The issue stems from having to
await new Promise(resolve => setTimeout(resolve, 0));
: sincereact-test-renderer
is mostly used for snapshot testing and doesn't have async utilities for awaiting DOM changes, our docs state thatyou can await a zero-millisecond timeout before performing your checks. This delays the checks until the next "tick" of the event loop, which gives MockedProvider an opportunity to populate the mocked result
.I got the above test to pass by adding a second 0ms setTimeout immediately after the one in the test, and the act warning remained. Using promisified setTimeouts to manually cycle through ticks of the event loop is a fairly brittle and unintuitive way of testing dynamic/interactive behavior, especially given the async utilities available via React Testing Library.
The Testing Library Approach
The same test of the success state written with RTL looks like this:
Instead of using setTimeout, Testing Library provides several
findBy
methods. From the Testing Library docs:We can use the asynchronous
screen.findByText
to query the elements containing the loading message first, followed by the success message "Buck is a poodle" which appears after our query completes.Checklist:
import '@testing-library/jest-dom';
(explain that it's usually present in a setup file, but include it in examples for copy-pastability)testing.mdx
(the current one crashes when you open it)