diff --git a/README.md b/README.md
index dac65a0f..59364ffb 100644
--- a/README.md
+++ b/README.md
@@ -45,17 +45,17 @@ to maintain.
- [Installation](#installation)
- [Usage](#usage)
- [Custom matchers](#custom-matchers)
+ - [`toBeDisabled`](#tobedisabled)
- [`toBeEmpty`](#tobeempty)
- [`toBeInTheDocument`](#tobeinthedocument)
+ - [`toBeVisible`](#tobevisible)
- [`toContainElement`](#tocontainelement)
- [`toContainHTML`](#tocontainhtml)
- - [`toHaveTextContent`](#tohavetextcontent)
- [`toHaveAttribute`](#tohaveattribute)
- [`toHaveClass`](#tohaveclass)
- - [`toHaveStyle`](#tohavestyle)
- [`toHaveFocus`](#tohavefocus)
- - [`toBeVisible`](#tobevisible)
- - [`toBeDisabled`](#tobedisabled)
+ - [`toHaveStyle`](#tohavestyle)
+ - [`toHaveTextContent`](#tohavetextcontent)
- [Deprecated matchers](#deprecated-matchers)
- [`toBeInTheDOM`](#tobeinthedom)
- [Inspiration](#inspiration)
@@ -100,6 +100,49 @@ expect.extend({toBeInTheDocument, toHaveClass})
## Custom matchers
+`jest-dom` can work with any library or framework that returns DOM elements from queries. The custom matcher examples below demonstrate using `document.querySelector` and [dom-testing-library](https://github.com/kentcdodds/dom-testing-library) for querying DOM elements.
+
+### `toBeDisabled`
+
+```typescript
+toBeDisabled()
+```
+
+This allows you to check whether an element is disabled from the user's perspective.
+
+It matches if the element is a form control and the `disabled` attribute is
+specified on this element or the element is a descendant of a form element
+with a `disabled` attribute.
+
+According to the specification, the following elements can be [actually disabled](https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements):
+`button`, `input`, `select`, `textarea`, `optgroup`, `option`, `fieldset`.
+
+#### Examples
+
+```html
+
+
+link
+```
+
+##### Using document.querySelector
+
+```javascript
+expect(document.querySelector('[data-testid="button"]')).toBeDisabled()
+expect(document.querySelector('[data-testid="input"]')).toBeDisabled()
+expect(document.querySelector('a')).not.toBeDisabled()
+```
+
+##### Using dom-testing-library
+
+```javascript
+expect(getByTestId(container, 'button')).toBeDisabled()
+expect(getByTestId(container, 'input')).toBeDisabled()
+expect(getByText(container, 'link')).not.toBeDisabled()
+```
+
+
+
### `toBeEmpty`
```typescript
@@ -108,17 +151,28 @@ toBeEmpty()
This allows you to assert whether an element has content or not.
+#### Examples
+
+```html
+
+```
+
+##### Using document.querySelector
+
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+expect(document.querySelector('[data-testid="empty"]').toBeEmpty()
+expect(document.querySelector('[data-testid="not-empty"]').not.toBeEmpty()
+```
+
+##### Using dom-testing-library
-// ...
-//
+```javascript
expect(queryByTestId(container, 'empty')).toBeEmpty()
expect(queryByTestId(container, 'not-empty')).not.toBeEmpty()
-// ...
```
+
+
### `toBeInTheDocument`
```typescript
@@ -127,26 +181,92 @@ toBeInTheDocument()
This allows you to assert whether an element is present in the document or not.
-```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+#### Examples
+
+```html
+Html Element
+
+```
-// ...
-// document.body.innerHTML = `Html Element`
+##### Using document.querySelector
-// const htmlElement = document.querySelector('[data-testid="html-element"]')
-// const svgElement = document.querySelector('[data-testid="svg-element"]')
-// const nonExistantElement = document.querySelector('does-not-exist')
-// const detachedElement = document.createElement('div')
+```javascript
+const htmlElement = document.querySelector('[data-testid="html-element"]')
+const svgElement = document.querySelector('[data-testid="svg-element"]')
+const nonExistantElement = document.querySelector('does-not-exist')
+const detachedElement = document.createElement('div')
expect(htmlElement).toBeInTheDocument()
expect(svgElement).toBeInTheDocument()
expect(detacthedElement).not.toBeInTheDocument()
expect(nonExistantElement).not.toBeInTheDocument()
-// ...
```
-> Note: This will not find detached elements. The element must be added to the document to be found. If you desire to search in a detached element please use: [`toContainElement`](#tocontainelement)
+##### Using dom-testing-library
+
+```javascript
+expect(
+ queryByTestId(document.documentElement, 'html-element'),
+).toBeInTheDocument()
+expect(
+ queryByTestId(document.documentElement, 'svg-element'),
+).toBeInTheDocument()
+expect(
+ queryByTestId(document.documentElement, 'does-not-exist'),
+).not.toBeInTheDocument()
+```
+
+> Note: This matcher does not find detached elements. The element must be added to the document to be found by toBeInTheDocument. If you desire to search in a detached element please use: [`toContainElement`](#tocontainelement)
+
+
+
+### `toBeVisible`
+
+```typescript
+toBeVisible()
+```
+
+This allows you to check if an element is currently visible to the user.
+
+An element is visible if **all** the following conditions are met:
+
+- it does not have its css property `display` set to `none`
+- it does not have its css property `visibility` set to either `hidden` or
+ `collapse`
+- it does not have its css property `opacity` set to `0`
+- its parent element is also visible (and so on up to the top of the DOM tree)
+
+#### Examples
+
+```html
+
Zero Opacity Example
+
Visibility Hidden Example
+
Display None Example
+
Hidden Parent Example
+
Visible Example
+```
+
+##### Using document.querySelector
+
+```javascript
+expect(document.querySelector('[data-testid="zero-opacity"]'])).not.toBeVisible()
+expect(document.querySelector('[data-testid="visibility-hidden"]'])).not.toBeVisible()
+expect(document.querySelector('[data-testid="display-none"]'])).not.toBeVisible()
+expect(document.querySelector('[data-testid="hidden-parent"]'])).not.toBeVisible()
+expect(document.querySelector('[data-testid="visible"]'])).toBeVisible()
+```
+
+##### Using dom-testing-library
+
+```javascript
+expect(getByText(container, 'Zero Opacity Example')).not.toBeVisible()
+expect(getByText(container, 'Visibility Hidden Example')).not.toBeVisible()
+expect(getByText(container, 'Display None Example')).not.toBeVisible()
+expect(getByText(container, 'Hidden Parent Example')).not.toBeVisible()
+expect(getByText(container, 'Visible Example')).toBeVisible()
+```
+
+
### `toContainElement`
@@ -156,12 +276,31 @@ toContainElement(element: HTMLElement | SVGElement | null)
This allows you to assert whether an element contains another element as a descendant or not.
+#### Examples
+
+```html
+
+```
+
+##### Using document.querySelector
+
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+const ancestor = document.querySelector('[data-testid="ancestor"]')
+const descendant = document.querySelector('[data-testid="descendant"]')
+const nonExistantElement = document.querySelector(
+ '[data-testid="does-not-exist"]',
+)
+
+expect(ancestor).toContainElement(descendant)
+expect(descendant).not.toContainElement(ancestor)
+expect(ancestor).not.toContainElement(nonExistantElement)
+```
+
+##### Using dom-testing-library
+
+```javascript
+const {queryByTestId} = render(/* Rendered HTML */)
-// ...
-//
const ancestor = queryByTestId(container, 'ancestor')
const descendant = queryByTestId(container, 'descendant')
const nonExistantElement = queryByTestId(container, 'does-not-exist')
@@ -169,9 +308,10 @@ const nonExistantElement = queryByTestId(container, 'does-not-exist')
expect(ancestor).toContainElement(descendant)
expect(descendant).not.toContainElement(ancestor)
expect(ancestor).not.toContainElement(nonExistantElement)
-// ...
```
+
+
### `toContainHTML`
```typescript
@@ -180,15 +320,26 @@ toContainHTML(htmlText: string)
Assert whether a string representing a HTML element is contained in another element:
+#### Examples
+
+```html
+
+```
+
+##### Using document.querySelector
+
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+expect(document.querySelector('[data-testid="parent"]')).toContainHTML(
+ '',
+)
+```
+
+##### Using dom-testing-library
-// ...
-//
-const parent = queryByTestId('parent')
-expect(parentElement).toContainHTML('')
-// ...
+```javascript
+expect(getByTestId(container, 'parent')).toContainHTML(
+ '',
+)
```
> Chances are you probably do not need to use this matcher. We encourage testing from the perspective of how the user perceives the app in a browser. That's why testing against a specific DOM structure is not advised.
@@ -197,51 +348,45 @@ expect(parentElement).toContainHTML('')
>
> It should not be used to check DOM structure that you control. Please use [`toContainElement`](#tocontainelement) instead.
-### `toHaveTextContent`
+
+
+### `toHaveAttribute`
```typescript
-toHaveTextContent(text: string | RegExp)
+toHaveAttribute(attr: string, value?: string)
```
-This API allows you to check whether the given element has a text content or not.
+This allows you to check whether the given element has an attribute or not. You
+can also optionally check that the attribute has a specific expected value.
-```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+#### Examples
-// ...
-// 2
-expect(getByTestId(container, 'count-value')).toHaveTextContent('2')
-expect(getByTestId(container, 'count-value')).not.toHaveTextContent('21')
-// ...
+```html
+
```
-### `toHaveAttribute`
+##### Using document.querySelector
-```typescript
-toHaveAttribute(attr: string, value?: string)
+```javascript
+const button = document.querySelector('[data-testid="ok-button"]')
+
+expect(button).toHaveAttribute('disabled')
+expect(button).toHaveAttribute('type', 'submit')
+expect(button).not.toHaveAttribute('type', 'button')
```
-This allows you to check whether the given element has an attribute or not. You
-can also optionally check that the attribute has a specific expected value.
+##### Using dom-testing-library
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+const button = getByTestId(container, 'ok-button')
-// ...
-//
-expect(getByTestId(container, 'ok-button')).toHaveAttribute('disabled')
-expect(getByTestId(container, 'ok-button')).toHaveAttribute('type', 'submit')
-expect(getByTestId(container, 'ok-button')).not.toHaveAttribute(
- 'type',
- 'button',
-)
-// ...
+expect(button).toHaveAttribute('disabled')
+expect(button).toHaveAttribute('type', 'submit')
+expect(button).not.toHaveAttribute('type', 'button')
```
+
+
### `toHaveClass`
```typescript
@@ -251,65 +396,45 @@ toHaveClass(...classNames: string[])
This allows you to check whether the given element has certain classes within its
`class` attribute.
-```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+You must provide at least one class, unless you are asserting that an element
+does not have any classes.
-// ...
-//
-expect(getByTestId(container, 'delete-button')).toHaveClass('extra')
-expect(getByTestId(container, 'delete-button')).toHaveClass('btn-danger btn')
-expect(getByTestId(container, 'delete-button')).toHaveClass('btn-danger', 'btn')
-expect(getByTestId(container, 'delete-button')).not.toHaveClass('btn-link')
-// ...
+#### Examples
+
+```html
+
+
```
-You must provide at least one class, unless you are asserting that an element
-does not have any classes.
+##### Using document.querySelector
```javascript
-// ...
-//
-expect(getByTestId(container, 'no-classes')).not.toHaveClass()
-```
+const deleteButton = document.querySelector('[data-testid="delete-button"]')
+const noClasses = document.querySelector('[data-testid="no-classes"]')
-### `toHaveStyle`
+expect(deleteButton).toHaveClass('extra')
+expect(deleteButton).toHaveClass('btn-danger btn')
+expect(deleteButton).toHaveClass('btn-danger', 'btn')
+expect(deleteButton).not.toHaveClass('btn-link')
-```typescript
-toHaveStyle(css: string)
+expect(noClasses).not.toHaveClass()
```
-This allows you to check if a certain element has some specific css properties
-with specific values applied. It matches only if the element has _all_ the
-expected properties applied, not just some of them.
+##### Using dom-testing-library
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+const deleteButton = getByTestId(container, 'delete-button')
+const noClasses = getByTestId(container, 'no-classes')
-// ...
-//
-expect(getByTestId(container, 'delete-button')).toHaveStyle('display: none')
-expect(getByTestId(container, 'delete-button')).toHaveStyle(`
- color: red;
- display: none;
-`)
-expect(getByTestId(container, 'delete-button')).not.toHaveStyle(`
- display: none;
- color: blue;
-`)
-// ...
+expect(deleteButton).toHaveClass('extra')
+expect(deleteButton).toHaveClass('btn-danger btn')
+expect(deleteButton).toHaveClass('btn-danger', 'btn')
+expect(deleteButton).not.toHaveClass('btn-link')
+
+expect(noClasses).not.toHaveClass()
```
-This also works with rules that are applied to the element via a class name for
-which some rules are defined in a stylesheet currently active in the document.
-The usual rules of css precedence apply.
+
### `toHaveFocus`
@@ -319,93 +444,130 @@ toHaveFocus()
This allows you to assert whether an element has focus or not.
+#### Examples
+
+```html
+
+```
+
+##### Using document.querySelector
+
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+const input = document.querySelector(['data-testid="element-to-focus"')
+
+input.focus()
+expect(input).toHaveFocus()
+
+input.blur()
+expect(input).not.toHaveFocus()
+```
-// ...
-//
-// const { container } = render(...)
-// const input = container.querySelector('#focused');
+##### Using dom-testing-library
-// input.focus()
-expect(queryByTestId(container, 'focused')).toHaveFocus()
+```javascript
+const input = queryByTestId(container, 'element-to-focus')
-// input.blur()
-expect(queryByTestId(container, 'focused')).not.toHaveFocus()
+fireEvent.focus(input)
+expect(input).toHaveFocus()
-// ...
+fireEvent.blur(input)
+expect(input).not.toHaveFocus()
```
-### `toBeVisible`
+
+
+### `toHaveStyle`
```typescript
-toBeVisible()
+toHaveStyle(css: string)
```
-This allows you to check if an element is currently visible to the user.
+This allows you to check if a certain element has some specific css properties
+with specific values applied. It matches only if the element has _all_ the
+expected properties applied, not just some of them.
-An element is visible if **all** the following conditions are met:
+#### Examples
-- it does not have its css property `display` set to `none`
-- it does not have its css property `visibility` set to either `hidden` or
- `collapse`
-- it does not have its css property `opacity` set to `0`
-- its parent element is also visible (and so on up to the top of the DOM tree)
+```html
+
+```
+
+##### Using document.querySelector
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+const input = document.querySelector(['data-testid="delete-button"')
-// ...
-//
-//
Page title
-//
-//
-//
Hello World
-//
-expect(container.querySelector('header')).toBeVisible()
-expect(container.querySelector('h1')).not.toBeVisible()
-expect(container.querySelector('strong')).not.toBeVisible()
-// ...
+expect(button).toHaveStyle('display: none')
+expect(button).toHaveStyle(`
+ color: red;
+ display: none;
+`)
+expect(button).not.toHaveStyle(`
+ display: none;
+ color: blue;
+`)
```
-### `toBeDisabled`
+##### Using dom-testing-library
+
+```javascript
+const button = getByTestId(container, 'delete-button')
+
+expect(button).toHaveStyle('display: none')
+expect(button).toHaveStyle(`
+ color: red;
+ display: none;
+`)
+expect(button).not.toHaveStyle(`
+ display: none;
+ color: blue;
+`)
+```
+
+This also works with rules that are applied to the element via a class name for
+which some rules are defined in a stylesheet currently active in the document.
+The usual rules of css precedence apply.
+
+
+
+### `toHaveTextContent`
```typescript
-toBeDisabled()
+toHaveTextContent(text: string | RegExp)
```
-This allows you to check whether an element is disabled from the user's perspective.
+This API allows you to check whether the given element has a text content or not.
-It matches if the element is a form control and the `disabled` attribute is
-specified on this element or the element is a descendant of a form element
-with a `disabled` attribute.
+#### Examples
-According to the specification, the following elements can be [actually disabled](https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements):
-`button`, `input`, `select`, `textarea`, `optgroup`, `option`, `fieldset`.
+```html
+2
+```
+
+##### Using document.querySelector
```javascript
-// add the custom expect matchers once
-import 'jest-dom/extend-expect'
+const button = document.querySelector('[data-testid="count-value"]')
-// ...
-//
-//
-expect(getByTestId(container, 'button')).toBeDisabled()
-expect(getByTestId(container, 'text')).toBeDisabled()
-// ...
+expect(content).toHaveTextContent('2')
+expect(content).toHaveTextContent(/^2$/)
+expect(content).not.toHaveTextContent('21')
+```
-// ...
-// LINK
-expect(getByText(container, 'LINK')).not.toBeDisabled()
-// ...
+##### Using dom-testing-library
+
+```javascript
+const content = getByTestId(container, 'count-value')
+
+expect(content).toHaveTextContent('2')
+expect(content).toHaveTextContent(/^2$/)
+expect(content).not.toHaveTextContent('21')
```
+
+
## Deprecated matchers
### `toBeInTheDOM`