Jest + test renderer helpers for concurrent mode#13751
Jest + test renderer helpers for concurrent mode#13751acdlite merged 5 commits intofacebook:masterfrom
Conversation
Details of bundled changes.Comparing: 36c5d69...07619df scheduler
jest-react
Generated by 🚫 dangerJS |
bvaughn
left a comment
There was a problem hiding this comment.
Didn't really read the ReactSuspenseWithTestRenderer-test case too closely, just left a thought about the matchers.
packages/jest-react/src/JestReact.js
Outdated
| * LICENSE file in the root directory of this source tree. | ||
| */ | ||
|
|
||
| import jestDiff from 'jest-diff'; |
| ReactFeatureFlags.enableSuspense = true; | ||
| React = require('react'); | ||
| ReactTestRenderer = require('react-test-renderer'); | ||
| JestReact = require('jest-react'); |
There was a problem hiding this comment.
This isn't actually used anywhere within this test.
packages/jest-react/README.md
Outdated
| @@ -0,0 +1,3 @@ | |||
| # `jest-react` | |||
|
|
|||
| Jest matchers and utilities for testing React components. No newline at end of file | |||
There was a problem hiding this comment.
We might want to add future clarity about whether this package is meant for generic React testing or only for testing with react-test-renderer. (I assume the latter.)
There was a problem hiding this comment.
Is react-test-renderer not for generic React testing? :D
There was a problem hiding this comment.
No. People will see this and then it's meant for use with Enzyme.
There was a problem hiding this comment.
What's an Enzyme? :D
But yeah good point :(
packages/jest-react/src/JestReact.js
Outdated
| return captureAssertion(() => expect(actualYields).toEqual(expectedYields)); | ||
| } | ||
|
|
||
| export function toClearYields(ReactTestRenderer, expectedYields) { |
There was a problem hiding this comment.
I still think it's weird that this matcher accepts the ReactTestRenderer rather than a renderer instance.
There was a problem hiding this comment.
You can yield from anywhere, not just a root.
There was a problem hiding this comment.
It's more a matter of consistency. I expect people will accidentally use expect(renderer).toClearYields because that's what they do everywhere else
There was a problem hiding this comment.
Ok I'll make it throw with a helpful message
| export function toMatchRenderedOutput(renderer, expectedJSX) { | ||
| const actualJSON = renderer.toJSON(); | ||
|
|
||
| let actualJSX; |
There was a problem hiding this comment.
This is...interesting. I guess it allows you to avoid the inline require, but it also seems more complex and less powerful than what I originally wrote. Why the change?
For example, the following test would work with this matcher:
const ExampleComponent = ({ foo }) => foo;
const renderer = ReactTestRenderer.create(<ExampleComponent foo="bar" />);
expect(renderer).toMatchRenderedOutput('bar');But this test wouldn't:
const ExampleComponent = ({ foo }) => <div>{foo}</div>;
const renderer = ReactTestRenderer.create(<ExampleComponent foo="bar" />);
expect(renderer).toMatchRenderedOutput(<div>bar</div>);And so I wouldn't be able to use this matcher for the tests in ErrorBoundaryReconciliation.
There was a problem hiding this comment.
The tricky bit is that ReactTestRenderer.create will run the renderer synchronously on a new root, so it will cause React to interrupt the previous root and switch to a new one. That makes it unsuitable for some tests, and it’s a non-obvious/surprising behavior when it happens.
There was a problem hiding this comment.
Also why wouldn't that test work? It should! I just used strings in the Suspense test because it was less to type.
There was a problem hiding this comment.
That's fair. I think it's reasonable
I'm concerned that what we have with this PR isn't flexible enough to be very useful with many "real" components.
There was a problem hiding this comment.
Oh whoops, missed your second comment.
Also why wouldn't that test work?
Lots of undefined property access errors. If you think it should be possible for it to work with more complex test cases, then I can help dig into how we'd fix it.
There was a problem hiding this comment.
Yeah it's probably just a bug. I'll add more tests as I go.
There was a problem hiding this comment.
Cool. In that case, it would be great to update ErrorBoundaryReconciliation to use the new matcher.
There was a problem hiding this comment.
Yeah it was just a bug :) Updated ErrorBoundaryReconciliation-test
Most of our concurrent React tests use the noop renderer. But most of those tests don't test the renderer API, and could instead be written with the test renderer. We should switch to using the test renderer whenever possible, because that's what we expect product devs and library authors to do. If test renderer is sufficient for writing most React core tests, it should be sufficient for others, too. (The converse isn't true but we should aim to dogfood test renderer as much as possible.) This PR adds a new package, jest-react (thanks @cpojer). I've moved our existing Jest matchers into that package and added some new ones. I'm not expecting to figure out the final API in this PR. My goal is to land something good enough that we can start dogfooding in www. TODO: Continue migrating Suspense tests, decide on better API names
bvaughn
left a comment
There was a problem hiding this comment.
Accept to unblock. Let's tweak the README to make the scope of this package clearer. Also fix the CI failure.
- Errors if user attempts to flush when log of yields is not empty - Throws if argument passed to toClearYields is not ReactTestRenderer
- toFlushAll -> toFlushAndYield - toFlushAndYieldThrough -> - toClearYields -> toHaveYielded Also added toFlushWithoutYielding
c981713 to
180f925
Compare
* Jest + test renderer helpers for concurrent mode Most of our concurrent React tests use the noop renderer. But most of those tests don't test the renderer API, and could instead be written with the test renderer. We should switch to using the test renderer whenever possible, because that's what we expect product devs and library authors to do. If test renderer is sufficient for writing most React core tests, it should be sufficient for others, too. (The converse isn't true but we should aim to dogfood test renderer as much as possible.) This PR adds a new package, jest-react (thanks @cpojer). I've moved our existing Jest matchers into that package and added some new ones. I'm not expecting to figure out the final API in this PR. My goal is to land something good enough that we can start dogfooding in www. TODO: Continue migrating Suspense tests, decide on better API names * Add additional invariants to prevent common errors - Errors if user attempts to flush when log of yields is not empty - Throws if argument passed to toClearYields is not ReactTestRenderer * Better method names - toFlushAll -> toFlushAndYield - toFlushAndYieldThrough -> - toClearYields -> toHaveYielded Also added toFlushWithoutYielding * Fix jest-react exports * Tweak README
* Jest + test renderer helpers for concurrent mode Most of our concurrent React tests use the noop renderer. But most of those tests don't test the renderer API, and could instead be written with the test renderer. We should switch to using the test renderer whenever possible, because that's what we expect product devs and library authors to do. If test renderer is sufficient for writing most React core tests, it should be sufficient for others, too. (The converse isn't true but we should aim to dogfood test renderer as much as possible.) This PR adds a new package, jest-react (thanks @cpojer). I've moved our existing Jest matchers into that package and added some new ones. I'm not expecting to figure out the final API in this PR. My goal is to land something good enough that we can start dogfooding in www. TODO: Continue migrating Suspense tests, decide on better API names * Add additional invariants to prevent common errors - Errors if user attempts to flush when log of yields is not empty - Throws if argument passed to toClearYields is not ReactTestRenderer * Better method names - toFlushAll -> toFlushAndYield - toFlushAndYieldThrough -> - toClearYields -> toHaveYielded Also added toFlushWithoutYielding * Fix jest-react exports * Tweak README
* Jest + test renderer helpers for concurrent mode Most of our concurrent React tests use the noop renderer. But most of those tests don't test the renderer API, and could instead be written with the test renderer. We should switch to using the test renderer whenever possible, because that's what we expect product devs and library authors to do. If test renderer is sufficient for writing most React core tests, it should be sufficient for others, too. (The converse isn't true but we should aim to dogfood test renderer as much as possible.) This PR adds a new package, jest-react (thanks @cpojer). I've moved our existing Jest matchers into that package and added some new ones. I'm not expecting to figure out the final API in this PR. My goal is to land something good enough that we can start dogfooding in www. TODO: Continue migrating Suspense tests, decide on better API names * Add additional invariants to prevent common errors - Errors if user attempts to flush when log of yields is not empty - Throws if argument passed to toClearYields is not ReactTestRenderer * Better method names - toFlushAll -> toFlushAndYield - toFlushAndYieldThrough -> - toClearYields -> toHaveYielded Also added toFlushWithoutYielding * Fix jest-react exports * Tweak README
* Jest + test renderer helpers for concurrent mode Most of our concurrent React tests use the noop renderer. But most of those tests don't test the renderer API, and could instead be written with the test renderer. We should switch to using the test renderer whenever possible, because that's what we expect product devs and library authors to do. If test renderer is sufficient for writing most React core tests, it should be sufficient for others, too. (The converse isn't true but we should aim to dogfood test renderer as much as possible.) This PR adds a new package, jest-react (thanks @cpojer). I've moved our existing Jest matchers into that package and added some new ones. I'm not expecting to figure out the final API in this PR. My goal is to land something good enough that we can start dogfooding in www. TODO: Continue migrating Suspense tests, decide on better API names * Add additional invariants to prevent common errors - Errors if user attempts to flush when log of yields is not empty - Throws if argument passed to toClearYields is not ReactTestRenderer * Better method names - toFlushAll -> toFlushAndYield - toFlushAndYieldThrough -> - toClearYields -> toHaveYielded Also added toFlushWithoutYielding * Fix jest-react exports * Tweak README
Most of our concurrent React tests use the noop renderer. But most of those tests don't test the renderer API, and could instead be written with the test renderer. We should switch to using the test renderer whenever possible, because that's what we expect product devs and library authors to do. If test renderer is sufficient for writing most React core tests, it should be sufficient for others, too. (The converse isn't true but we should aim to dogfood test renderer as much as possible.)
This PR adds a new package, jest-react (thanks @cpojer). I've moved our existing Jest matchers into that package and added some new ones.
I'm not expecting to figure out the final API in this PR. My goal is to land something good enough that we can start dogfooding in www.
TODO: Continue migrating Suspense tests, decide on better API names