Skip to content

v7.0.0

Compare
Choose a tag to compare
@kentcdodds kentcdodds released this 12 Mar 21:55

7.0.0 (2020-03-12)

Features

  • waitFor: replace wait with waitFor (read more in the Breaking changes list below) (2b641e1), closes #376 #416
  • waitForElementToBeRemoved: support passing an element directly (#460) (1b711a4)

The new feature in waitForElementToBeRemoved is pretty cool. Here's what you had to do before:

const submitButton = screen.getByText(/submit/i)
fireEvent.click(submitButton)
await waitForElementToBeRemoved(() => screen.getByText(/submit/i))
// submit is now gone

That still works, but you can now do this too:

const submitButton = screen.getByText(/submit/i)
fireEvent.click(submitButton)
await waitForElementToBeRemoved(submitButton)
// submit is now gone

Cool right!?

BREAKING CHANGES

Drop Node 8

Node 10 or greater is required. Node 8 is out of LTS (#459) (c3ab843), closes #430

MutationObserver shim removed.

MutationObserver is supported by all major browsers and recent versions of JSDOM. If you need, you can create your own shim (using @sheerun/mutationobserver-shim) and attach it to the window. If you're on an old version of Jest, either update your version of Jest or use jest-environment-jsdom-sixteen (#457) (e3fdb8e9)

If you're using the latest version of react-scripts (Create React App), here are your options:

Option 1:

Wait until the react-scripts updates to the latest version of Jest (subscribe to this PR)

Option 2 (recommended):

Install jest-environment-jsdom-sixteen and then update your test script:

  ...
  "scripts": {
    ...
-   "test": "react-scripts test --env=dom"
+   "test": "react-scripts test --env=jest-environment-jsdom-sixteen"
    ...
  },
  ...
  "devDependencies": {
    ...
    "jest-environment-jsdom-sixteen": "^1.0.3",
    ...
  },
  ...

Option 3:

Add the MutationObserver constructor to window via @sheerun/mutationobserver-shim:

npm install --save-dev @sheerun/mutationobserver-shim
# yarn add --dev @sheerun/mutationobserver-shim
// src/setupTests.js
import MutationObserver from '@sheerun/mutationobserver-shim'
window.MutationObserver = MutationObserver

waitFor: wait is now deprecated in favor of waitFor

waitFor satisfies the use cases of wait, waitForElement, and waitForDomChange, so those have been deprecated (will be removed in the next major version). Here are some examples of how you can change those:

- await wait()
+ await waitFor(() => {})

This should get you going on the upgrade, but it's recommended to avoid an empty callback and instead insert an assertion in that callback function. This is because otherwise your test is relying on the "next tick of the event loop" before proceeding, and that's not consistent with the philosophy of the library:

The more your tests resemble the way your software is used, the more confidence they can give you.

So it would be better to move the assertion that followed await wait() into the callback you provide to await waitFor(() => { /* assertion here */ })

As for waitForElement, that should normally be accomplished with one of the find* queries:

- const element = await waitForElement(() => screen.getByText(/loading/i))
+ const element = await screen.findByText(/loading/i)

However, if for some reason you cannot use a find query, then waitFor should be a find/replace for waitForElement:

- const element = await waitForElement(() => container.querySelector('.loading'))
+ const element = await waitFor(() => container.querySelector('.loading'))

waitForDomChange encouraged testing implementation details because the user doesn't care about when the DOM changes, they care about when something appears or disappears from the page, so it's better to use waitFor with a specific assertion or waitForElementToBeRemoved (if that's what you're actually trying to do):

- await waitForDomChange()
+ await waitFor(() => {})
// remember, this is not recommended, provide a specific assertion

- await waitForDomChange(mutationObserverOptions)
+ await waitFor(() => {}, mutationObserverOptions)
// if you provided mutationObserverOptions, you can provide those as a second argument

Note that wait called your callback function on an interval and waitFor also does this, but it also calls your callback with the mutation observer as well, which is why it supports the use cases of the deprecated methods so well.

And to be clear, waitForElementToBeRemoved, is not getting deprecated or removed, in fact, it got a really neat new feature which you can read about above.

default timeout for async utilities is now 1000ms rather than 4500ms

Most of the time in the kinds of tests that people are writing with DOM Testing Library, if something doesn't happen within 1 second, then it probably won't happen at all and waiting a full 4.5 seconds is a frustrating amount of time. So that's why the default has been changed, however this can be configured when calling the async utility via the timeout option and it can also be globally configured: https://testing-library.com/docs/dom-testing-library/api-configuration

  • ByLabelText: If you used the selector option in ByLabelText queries, then you will probably need to update that code to be able to find the label you're looking for:
 // <label for="example-input" class="example">Example</label><input id="example-input" />
- screen.getByLabelText(/example/i, {selector: '.example'})
+ screen.getByLabelText(/example/i)
+ // or: screen.getByLabelText(/example/i, {selector: '#example-input})

Changed the selector option in ByLabelText queries.

If you used the selector option in ByLabelText queries, then you will probably need to update that code to be able to find the label you're looking for as a result of #373.