Skip to content

Cheat Sheet should be updated to reflect that wait and waitForElement are deprecated #673

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

Closed
jonyyz opened this issue May 21, 2020 · 17 comments · Fixed by #711
Closed

Cheat Sheet should be updated to reflect that wait and waitForElement are deprecated #673

jonyyz opened this issue May 21, 2020 · 17 comments · Fixed by #711
Labels

Comments

@jonyyz
Copy link

jonyyz commented May 21, 2020

Cheat sheet URL: https://github.com/testing-library/react-testing-library/raw/master/other/cheat-sheet.pdf

Section in question:
image

@kentcdodds
Copy link
Member

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

@kettanaito
Copy link
Contributor

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

@weyert
Copy link
Contributor

weyert commented Jun 10, 2020

I will pick this ticket up :)

@weyert
Copy link
Contributor

weyert commented Jun 13, 2020

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

@kentcdodds
Copy link
Member

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!

@weyert
Copy link
Contributor

weyert commented Jun 14, 2020

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

@weyert
Copy link
Contributor

weyert commented Jun 14, 2020

I have worked a bit more on the cheat sheet

cheat-sheet-v2.5.pdf

@kentcdodds
Copy link
Member

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 :)

@weyert
Copy link
Contributor

weyert commented Jun 15, 2020

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

@MichaelDeBoey
Copy link
Member

@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

@weyert
Copy link
Contributor

weyert commented Jun 17, 2020

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

cheat-sheet-v2.7.pdf

@kentcdodds
Copy link
Member

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!

@weyert
Copy link
Contributor

weyert commented Jun 17, 2020

@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

@kentcdodds
Copy link
Member

SHIP IT!!!! :shipit:

ship it

That's awesome 👍

@weyert
Copy link
Contributor

weyert commented Jun 17, 2020

Sweet, I spend some time fixing the margins:

cheat-sheet-v2.9.pdf

@kentcdodds
Copy link
Member

🎉 This issue has been resolved in version 10.3.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@weyert
Copy link
Contributor

weyert commented Jun 18, 2020

Awesome thank you for merging :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants