Skip to content
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

fix: Updates deprecated matchers info #378

Merged
merged 1 commit into from
Jun 11, 2021
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
166 changes: 87 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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',
Copy link

Choose a reason for hiding this comment

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

Should be 'toHaveDescription'

'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