Skip to content

docs: update user-event references #1030

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

Merged
merged 11 commits into from
Mar 29, 2022
2 changes: 1 addition & 1 deletion docs/dom-testing-library/api-events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'
>
> Most projects have a few use cases for `fireEvent`, but the majority of the
> time you should probably use
> [`@testing-library/user-event`](ecosystem-user-event.mdx).
> [`@testing-library/user-event`](user-event/intro.mdx).

## `fireEvent`

Expand Down
2 changes: 1 addition & 1 deletion docs/dom-testing-library/install.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ install the wrapper:

`DOM Testing Library` works well with these companion libraries:

- [user-event](ecosystem-user-event.mdx) browser event simulation
- [user-event](user-event/intro.mdx) browser event simulation
- [jest-dom](ecosystem-jest-dom.mdx) custom Jest matchers
- [bs-jest-dom](ecosystem-bs-jest-dom.mdx) companion library for
`bs-react-testing-library`
Expand Down
9 changes: 5 additions & 4 deletions docs/ecosystem-user-event.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import TabItem from '@theme/TabItem'
advanced simulation of browser interactions than the built-in
[`fireEvent`](dom-testing-library/api-events.mdx#fireevent) method.

> This page describes `[email protected]`.
If you are starting or actively working on a project,
we recommend to use [`[email protected]`](user-event/intro.mdx) instead, as it includes important bug fixes and new features.
> This page describes `[email protected]`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of making this a warning https://docusaurus.io/docs/markdown-features/admonitions?
To me, this doesn't stand out and could be overlooked.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I converted those blockquotes on the intro into admonitions. :)

> This version is no longer maintained. Please use
> [`user-event@14`](user-event/intro.mdx) instead, as it includes important bug
> fixes and new features.

## Installation

Expand Down Expand Up @@ -222,7 +223,7 @@ import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'

test('prepend text', () => {
render(<input defaultValue="World!"/>)
render(<input defaultValue="World!" />)
const element = screen.getByRole('textbox')

// Prepend text
Expand Down
51 changes: 24 additions & 27 deletions docs/example-findByText.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ title: Using findByText
// This is an example of how to use findByText to query for text that
// is not visible right away

import {getByRole, findByText, getByPlaceholderText} from '@testing-library/dom'
import {screen} from '@testing-library/dom'
import userEvent from '@testing-library/user-event'
// provides a set of custom jest matchers that you can use to extend jest
// i.e. `.toBeVisible`
import '@testing-library/jest-dom'

const renderContent = el => {
function renderApp() {
const el = document.body.appendChild(document.createElement('div'))
el.innerHTML = `
<form id='login_form' method='post' name='login'>
<label for='username'>User Name:</label>
Expand Down Expand Up @@ -64,8 +65,8 @@ const renderContent = el => {
const userInput = el.querySelector('#username_input')
const passwordInput = el.querySelector('#password_input')

var userName = userInput.value
var password = passwordInput.value
const userName = userInput.value
const password = passwordInput.value
if (!userName) {
el.querySelector('#username_required_error').style.display = 'inline'
}
Expand All @@ -88,51 +89,47 @@ const renderContent = el => {
window.history.back()
})

return el
return {user: userEvent.setup()}
}

describe('findByText Examples', () => {
let div
let container

beforeEach(() => {
div = document.createElement('div')
container = renderContent(div)
})
afterEach(() => (document.body.innerHTML = ``))

describe('findByText Examples', () => {
it('should show a required field warning for each empty input field', async () => {
userEvent.click(
getByRole(container, 'button', {
const {user} = renderApp()
await user.click(
screen.getByRole('button', {
name: 'Login',
}),
)

expect(await findByText(container, 'User Name Required')).toBeVisible()
expect(await screen.findByText('User Name Required')).toBeVisible()

expect(await findByText(container, 'Password Required')).toBeVisible()
expect(await screen.findByText('Password Required')).toBeVisible()
})

it('should show invalid field errors for each invalid input field', async () => {
const userNameField = getByPlaceholderText(container, 'Enter user name')
const passwordField = getByPlaceholderText(container, 'Enter password')
const {user} = renderApp()
const userNameField = screen.getByPlaceholderText('Enter user name')
const passwordField = screen.getByPlaceholderText('Enter password')

expect(await findByText(container, 'Invalid Password')).not.toBeVisible()
expect(await findByText(container, 'Invalid User Name')).not.toBeVisible()
expect(await screen.findByText('Invalid Password')).not.toBeVisible()
expect(await screen.findByText('Invalid User Name')).not.toBeVisible()

userEvent.type(userNameField, 'Philchard')
userEvent.type(passwordField, 'theCat')
await user.type(userNameField, 'Philchard')
await user.type(passwordField, 'theCat')

expect(userNameField).toHaveValue('Philchard')
expect(passwordField).toHaveValue('theCat')

userEvent.click(
getByRole(container, 'button', {
await user.click(
screen.getByRole('button', {
name: 'Login',
}),
)

expect(await findByText(container, 'Invalid User Name')).toBeVisible()
expect(await findByText(container, 'Invalid Password')).toBeVisible()
expect(await screen.findByText('Invalid User Name')).toBeVisible()
expect(await screen.findByText('Invalid Password')).toBeVisible()
})
})
```
9 changes: 5 additions & 4 deletions docs/example-formik.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ import {MyForm} from './myForm.js'
test('rendering and submitting a basic Formik form', async () => {
const handleSubmit = jest.fn()
render(<MyForm onSubmit={handleSubmit} />)
const user = userEvent.setup()

userEvent.type(screen.getByLabelText(/first name/i), 'John')
userEvent.type(screen.getByLabelText(/last name/i), 'Dee')
userEvent.type(screen.getByLabelText(/email/i), '[email protected]')
await user.type(screen.getByLabelText(/first name/i), 'John')
await user.type(screen.getByLabelText(/last name/i), 'Dee')
await user.type(screen.getByLabelText(/email/i), '[email protected]')

userEvent.click(screen.getByRole('button', {name: /submit/i}))
await user.click(screen.getByRole('button', {name: /submit/i}))

await waitFor(() =>
expect(handleSubmit).toHaveBeenCalledWith({
Expand Down
3 changes: 1 addition & 2 deletions docs/example-input-event.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ sidebar_label: Input Event
> **Note**
>
> If you want to simulate a more natural typing behaviour while testing your
> component, consider the companion library
> [`user-event`](ecosystem-user-event.mdx)
> component, consider the companion library [`user-event`](user-event/intro.mdx)

```jsx
import React, {useState} from 'react'
Expand Down
18 changes: 10 additions & 8 deletions docs/example-react-router.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ import '@testing-library/jest-dom'

import {App, LocationDisplay} from './app'

test('full app rendering/navigating', () => {
test('full app rendering/navigating', async () => {
const history = createMemoryHistory()
render(
<Router history={history}>
<App />
</Router>,
)
const user = userEvent.setup()
// verify page content for expected route
// often you'd use a data-testid or role query, but this is also possible
expect(screen.getByText(/you are home/i)).toBeInTheDocument()

const leftClick = {button: 0}
userEvent.click(screen.getByText(/about/i), leftClick)
await user.click(screen.getByText(/about/i))

// check that the content changed to the new page
expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
Expand Down Expand Up @@ -127,18 +127,20 @@ test('full app rendering/navigating', () => {
const renderWithRouter = (ui, {route = '/'} = {}) => {
window.history.pushState({}, 'Test page', route)

return render(ui, {wrapper: BrowserRouter})
return {
user: userEvent.setup(),
...render(ui, {wrapper: BrowserRouter}),
}
}
```

```jsx
// app.test.js
test('full app rendering/navigating', () => {
renderWithRouter(<App />)
test('full app rendering/navigating', async () => {
const {user} = renderWithRouter(<App />)
expect(screen.getByText(/you are home/i)).toBeInTheDocument()

const leftClick = {button: 0}
userEvent.click(screen.getByText(/about/i), leftClick)
await user.click(screen.getByText(/about/i))

expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
})
Expand Down
2 changes: 1 addition & 1 deletion docs/guide-events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ simply using `fireEvent.click` is worth it.
We will describe a couple of simple adjustments to your tests that will increase
your confidence in the interactive behavior of your components. For other
interactions you may want to either consider using
[`user-event`](ecosystem-user-event.mdx) or testing your components in a real
[`user-event`](user-event/intro.mdx) or testing your components in a real
environment (e.g. manually, automatic with cypress, etc.).

### Keydown
Expand Down
6 changes: 3 additions & 3 deletions docs/queries/about.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ make use of semantic queries to test your page in the most accessible way.

After selecting an element, you can use the
[Events API](dom-testing-library/api-events.mdx) or
[user-event](ecosystem-user-event.mdx) to fire events and simulate user
interactions with the page, or use Jest and [jest-dom](ecosystem-jest-dom.mdx)
to make assertions about the element.
[user-event](user-event/intro.mdx) to fire events and simulate user interactions
with the page, or use Jest and [jest-dom](ecosystem-jest-dom.mdx) to make
assertions about the element.

There are Testing Library helper methods that work with queries. As elements
appear and disappear in response to actions,
Expand Down
32 changes: 18 additions & 14 deletions docs/react-testing-library/migrate-from-enzyme.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ some of the project's other libraries that can help you along the way:

- **[@testing-library/jest-dom](https://github.com/testing-library/jest-dom)**:
`jest-dom` provides a set of custom Jest matchers that you can use to extend
Jest. These make your tests more declarative, clearer to read, and easier
to maintain.
Jest. These make your tests more declarative, clearer to read, and easier to
maintain.

- **[@testing-library/user-event](https://github.com/testing-library/user-event):**
`user-event` tries to simulate the real events that happen in the browser as
Expand Down Expand Up @@ -120,8 +120,8 @@ test this component:

The following component gets a `name` from `props` and shows a welcome message
in an `h1` element. It also has a text input which users can change to a
different name, and the template updates accordingly. Check the live version
on [CodeSandbox](https://codesandbox.io/s/ecstatic-hellman-fh7in).
different name, and the template updates accordingly. Check the live version on
[CodeSandbox](https://codesandbox.io/s/ecstatic-hellman-fh7in).

```jsx
const Welcome = props => {
Expand Down Expand Up @@ -247,15 +247,15 @@ of the query documentation might help you understand the concepts better.
> A `<form>` element must have a `name` attribute in order to have an implicit
> `role` of `'form'` (as required by the specification).

React Testing Library aims to test the components how users use them. Users
see buttons, headings, forms and other elements by their role, not by their
`id`, `class`, or element tag name. Therefore, when you use React Testing
Library you should avoid accessing the DOM with the `document.querySelector`
API. (You _can_ use it in your tests, but it's not recommended for the reasons
stated in this paragraph.)
React Testing Library aims to test the components how users use them. Users see
buttons, headings, forms and other elements by their role, not by their `id`,
`class`, or element tag name. Therefore, when you use React Testing Library you
should avoid accessing the DOM with the `document.querySelector` API. (You _can_
use it in your tests, but it's not recommended for the reasons stated in this
paragraph.)

React Testing Library exposes some handy query APIs which help you access
the component elements efficiently. You can see the
React Testing Library exposes some handy query APIs which help you access the
component elements efficiently. You can see the
[list of available queries here](queries/about.mdx#types-of-queries). If you're
not sure which query you should use in a given situation, we have a great page
which explains [which query to use](queries/about.mdx#priority), so check it
Expand Down Expand Up @@ -330,10 +330,14 @@ input's "checked" property is properly set. Let's see how we might write a test
for that case:

```jsx
test('handles click correctly', () => {
test('handles click correctly', async () => {
render(<Checkbox />)
const user = userEvent.setup()

// You can also call this method directly on userEvent,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if that's even something we want to "share". If we believe that the recommended approach is to use the methods returned from setup, maybe this comment isn't helpful and can only cause bad practices. Wdyt?

Copy link
Member Author

@ph-fritsche ph-fritsche Mar 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it eases the transition for people who are used to the previous APIs. That's why the Direct APIs still exist.

If there is only a single API call, it makes no difference, as the Direct APIs call .setup() internally and then use the method from there.

If it helps or hurts to mention it in the example - I don't know.
But I thought maybe mentioning it makes it sound "easier" to use.

// but using the methods from `.setup()` is recommended.
await user.click(screen.getByText('Check'))

userEvent.click(screen.getByText('Check'))
expect(screen.getByLabelText('Check')).toBeChecked()
})
```
Expand Down
6 changes: 3 additions & 3 deletions docs/user-event/api-keyboard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ keyboard('{Shift>}A{/Shift}') // translates to: Shift(down), A, Shift(up)
```

The mapping of `key` to `code` is performed by a
[default key map](https://github.com/testing-library/user-event/blob/beta/src/keyboard/keyMap.ts)
[default key map](https://github.com/testing-library/user-event/blob/main/src/keyboard/keyMap.ts)
portraying a "default" US-keyboard. You can provide your own local keyboard
mapping per [`keyboardMap`](options.mdx#keyboardmap) option.

Expand All @@ -79,5 +79,5 @@ keys.
> Future versions might try to interpolate the modifiers needed to reach a
> printable key on the keyboard. E.g. Automatically pressing `{Shift}` when
> CapsLock is not active and `A` is referenced. If you don't wish this behavior,
> you can deactivate the [`autoModify`](options.mdx#automodify) option to opt out
> of this non-breaking change.
> you can deactivate the [`autoModify`](options.mdx#automodify) option to opt
> out of this non-breaking change.
10 changes: 5 additions & 5 deletions docs/user-event/install.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import TabItem from '@theme/TabItem'
<TabItem value="npm">

```sh
npm install --save-dev @testing-library/user-event@^14.0.0-beta
npm install --save-dev @testing-library/user-event
```

</TabItem>
<TabItem value="yarn">

```sh
yarn add --dev @testing-library/user-event@^14.0.0-beta
yarn add --dev @testing-library/user-event
```

</TabItem>
Expand All @@ -29,8 +29,8 @@ yarn add --dev @testing-library/user-event@^14.0.0-beta
Note that `@testing-library/user-event` requires `@testing-library/dom`.

If you use one of the
[framework wrappers](../dom-testing-library/install.mdx#wrappers), it is important
that `@testing-library/dom` is resolved to the same installation required by the
framework wrapper of your choice.
[framework wrappers](../dom-testing-library/install.mdx#wrappers), it is
important that `@testing-library/dom` is resolved to the same installation
required by the framework wrapper of your choice.
Usually this means that if you use one of the framework wrappers, you should not
add `@testing-library/dom` to your project dependencies.
Loading