Skip to content

docs: add findByText example #616

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions docs/dom-testing-library/api-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ fireEvent.change(getByLabelText(/picture/i), {
},
})

// Note: The 'value' attribute must use ISO 8601 format when firing a
// change event on an input of type "date". Otherwise the element will not
// Note: The 'value' attribute must use ISO 8601 format when firing a
// change event on an input of type "date". Otherwise the element will not
// reflect the changed value.

// Invalid:
Expand Down Expand Up @@ -133,10 +133,10 @@ fireEvent(

## Using Jest Function Mocks

[Jest's Mock functions](https://jestjs.io/docs/en/mock-functions) can be used to test
that a callback passed to the function was called, or what it was called when the event
that **should** trigger the callback function does trigger the bound callback.

[Jest's Mock functions](https://jestjs.io/docs/en/mock-functions) can be used to
test that a callback passed to the function was called, or what it was called
when the event that **should** trigger the callback function does trigger the
bound callback.

<!--DOCUSAURUS_CODE_TABS-->

Expand All @@ -145,7 +145,9 @@ that **should** trigger the callback function does trigger the bound callback.
```jsx
import { render, screen } from '@testing-library/react'

const Button = ({onClick, children}) => <button onClick={onClick}>{children}</button>
const Button = ({ onClick, children }) => (
<button onClick={onClick}>{children}</button>
)

test('calls onClick prop when clicked', () => {
const handleClick = jest.fn()
Expand Down
7 changes: 4 additions & 3 deletions docs/ecosystem-user-event.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ title: user-event
---

[`user-event`][gh] is a companion library for Testing Library that provides more
advanced simulation of browser interactions than the built-in [`fireEvent`][docs]
method.
advanced simulation of browser interactions than the built-in
[`fireEvent`][docs] method.

```
npm install --save-dev @testing-library/user-event
Expand All @@ -26,4 +26,5 @@ test('types inside textarea', async () => {
- [user-event on GitHub][gh]

[gh]: https://github.com/testing-library/user-event
[docs]: https://testing-library.com/docs/dom-testing-library/api-events#fireevent
[docs]:
https://testing-library.com/docs/dom-testing-library/api-events#fireevent
147 changes: 147 additions & 0 deletions docs/example-findByText.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
id: example-findByText
title: example `findByText`
sidebar_label: findByText
---

```javascript
// src/__tests__/example.test.js
// 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 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 => {
el.innerHTML = `
<form id='login_form' method='post' name='login'>
<label for='username'>User Name:</label>

<input
type='text'
name='username'
id='username_input'
placeholder='Enter user name'
/>

<span id='username_required_error' style='color: red; display: none;'>
User Name Required
</span>

<span id='invalid_username_error' style='color: red; display: none;'>
Invalid User Name
</span>

<label for='password'>Password:</label>

<input
type='password'
name='password'
id='password_input'
placeholder='Enter password'
/>

<span id='invalid_password_error' style='color: red; display: none;'>
Invalid Password
</span>

<span id='password_required_error' style='color: red; display: none;'>
Password Required
</span>

<button id='submit' type='submit'>
Login
</button>
</form>
`

const submitButton = el.querySelector('#submit')
const formEl = el.querySelector('#login_form')

submitButton.addEventListener('click', () => {
const userInput = el.querySelector('#username_input')
const passwordInput = el.querySelector('#password_input')

var userName = userInput.value
var password = passwordInput.value
if (!userName) {
el.querySelector('#username_required_error').style.display = 'inline'
}

if (!password) {
el.querySelector('#password_required_error').style.display = 'inline'
}

if (userName && userName !== 'Bob') {
el.querySelector('#invalid_username_error').style.display = 'inline'
}

if (password && password !== 'theBuilder') {
el.querySelector('#invalid_password_error').style.display = 'inline'
}
})

formEl.addEventListener('submit', function(evt) {
evt.preventDefault()
window.history.back()
})

return el
}

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

beforeEach(() => {
div = document.createElement('div')
container = renderContent(div)
})

it('should show a required field warning for each empty input field', async () => {
userEvent.click(
getByRole(container, 'button', {
name: 'Login',
})
)

expect(
await findByText(container, "User Name Required")
).toBeVisible();

expect(
await findByText(container, "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')

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

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

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

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

expect(await findByText(container, 'Invalid User Name')).toBeVisible()
expect(await findByText(container, 'Invalid Password')).toBeVisible()
})
})
```
8 changes: 4 additions & 4 deletions docs/example-update-props.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ sidebar_label: Update Props
// the basic idea is to simply call `render` again and provide the same container
// that your first call created for you.

import React, {useRef} from 'react'
import {render, screen} from '@testing-library/react'
import React, { useRef } from 'react'
import { render, screen } from '@testing-library/react'

let idCounter = 1

const NumberDisplay = ({number}) => {
const NumberDisplay = ({ number }) => {
const id = useRef(idCounter++) // to ensure we don't remount a different instance

return (
Expand All @@ -26,7 +26,7 @@ const NumberDisplay = ({number}) => {
}

test('calling render with the same component on the same container does not remount', () => {
const {rerender} = render(<NumberDisplay number={1} />)
const { rerender } = render(<NumberDisplay number={1} />)
expect(screen.getByTestId('number-display')).toHaveTextContent('1')

// re-render the same component with different props
Expand Down
6 changes: 3 additions & 3 deletions docs/guide-disappearance.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ vice versa.

If you need to wait for an element to appear, the [async wait
utilities][async-api] allow you to wait for an assertion to be satisfied before
proceeding. The wait utilities retry until the query passes or times out.
*The async methods return a Promise, so you must always use `await` or
.then(done) when calling them.*
proceeding. The wait utilities retry until the query passes or times out. _The
async methods return a Promise, so you must always use `await` or .then(done)
when calling them._

```jsx
test('movie title appears', async () => {
Expand Down
4 changes: 2 additions & 2 deletions docs/react-testing-library/cheatsheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ A short guide to all the exported functions in `React Testing Library`
- `unmount` function to unmount the component
- `container` reference to the DOM node where the component is mounted
- all the queries from `DOM Testing Library`, bound to the document so there
is no need to pass a node as the first argument (usually, you can use
the `screen` import instead)
is no need to pass a node as the first argument (usually, you can use the
`screen` import instead)

```jsx
import { render, fireEvent, screen } from '@testing-library/react'
Expand Down
7 changes: 5 additions & 2 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ title: This Doc Needs To Be Edited
My new content here..
```

1. Refer to that doc's ID in an existing sidebar in `website/sidebar.json`:
Note: Ensure the file name and the id value do not include non-url safe
characters i.e. '\*'.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the website README to make sure future contributors don't use non-url safe characters.


2. Refer to that doc's ID in an existing sidebar in `website/sidebar.json`:

```javascript
// Add newly-created-doc to the Getting Started category of docs
Expand Down Expand Up @@ -192,7 +195,7 @@ For more information about the navigation bar, click

1. Docusaurus uses React components to build pages. The components are saved as
.js files in `website/pages/en`:
1. If you want your page to show up in your navigation header, you will need to
2. If you want your page to show up in your navigation header, you will need to
update `website/siteConfig.js` to add to the `headerLinks` element:

`website/siteConfig.js`
Expand Down
5 changes: 3 additions & 2 deletions website/sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,9 @@
],
"Examples": [
"example-codesandbox",
"example-external",
"example-findByText",
"example-input-event",
"example-update-props",
"example-react-context",
"example-react-hooks-useReducer",
"example-react-intl",
Expand All @@ -138,7 +139,7 @@
"example-reach-router",
"example-react-transition-group",
"example-react-modal",
"example-external"
"example-update-props"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reorganized these examples to be in alphabetical order

],
"Help": ["faq", "learning", "contributing"]
}
Expand Down