Skip to content

Commit

Permalink
docs(dom): Document breaking changes of v8 (#866)
Browse files Browse the repository at this point in the history
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
  • Loading branch information
eps1lon and kentcdodds committed Jun 23, 2021
1 parent 70b61a5 commit ebb4a6b
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 166 deletions.
167 changes: 3 additions & 164 deletions docs/dom-testing-library/api-async.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1))
// ...
```

`waitFor` may run the callback a variable number of times.
`waitFor` may run the callback a number of times until the timeout is reached.
Note that the number of calls is constrained by the `timeout` and `interval` options.

This can be useful if you have a unit test that mocks API calls and you need to
wait for your mock promises to all resolve.
Expand All @@ -71,8 +72,7 @@ wait for are descendants of `container`.
The default `interval` is `50ms`. However it will run your callback immediately
before starting the intervals.

The default `timeout` is `1000ms` which will keep you under
[Jest's default timeout of `5000ms`](https://jestjs.io/docs/en/jest-object.html#jestsettimeouttimeout).
The default `timeout` is `1000ms`.

The default `onTimeout` takes the error and appends the `container`'s printed
state to the error message which should hopefully make it easier to track down
Expand Down Expand Up @@ -141,164 +141,3 @@ waitForElementToBeRemoved(() => getByText(/not here/i)).catch((err) =>
```

The options object is forwarded to `waitFor`.

## Deprecated Methods

`wait`, `waitForDomChange`, and `waitForElement` have been combined into the
`waitFor` method.

<details>

<br />

<summary>Deprecated Methods</summary>

### `wait`

> (DEPRECATED, use `waitFor` instead)

```typescript
function wait<T>(
callback: () => void,
options?: {
container?: HTMLElement
timeout?: number
interval?: number
mutationObserverOptions?: MutationObserverInit
}
): Promise<T>
```

Previously, wait was a wrapper around wait-for-expect and used polling instead
of a MutationObserver to look for changes. It is now an alias to waitFor and
will be removed in a future release.

Unlike wait, the callback parameter is mandatory in waitFor. Although you can
migrate an existing `wait()` call to `waitFor( () => {} )`, it is considered bad
practice to use an empty callback because it will make the tests more fragile.

### `waitForDomChange`

> (DEPRECATED, use `waitFor` instead)

```typescript
function waitForDomChange<T>(options?: {
container?: HTMLElement
timeout?: number
mutationObserverOptions?: MutationObserverInit
}): Promise<T>
```

When in need to wait for the DOM to change you can use `waitForDomChange`. The
`waitForDomChange` function is a small wrapper around the
[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).

Here is an example where the promise will be resolved because the container is
changed:

```javascript
const container = document.createElement('div')
waitForDomChange({ container })
.then(() => console.log('DOM changed!'))
.catch((err) => console.log(`Error you need to deal with: ${err}`))
container.append(document.createElement('p'))
// if 👆 was the only code affecting the container and it was not run,
// waitForDomChange would throw an error
```

The promise will resolve with a
[`mutationsList`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver)
which you can use to determine what kind of a change (or changes) affected the
container

```javascript
const container = document.createElement('div')
container.setAttribute('data-cool', 'true')
waitForDomChange({ container }).then((mutationsList) => {
const mutation = mutationsList[0]
console.log(
`was cool: ${mutation.oldValue}\ncurrently cool: ${mutation.target.dataset.cool}`
)
})
container.setAttribute('data-cool', 'false')
/*
logs:
was cool: true
currently cool: false
*/
```

The default `container` is the global `document`. Make sure the elements you
wait for are descendants of `container`.

The default `timeout` is `1000ms` which will keep you under
[Jest's default timeout of `5000ms`](https://jestjs.io/docs/en/jest-object.html#jestsettimeouttimeout).

The default `mutationObserverOptions` is
`{subtree: true, childList: true, attributes: true, characterData: true}` which
will detect additions and removals of child elements (including text nodes) in
the `container` and any of its descendants. It will also detect attribute
changes.

### `waitForElement`

> (DEPRECATED, use `find*` queries or `waitFor`)

```typescript
function waitForElement<T>(
callback: () => T,
options?: {
container?: HTMLElement
timeout?: number
mutationObserverOptions?: MutationObserverInit
}
): Promise<T>
```

When in need to wait for DOM elements to appear, disappear, or change you can
use `waitForElement`. The `waitForElement` function is a small wrapper around
the
[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).

Here's a simple example:

```javascript
// ...
// Wait until the callback does not throw an error and returns a truthy value. In this case, that means
// it'll wait until we can get a form control with a label that matches "username".
// Previously, the difference from `wait` is that rather than running your callback on
// an interval, it's run as soon as there are DOM changes in the container
// and returns the value returned by the callback.
const usernameElement = await waitForElement(
() => getByLabelText(container, 'username'),
{ container }
)
usernameElement.value = 'chucknorris'
// ...
```

You can also wait for multiple elements at once:

```javascript
const [usernameElement, passwordElement] = await waitForElement(
() => [
getByLabelText(container, 'username'),
getByLabelText(container, 'password'),
],
{ container }
)
```

The default `container` is the global `document`. Make sure the elements you
wait for will be attached to it, or set a different `container`.

The default `timeout` is `4500ms` which will keep you under
[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).

The default `mutationObserverOptions` is
`{subtree: true, childList: true, attributes: true, characterData: true}` which
will detect additions and removals of child elements (including text nodes) in
the `container` and any of its descendants. It will also detect attribute
changes.

</details>
11 changes: 9 additions & 2 deletions docs/dom-testing-library/api-debugging.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ tree of a node. This can be helpful for instance when debugging tests.
It is defined as:

```typescript
interface Options extends prettyFormat.OptionsReceived {
filterNode?: (node: Node) => boolean;
}

function prettyDOM(
node: HTMLElement,
maxLength?: number,
Expand All @@ -59,10 +63,13 @@ function prettyDOM(

It receives the root node to print out, an optional extra parameter to limit the
size of the resulting string, for cases when it becomes too large. It has a last
parameter which allows you to configure your formatting as defined in the
[options](https://github.com/facebook/jest/tree/master/packages/pretty-format#usage-with-options)
parameter which allows you to configure your formatting.
In addition to the options listed you can also pass the [options](https://github.com/facebook/jest/tree/master/packages/pretty-format#usage-with-options)
of `pretty-format`.

By default, `<style />`, `<script />` and comment nodes are ignored.
You can configure this behavior by passing a custom `filterNode` function that should return `true` for every node that you wish to include in the output.

This function is usually used alongside `console.log` to temporarily print out
DOM trees during tests for debugging purposes:

Expand Down

0 comments on commit ebb4a6b

Please sign in to comment.