React-testing-library: Cheat Sheet should be updated to reflect that wait and waitForElement are deprecated

Created on 21 May 2020  ·  17Comments  ·  Source: testing-library/react-testing-library

Most helpful comment

I will pick this ticket up :)

All 17 comments

Ah yeah, that'll need to get updated. @bcarroll22 do you still have the original source file for that?

The React Example also uses waitFor, which has been replaced by wait.

I will pick this ticket up :)

This is a first draft of the content; please ignore the shaky layout. Oh, this an slightly version a newer version refers to @testing-library/dom instead of user-event :)

cheat-sheet-v2.4.pdf

Thanks for working on this @weyert! Here are a few bits of feedback (these are just my thoughts, feel free to disagree):

render a component:

  • Remove the comment about the render result. 99% of the time people shouldn't care about the return value of render.

search the DOM:

This doesn't seem like the place to include references to assertions. Remove the comment.

fire an event:

  • Let's remove this section entirely. It's for more advanced use cases now that user-event will be built-into @testing-library/dom (and re-exported from @testing-library/react)

interact with element:

  • Change UserEvent to userEvent and it should be: import {userEvent} from '@testing-library/react' (this doesn't work yet, but it will very soon.

wait for something:

Place an assertion in the callback. Something like:

await waitFor(() => expect(mockFn).toHaveBeenCalledWith('some argument'))

If you're waiting for an element, you should use find* queries.

search variants (return value):

  • Error is not the "return value" so instead let's title this "search variants (result)".
  • queryBy should be Element or null
  • both of the find variants return a promise that resolves to the element(s) or rejects with an error when it times out, so they should be Promise<Element> or Promise<Rejection> and Promise<Element[]> or Promise<Rejection>

(DOM attribute) search types:

  • It's weird to have the parentheses at the front. Also, I'm not sure what "DOM attribute" would refer to here. Let's change it to: search types (result)
  • DisplayValue should be something like <input value="display value" />

text matches:

  • I want to change this example from text which is not typically recommended, to role which is most recommended. So let's do this:
render(<label>Remember Me <input type="checkbox" /></label>)

screen.getByRole('checkbox', {name: /remember me/i}) // ✅
screen.getByRole('checkbox', {name: 'remember me'})  // ❌
screen.getByRole('checkbox', {name: 'Remember Me'})  // ✅

// other queries accept text matches as well
// the text match argument can also be a function
screen.getByText((text, element) => {/* return true/false */})

wait for appearance:

This should use find* queries instead:

test('movie title appears', async () => {
  render(<Movie />)
  // element is initially not present...
  // wait for appearance
  const movieTitle = await findByText(/the lion king/i)
})

wait for element to be removed:

Let's do this:

test('submit button disappears', async () => {
  // Element is initially present...
  // Wait for element to be removed
  await waitForElementToBeRemoved(screen.getByRole('button', {name: /submit/i}))
})

the screen object (description):

I believe this used to be the "render result" section, so it's mostly wrong. All the screen object has are all the queries and the debug function. So this could probably just say that screen is how you query elements on the page and you can use the screen.debug() feature to print out the DOM at any time.

Thanks so much fo this! Love it!

Thank you for your feedback @kentcdodds. I will play around and apply your changes :)

I have worked a bit more on the cheat sheet

cheat-sheet-v2.5.pdf

render a component:

search the DOM:

Make sure we import render and let's switch the example to make sure we encourage *ByRole first:

import {screen, render} from '@testing-library/react'
render(<label>Remember Me <input type="checkbox" /></label>)
const checkboxInput = screen.getByRole('checkbox', {name: /remember me/i})

interact with element:

Make sure we import that correctly:

import {userEvent} from '@testing-library/react'

The userEvent.type arguments are in the wrong order

Make sure to add await before both of those userEvent calls.

screen:

"Queries for the baseElement" should actually say "Functions to query the DOM."

search variants (result):

I think we could avoid the last line being on multiple lines if we reduce the padding in the left column a bit.

search types:

The table is not alternating white and gray rows. AltText and Title are side-by-side and both white.

text matches:

This example isn't quite right. The first line is rendering "Hello World" and is missing a closing parentheses. The example I gave in my previous comment should work perfectly as a copy/paste I think.

wait for appearance:

wait for element to be removed:

The argument passed to waitForElementToBeRemoved should be a callback:

await waitForElementToBeRemoved(
  () => screen.getByRole('button', {name: /submit/i})
)

wait for something:

Could we reformat this a tiny bit? Could probably be:

await waitFor(() =>
  expect(mockFn).toHaveBeenCalledWith('some argument')
)

render() options:

Let's leave off container and baseElement, people shouldn't typically change those. hydrate() should not have () and should instead just be hydrate.

Making great progress :)

Thank you for your feedback, I have applied some of the feedback already this morning. I will have a second look over my lunch break to double check.

If anyone see any other typos/mistakes, don't hesitate to let me know! Also as you can see there is still bits of a space left, so if think of anything else that could be added (examples or callouts), let me know.

cheat-sheet-v2.6.pdf

@weyert Since all changes to @testing-library/user-event aren't merged into @testing-library/dom (yet) and are released as a new version, be sure to update the "interact with element" part

Updated the cheat sheet so it's referring to @testing-library/user-event-again

cheat-sheet-v2.7.pdf

Cool!

search the DOM:

Could we reformat that a tiny bit so it doesn't run onto two lines like it does?

const checkboxInput = screen.getByRole(
  'checkbox',
  {name: /remember me/i}
)

interact with element:

We backtracked on the async stuff (which is why the merge didn't happen) and now everything is sync not async. So remove the await on both of those please. (Sorry about that). Should be able to make those one liners now.

wait for appearance, wait for element to be removed, and wait for something:

I think all three of these could be simplified and combined into a single box titled wait for things. And here's what it could have in it:

// the element isn't available yet, so wait for it:
const movieTitle = await screen.findByText(/the lion king/i)

// the element is there but we want to wait for it to be removed
await waitForElementToBeRemoved(() => screen.getByLabelText(/loading/i))

// we want to wait until an assertion passes
await waitFor(() => expect(mockFn).toHaveBeenCalledWith('some arg'))

If those lines are too long, then use this and adjust the print width option.

Looking great!

@kentcdodds I have updated the PDF with your latest comments and I also have added the colour coding as shown by Prettier to it:

cheat-sheet-v2.8.pdf

Let me know, if you are happy with it, then I will make a PR with the source file + PDF

SHIP IT!!!! :shipit:

ship it

That's awesome 👍

Sweet, I spend some time fixing the margins:

cheat-sheet-v2.9.pdf

:tada: This issue has been resolved in version 10.3.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

Awesome thank you for merging :)

Was this page helpful?
0 / 5 - 0 ratings