Skip to content

Commit 87ffd2a

Browse files
gnapseeps1lon
andauthored
feat: toHaveAccessibleName and toHaveAccessibleDescription (#377)
* Add toHaveAccessibleName * Add toHaveAccessibleDescription * Update README.md Co-authored-by: Sebastian Silbermann <[email protected]>
1 parent 317e319 commit 87ffd2a

File tree

7 files changed

+559
-2
lines changed

7 files changed

+559
-2
lines changed

README.md

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ clear to read and to maintain.
6464
- [`toBeVisible`](#tobevisible)
6565
- [`toContainElement`](#tocontainelement)
6666
- [`toContainHTML`](#tocontainhtml)
67+
- [`toHaveAccessibleDescription`](#tohaveaccessibledescription)
68+
- [`toHaveAccessibleName`](#tohaveaccessiblename)
6769
- [`toHaveAttribute`](#tohaveattribute)
6870
- [`toHaveClass`](#tohaveclass)
6971
- [`toHaveFocus`](#tohavefocus)
@@ -155,8 +157,7 @@ toBeDisabled()
155157
```
156158

157159
This allows you to check whether an element is disabled from the user's
158-
perspective.
159-
According to the specification, the following elements can be
160+
perspective. According to the specification, the following elements can be
160161
[disabled](https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements):
161162
`button`, `input`, `select`, `textarea`, `optgroup`, `option`, `fieldset`.
162163

@@ -526,6 +527,94 @@ expect(getByTestId('parent')).toContainHTML('</span>')
526527
527528
<hr />
528529

530+
### `toHaveAccessibleDescription`
531+
532+
```typescript
533+
toHaveAccessibleDescription(expectedAccessibleDescription?: string | RegExp)
534+
```
535+
536+
This allows to assert that an element has the expected
537+
[accessible description](https://w3c.github.io/accname/).
538+
539+
You can pass the exact string of the expected accessible description, or you can
540+
make a partial match passing a regular expression, or by using
541+
[expect.stringContaining](https://jestjs.io/docs/en/expect.html#expectnotstringcontainingstring)/[expect.stringMatching](https://jestjs.io/docs/en/expect.html#expectstringmatchingstring-regexp).
542+
543+
#### Examples
544+
545+
```html
546+
<a
547+
data-testid="link"
548+
href="/"
549+
aria-label="Home page"
550+
title="A link to start over"
551+
>Start</a
552+
>
553+
<a data-testid="extra-link" href="/about" aria-label="About page">About</a>
554+
<img src="avatar.jpg" data-testid="avatar" alt="User profile pic" />
555+
<img
556+
src="logo.jpg"
557+
data-testid="logo"
558+
alt="Company logo"
559+
aria-describedby="t1"
560+
/>
561+
<span id="t1" role="presentation">The logo of Our Company</span>
562+
```
563+
564+
```js
565+
expect(getByTestId('link')).toHaveAccessibleDescription()
566+
expect(getByTestId('link')).toHaveAccessibleDescription('A link to start over')
567+
expect(getByTestId('link')).not.toHaveAccessibleDescription('Home page')
568+
expect(getByTestId('extra-link')).not.toHaveAccessibleDescription()
569+
expect(getByTestId('avatar')).not.toHaveAccessibleDescription()
570+
expect(getByTestId('logo')).not.toHaveAccessibleDescription('Company logo')
571+
expect(getByTestId('logo')).toHaveAccessibleDescription(
572+
'The logo of Our Company',
573+
)
574+
```
575+
576+
<hr />
577+
578+
### `toHaveAccessibleName`
579+
580+
```typescript
581+
toHaveAccessibleName(expectedAccessibleName?: string | RegExp)
582+
```
583+
584+
This allows to assert that an element is has the expected
585+
[accessible name](https://w3c.github.io/accname/). It is useful, for instance,
586+
to assert that form elements and buttons are properly labelled.
587+
588+
You can pass the exact string of the expected accessible name, or you can make a
589+
partial match passing a regular expression, or by using
590+
[expect.stringContaining](https://jestjs.io/docs/en/expect.html#expectnotstringcontainingstring)/[expect.stringMatching](https://jestjs.io/docs/en/expect.html#expectstringmatchingstring-regexp).
591+
592+
#### Examples
593+
594+
```html
595+
<img data-testid="img-alt" src="" alt="Test alt" />
596+
<img data-testid="img-empty-alt" src="" alt="" />
597+
<svg data-testid="svg-title"><title>Test title</title></svg>
598+
<button data-testid="button-img-alt"><img src="" alt="Test" /></button>
599+
<p><img data-testid="img-paragraph" src="" alt="" /> Test content</p>
600+
<button data-testid="svg-button"><svg><title>Test</title></svg></p>
601+
<div><svg data-testid="svg-without-title"></svg></div>
602+
<input data-testid="input-title" title="test" />
603+
```
604+
605+
```javascript
606+
expect(getByTestId('img-alt')).toHaveAccessibleName('Test alt')
607+
expect(getByTestId('img-empty-alt')).not.toHaveAccessibleName()
608+
expect(getByTestId('svg-title')).toHaveAccessibleName('Test title')
609+
expect(getByTestId('button-img-alt')).toHaveAccessibleName()
610+
expect(getByTestId('img-paragraph')).not.toHaveAccessibleName()
611+
expect(getByTestId('svg-button')).toHaveAccessibleName()
612+
expect(getByTestId('svg-without-title')).not.toHaveAccessibleName()
613+
expect(getByTestId('input-title')).toHaveAccessibleName()
614+
```
615+
616+
<hr />
617+
529618
### `toHaveAttribute`
530619

531620
```typescript

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"chalk": "^3.0.0",
3838
"css": "^3.0.0",
3939
"css.escape": "^1.5.1",
40+
"dom-accessibility-api": "^0.5.6",
4041
"lodash": "^4.17.15",
4142
"redent": "^3.0.0"
4243
},
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {render} from './helpers/test-utils'
2+
3+
describe('.toHaveAccessibleDescription', () => {
4+
it('works with the link title attribute', () => {
5+
const {queryByTestId} = render(`
6+
<div>
7+
<a data-testid="link" href="/" aria-label="Home page" title="A link to start over">Start</a>
8+
<a data-testid="extra-link" href="/about" aria-label="About page">About</a>
9+
</div>
10+
`)
11+
12+
const link = queryByTestId('link')
13+
expect(link).toHaveAccessibleDescription()
14+
expect(link).toHaveAccessibleDescription('A link to start over')
15+
expect(link).not.toHaveAccessibleDescription('Home page')
16+
expect(() => {
17+
expect(link).toHaveAccessibleDescription('Invalid description')
18+
}).toThrow(/expected element to have accessible description/i)
19+
expect(() => {
20+
expect(link).not.toHaveAccessibleDescription()
21+
}).toThrow(/expected element not to have accessible description/i)
22+
23+
const extraLink = queryByTestId('extra-link')
24+
expect(extraLink).not.toHaveAccessibleDescription()
25+
expect(() => {
26+
expect(extraLink).toHaveAccessibleDescription()
27+
}).toThrow(/expected element to have accessible description/i)
28+
})
29+
30+
it('works with aria-describedby attributes', () => {
31+
const {queryByTestId} = render(`
32+
<div>
33+
<img src="avatar.jpg" data-testid="avatar" alt="User profile pic">
34+
<img src="logo.jpg" data-testid="logo" alt="Company logo" aria-describedby="t1">
35+
<span id="t1" role="presentation">The logo of Our Company</span>
36+
</div>
37+
`)
38+
39+
const avatar = queryByTestId('avatar')
40+
expect(avatar).not.toHaveAccessibleDescription()
41+
expect(() => {
42+
expect(avatar).toHaveAccessibleDescription('User profile pic')
43+
}).toThrow(/expected element to have accessible description/i)
44+
45+
const logo = queryByTestId('logo')
46+
expect(logo).not.toHaveAccessibleDescription('Company logo')
47+
expect(logo).toHaveAccessibleDescription('The logo of Our Company')
48+
expect(logo).toHaveAccessibleDescription(/logo of our company/i)
49+
expect(logo).toHaveAccessibleDescription(
50+
expect.stringContaining('logo of Our Company'),
51+
)
52+
expect(() => {
53+
expect(logo).toHaveAccessibleDescription("Our company's logo")
54+
}).toThrow(/expected element to have accessible description/i)
55+
expect(() => {
56+
expect(logo).not.toHaveAccessibleDescription('The logo of Our Company')
57+
}).toThrow(/expected element not to have accessible description/i)
58+
})
59+
})

0 commit comments

Comments
 (0)