-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Unit Tests: rewrite ReactDOM.render usages to RTL #45453
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
Conversation
|
|
|
Size Change: +1.54 kB (0%) Total Size: 1.28 MB
ℹ️ View Unchanged
|
tyxla
left a comment
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 looks great, thank you for beating me to it 🚀
I've left a few suggestions for improvement, let me know what you think!
| const { container, rerender } = render( <MergedRefs /> ); | ||
|
|
||
| const originalElement = rootElement.firstElementChild; | ||
| const originalElement = container.firstElementChild; |
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.
Do you mind altering the default tagName in MergedRefs above to be ul for example? That way instead of creating new ESLint violations for no-node-access, we'll be able to use screen.getByRole( 'list' )?
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.
That's a neat trick, I used it 🙂 getByRole also ensures that the element actually exists. That was one of my worries when migrating the test: is firstElementChild really an element, or is it undefined?
| ] ); | ||
|
|
||
| ReactDOM.render( null, rootElement ); | ||
| rerender( null ); |
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.
We should be able to use unmount from the result of render() above. It expresses our intentions more explicitly. WDYT?
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.
unmount() works, changed rerender( null ) instances to that 👍
| ); | ||
|
|
||
| expect( div.innerHTML ).toMatchSnapshot(); | ||
| expect( container.innerHTML ).toMatchSnapshot(); |
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.
Mind going with container instead? We'll need to update the snapshot, but at least we'll get rid of a no-node-access violation.
| expect( container.innerHTML ).toMatchSnapshot(); | |
| expect( container ).toMatchSnapshot(); |
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.
As the purpose of the test is to check whether the PluginPrePublishPanel was rendered at all, by filling in a slot, I modified the assertion to check for the panel title element (with getByText). Checking the entire markup with a snapshot is redundant, so I removed the snapshot completely.
|
Thanks for reviewing @tyxla! All the reported issues are addressed now. |
tyxla
left a comment
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.
Nice work! LGTM 🚀
| ); | ||
|
|
||
| expect( div.innerHTML ).toMatchSnapshot(); | ||
| expect( screen.getByText( 'My panel title' ) ).toBeInTheDocument(); |
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.
I've found that .toBeVisible() is even a bit more specific than .toBeInTheDocument(), but that's just me nitpicking, feel free to ignore it.
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.
Good idea, fixed.
By the way here's one place where our tests are happy with an invisible element, although they shouldn't be:
gutenberg/packages/block-editor/src/components/url-popover/test/__snapshots__/index.js.snap
Line 8 in bf6eddd
| style="position: absolute; opacity: 0; transform: translateY(-2em) scale(0) translateZ(0); transform-origin: 50% 0% 0;" |
That components-popover element is made visible with an animation, and this snapshot caught only the initial frame of the animation, where there is opacity: 0. It should wait for the animation to finish. Or specify animate={ false }. In that test the animation wouldn't even run because there are fake timers and nobody advances them.
There are some unit tests that use
ReactDOM.renderto render a React UI into a JSDOM element. But theReactDOM.renderAPI is deprecated in React 18.This PR is rewriting the
ReactDOM.renderto use therenderabstraction from Testing Library. Under the hood it does exactly the same thing, and when we eventually upgrade to React 18, we'll get an update tocreateRootfor free.Part of React 18 migration in #45235.