-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Unit Tests: rewrite ReactDOM.render usages to RTL #45453
Conversation
Open in CodeSandbox Web Editor | VS Code | VS Code Insiders |
Size Change: +1.54 kB (0%) Total Size: 1.28 MB
ℹ️ View Unchanged
|
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 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
?
@@ -104,7 +95,7 @@ describe( 'useMergeRefs', () => { | |||
[ [], [] ], | |||
] ); | |||
|
|||
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. |
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.render
to render a React UI into a JSDOM element. But theReactDOM.render
API is deprecated in React 18.This PR is rewriting the
ReactDOM.render
to use therender
abstraction 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 tocreateRoot
for free.Part of React 18 migration in #45235.