Skip to content

Commit

Permalink
fix: Updates deprecated matchers info (#378)
Browse files Browse the repository at this point in the history
  • Loading branch information
gnapse committed Jun 11, 2021
1 parent 87ffd2a commit fc9ce6d
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 80 deletions.
166 changes: 87 additions & 79 deletions README.md
Expand Up @@ -49,13 +49,13 @@ clear to read and to maintain.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->


- [Installation](#installation)
- [Usage](#usage)
- [With TypeScript](#with-typescript)
- [Custom matchers](#custom-matchers)
- [`toBeDisabled`](#tobedisabled)
- [`toBeEnabled`](#tobeenabled)
- [`toBeEmpty`](#tobeempty)
- [`toBeEmptyDOMElement`](#tobeemptydomelement)
- [`toBeInTheDocument`](#tobeinthedocument)
- [`toBeInvalid`](#tobeinvalid)
Expand All @@ -76,10 +76,11 @@ clear to read and to maintain.
- [`toHaveDisplayValue`](#tohavedisplayvalue)
- [`toBeChecked`](#tobechecked)
- [`toBePartiallyChecked`](#tobepartiallychecked)
- [`toHaveDescription`](#tohavedescription)
- [`toHaveErrorMessage`](#tohaveerrormessage)
- [Deprecated matchers](#deprecated-matchers)
- [`toBeEmpty`](#tobeempty)
- [`toBeInTheDOM`](#tobeinthedom)
- [`toHaveDescription`](#tohavedescription)
- [Inspiration](#inspiration)
- [Other Solutions](#other-solutions)
- [Guiding Principles](#guiding-principles)
Expand Down Expand Up @@ -205,31 +206,6 @@ your tests.
<hr />

### `toBeEmpty`

```typescript
toBeEmpty()
```

This allows you to assert whether an element has content or not.

#### Examples

```html
<span data-testid="not-empty"><span data-testid="empty"></span></span>
```

```javascript
expect(getByTestId('empty')).toBeEmpty()
expect(getByTestId('not-empty')).not.toBeEmpty()
```

> Note: This matcher is being deprecated due to a name clash with
> `jest-extended`. See more info in #216. In the future, please use only:
> [`toBeEmptyDOMElement`](#toBeEmptyDOMElement)
<hr />

### `toBeEmptyDOMElement`

```typescript
Expand Down Expand Up @@ -1081,58 +1057,6 @@ expect(inputCheckboxIndeterminate).toBePartiallyChecked()

<hr />

### `toHaveDescription`

```typescript
toHaveDescription(text: string | RegExp)
```

This allows you to check whether the given element has a description or not.

An element gets its description via the
[`aria-describedby` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute).
Set this to the `id` of one or more other elements. These elements may be nested
inside, be outside, or a sibling of the passed in element.

Whitespace is normalized. Using multiple ids will
[join the referenced elements’ text content separated by a space](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description).

When a `string` argument is passed through, it will perform a whole
case-sensitive match to the description text.

To perform a case-insensitive match, you can use a `RegExp` with the `/i`
modifier.

To perform a partial match, you can pass a `RegExp` or use
`expect.stringContaining("partial string")`.

#### Examples

```html
<button aria-label="Close" aria-describedby="description-close">
X
</button>
<div id="description-close">
Closing will discard any changes
</div>

<button>Delete</button>
```

```javascript
const closeButton = getByRole('button', {name: 'Close'})

expect(closeButton).toHaveDescription('Closing will discard any changes')
expect(closeButton).toHaveDescription(/will discard/) // to partially match
expect(closeButton).toHaveDescription(expect.stringContaining('will discard')) // to partially match
expect(closeButton).toHaveDescription(/^closing/i) // to use case-insensitive match
expect(closeButton).not.toHaveDescription('Other description')

const deleteButton = getByRole('button', {name: 'Delete'})
expect(deleteButton).not.toHaveDescription()
expect(deleteButton).toHaveDescription('') // Missing or empty description always becomes a blank string
```

### `toHaveErrorMessage`

```typescript
Expand Down Expand Up @@ -1187,8 +1111,36 @@ expect(timeInput).not.toHaveErrorMessage('Pikachu!')

## Deprecated matchers

### `toBeEmpty`

> Note: This matcher is being deprecated due to a name clash with
> `jest-extended`. See more info in #216. In the future, please use only
> [`toBeEmptyDOMElement`](#toBeEmptyDOMElement)
```typescript
toBeEmpty()
```

This allows you to assert whether an element has content or not.

#### Examples

```html
<span data-testid="not-empty"><span data-testid="empty"></span></span>
```

```javascript
expect(getByTestId('empty')).toBeEmpty()
expect(getByTestId('not-empty')).not.toBeEmpty()
```

<hr />

### `toBeInTheDOM`

> This custom matcher is deprecated. Prefer
> [`toBeInTheDocument`](#tobeinthedocument) instead.
```typescript
toBeInTheDOM()
```
Expand Down Expand Up @@ -1219,6 +1171,62 @@ expect(document.querySelector('.cancel-button')).toBeTruthy()
> replacing `toBeInTheDOM` to read through the documentation of the proposed
> alternatives to see which use case works better for your needs.
### `toHaveDescription`

> This custom matcher is deprecated. Prefer
> [`toHaveAccessibleDescription`](#tohaveaccessibledescription) instead, which
> is more comprehensive in implementing the official spec.
```typescript
toHaveDescription(text: string | RegExp)
```

This allows you to check whether the given element has a description or not.

An element gets its description via the
[`aria-describedby` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute).
Set this to the `id` of one or more other elements. These elements may be nested
inside, be outside, or a sibling of the passed in element.

Whitespace is normalized. Using multiple ids will
[join the referenced elements’ text content separated by a space](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description).

When a `string` argument is passed through, it will perform a whole
case-sensitive match to the description text.

To perform a case-insensitive match, you can use a `RegExp` with the `/i`
modifier.

To perform a partial match, you can pass a `RegExp` or use
`expect.stringContaining("partial string")`.

#### Examples

```html
<button aria-label="Close" aria-describedby="description-close">
X
</button>
<div id="description-close">
Closing will discard any changes
</div>

<button>Delete</button>
```

```javascript
const closeButton = getByRole('button', {name: 'Close'})

expect(closeButton).toHaveDescription('Closing will discard any changes')
expect(closeButton).toHaveDescription(/will discard/) // to partially match
expect(closeButton).toHaveDescription(expect.stringContaining('will discard')) // to partially match
expect(closeButton).toHaveDescription(/^closing/i) // to use case-insensitive match
expect(closeButton).not.toHaveDescription('Other description')

const deleteButton = getByRole('button', {name: 'Delete'})
expect(deleteButton).not.toHaveDescription()
expect(deleteButton).toHaveDescription('') // Missing or empty description always becomes a blank string
```

## Inspiration

This whole library was extracted out of Kent C. Dodds' [DOM Testing
Expand Down
50 changes: 50 additions & 0 deletions src/__tests__/to-have-accessible-description.js
Expand Up @@ -56,4 +56,54 @@ describe('.toHaveAccessibleDescription', () => {
expect(logo).not.toHaveAccessibleDescription('The logo of Our Company')
}).toThrow(/expected element not to have accessible description/i)
})

it('handles multiple ids', () => {
const {queryByTestId} = render(`
<div>
<div id="first">First description</div>
<div id="second">Second description</div>
<div id="third">Third description</div>
<div data-testid="multiple" aria-describedby="first second third"></div>
</div>
`)

expect(queryByTestId('multiple')).toHaveAccessibleDescription(
'First description Second description Third description',
)
expect(queryByTestId('multiple')).toHaveAccessibleDescription(
/Second description Third/,
)
expect(queryByTestId('multiple')).toHaveAccessibleDescription(
expect.stringContaining('Second description Third'),
)
expect(queryByTestId('multiple')).toHaveAccessibleDescription(
expect.stringMatching(/Second description Third/),
)
expect(queryByTestId('multiple')).not.toHaveAccessibleDescription(
'Something else',
)
expect(queryByTestId('multiple')).not.toHaveAccessibleDescription('First')
})

it('normalizes whitespace', () => {
const {queryByTestId} = render(`
<div id="first">
Step
1
of
4
</div>
<div id="second">
And
extra
description
</div>
<div data-testid="target" aria-describedby="first second"></div>
`)

expect(queryByTestId('target')).toHaveAccessibleDescription(
'Step 1 of 4 And extra description',
)
})
})
10 changes: 10 additions & 0 deletions src/__tests__/to-have-description.js
@@ -1,6 +1,16 @@
import {render} from './helpers/test-utils'

describe('.toHaveDescription', () => {
let spy
beforeAll(() => {
// @deprecated intentionally hiding warnings for test clarity
spy = jest.spyOn(console, 'warn').mockImplementation(() => {})
})

afterAll(() => {
spy.mockRestore()
})

test('handles positive test cases', () => {
const {queryByTestId} = render(`
<div id="description">The description</div>
Expand Down
7 changes: 6 additions & 1 deletion src/to-have-description.js
@@ -1,7 +1,12 @@
import {checkHtmlElement, getMessage, normalize} from './utils'
import {checkHtmlElement, getMessage, normalize, deprecate} from './utils'

// See algoritm: https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description
export function toHaveDescription(htmlElement, checkWith) {
deprecate(
'toBeInTheDOM',
'Please use toBeInTheDocument for searching the entire document and toContainElement for searching a specific container.',
)

checkHtmlElement(htmlElement, toHaveDescription, this)

const expectsDescription = checkWith !== undefined
Expand Down

0 comments on commit fc9ce6d

Please sign in to comment.