Skip to content

Commit 4b7996c

Browse files
eps1lonkentcdodds
andauthored
fix(ByRole): various implicit roles (#446)
* test: add select-combobox test * fix: Various implicit roles in ByRole * test: add note about aria-query fix * simplify some tests * test: document how to name elements Co-authored-by: Kent C. Dodds <[email protected]>
1 parent a3c5699 commit 4b7996c

File tree

6 files changed

+55
-33
lines changed

6 files changed

+55
-33
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"@babel/runtime": "^7.6.2",
4444
"@sheerun/mutationobserver-shim": "^0.3.2",
4545
"@types/testing-library__dom": "^6.0.0",
46-
"aria-query": "3.0.0",
46+
"aria-query": "^4.0.1",
4747
"dom-accessibility-api": "^0.3.0",
4848
"pretty-format": "^24.9.0",
4949
"wait-for-expect": "^3.0.0"

src/__tests__/__snapshots__/role-helpers.js.snap

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
exports[`logRoles calls console.log with output from prettyRoles 1`] = `
44
"region:
55
6-
Name "":
6+
Name "a region":
77
<section
8-
data-testid="a-section"
8+
aria-label="a region"
9+
data-testid="named-section"
910
/>
1011
1112
--------------------------------------------------
@@ -158,9 +159,10 @@ Name "Cell 3":
158159
--------------------------------------------------
159160
form:
160161
161-
Name "":
162+
Name "a form":
162163
<form
163-
data-testid="a-form"
164+
aria-label="a form"
165+
data-testid="named-form"
164166
/>
165167
166168
--------------------------------------------------

src/__tests__/element-queries.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ test('queryAllByRole returns semantic html elements', () => {
414414
<table role="grid"></table>
415415
<div role="meter progressbar" />
416416
<button>Button</button>
417+
<select><option value="1">one</option></select>
418+
<select size="2">
419+
<option value="1">one</option>
420+
<option value="2">two</option>
421+
</select>
417422
</form>
418423
`)
419424

@@ -422,21 +427,27 @@ test('queryAllByRole returns semantic html elements', () => {
422427
expect(queryAllByRole(/columnheader/i)).toHaveLength(1)
423428
expect(queryAllByRole(/rowheader/i)).toHaveLength(1)
424429
expect(queryAllByRole(/grid/i)).toHaveLength(1)
425-
expect(queryAllByRole(/form/i)).toHaveLength(1)
430+
expect(queryAllByRole(/form/i)).toHaveLength(0)
426431
expect(queryAllByRole(/button/i)).toHaveLength(1)
427432
expect(queryAllByRole(/heading/i)).toHaveLength(6)
428433
expect(queryAllByRole('list')).toHaveLength(2)
429434
expect(queryAllByRole(/listitem/i)).toHaveLength(3)
430-
expect(queryAllByRole(/textbox/i)).toHaveLength(2)
435+
// TODO: with https://github.com/A11yance/aria-query/pull/42
436+
// the actual value will match `toHaveLength(2)`
437+
expect(queryAllByRole(/textbox/i)).toHaveLength(1)
431438
expect(queryAllByRole(/checkbox/i)).toHaveLength(1)
432439
expect(queryAllByRole(/radio/i)).toHaveLength(1)
433440
expect(queryAllByRole('row')).toHaveLength(3)
434441
expect(queryAllByRole(/rowgroup/i)).toHaveLength(2)
435-
expect(queryAllByRole(/(table)|(textbox)/i)).toHaveLength(3)
442+
// TODO: with https://github.com/A11yance/aria-query/pull/42
443+
// the actual value will match `toHaveLength(3)`
444+
expect(queryAllByRole(/(table)|(textbox)/i)).toHaveLength(2)
436445
expect(queryAllByRole(/img/i)).toHaveLength(1)
437446
expect(queryAllByRole('meter')).toHaveLength(1)
438447
expect(queryAllByRole('progressbar')).toHaveLength(0)
439448
expect(queryAllByRole('progressbar', {queryFallbacks: true})).toHaveLength(1)
449+
expect(queryAllByRole('combobox')).toHaveLength(1)
450+
expect(queryAllByRole('listbox')).toHaveLength(1)
440451
})
441452

442453
test('getAll* matchers return an array', () => {

src/__tests__/role-helpers.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ afterEach(() => {
1616

1717
function setup() {
1818
const {getByTestId} = render(`
19-
<section data-testid='a-section'>
19+
<section aria-label="a region" data-testid='named-section'>
2020
<a href="http://whatever.com" data-testid="a-link">link</a>
2121
<a>invalid link</a>
2222
@@ -50,7 +50,7 @@ function setup() {
5050
</tbody>
5151
</table>
5252
53-
<form data-testid='a-form'>
53+
<form aria-label="a form" data-testid='named-form'>
5454
<input type='radio' data-testid='a-radio-1' />
5555
<input type='radio' data-testid='a-radio-2' />
5656
<input type='text' data-testid='a-input-1' />
@@ -62,12 +62,16 @@ function setup() {
6262
<li data-testid='b-list-item-1'>Item 1</li>
6363
<li data-testid='b-list-item-2'>Item 2</li>
6464
</ul>
65+
66+
<form data-testid="a-form" />
67+
<section data-testid="a-section" />
6568
</article>
6669
</section>
6770
`)
6871

6972
return {
70-
section: getByTestId('a-section'),
73+
unnamedSection: getByTestId('a-section'),
74+
namedSection: getByTestId('named-section'),
7175
anchor: getByTestId('a-link'),
7276
h1: getByTestId('a-h1'),
7377
h2: getByTestId('a-h2'),
@@ -88,7 +92,8 @@ function setup() {
8892
td1: getByTestId('a-cell-1'),
8993
td2: getByTestId('a-cell-2'),
9094
td3: getByTestId('a-cell-3'),
91-
form: getByTestId('a-form'),
95+
unnamedForm: getByTestId('a-form'),
96+
namedForm: getByTestId('named-form'),
9297
radio: getByTestId('a-radio-1'),
9398
radio2: getByTestId('a-radio-2'),
9499
input: getByTestId('a-input-1'),
@@ -99,7 +104,6 @@ function setup() {
99104

100105
test('getRoles returns expected roles for various dom nodes', () => {
101106
const {
102-
section,
103107
anchor,
104108
h1,
105109
h2,
@@ -120,17 +124,17 @@ test('getRoles returns expected roles for various dom nodes', () => {
120124
td1,
121125
td2,
122126
td3,
123-
form,
124127
radio,
125128
radio2,
126129
input,
127130
input2,
128131
textarea,
132+
namedSection,
133+
namedForm,
129134
} = setup()
130135

131-
expect(getRoles(section)).toEqual({
136+
expect(getRoles(namedSection)).toEqual({
132137
link: [anchor],
133-
region: [section],
134138
heading: [h1, h2, h3],
135139
navigation: [nav],
136140
radio: [radio, radio2],
@@ -140,27 +144,28 @@ test('getRoles returns expected roles for various dom nodes', () => {
140144
table: [table],
141145
row: [tr],
142146
cell: [td1, td2, td3],
143-
form: [form],
144147
textbox: [input, input2, textarea],
145148
rowgroup: [tbody],
146149
command: [menuItem, menuItem2],
147150
menuitem: [menuItem, menuItem2],
151+
form: [namedForm],
152+
region: [namedSection],
148153
})
149154
})
150155

151156
test('logRoles calls console.log with output from prettyRoles', () => {
152-
const {section} = setup()
153-
logRoles(section)
157+
const {namedSection} = setup()
158+
logRoles(namedSection)
154159
expect(console.log).toHaveBeenCalledTimes(1)
155160
expect(console.log.mock.calls[0][0]).toMatchSnapshot()
156161
})
157162

158163
test('getImplicitAriaRoles returns expected roles for various dom nodes', () => {
159-
const {section, h1, form, radio, input} = setup()
164+
const {namedSection, h1, unnamedForm, radio, input} = setup()
160165

161-
expect(getImplicitAriaRoles(section)).toEqual(['region'])
166+
expect(getImplicitAriaRoles(namedSection)).toEqual(['region'])
162167
expect(getImplicitAriaRoles(h1)).toEqual(['heading'])
163-
expect(getImplicitAriaRoles(form)).toEqual(['form'])
168+
expect(getImplicitAriaRoles(unnamedForm)).toEqual([])
164169
expect(getImplicitAriaRoles(radio)).toEqual(['radio'])
165170
expect(getImplicitAriaRoles(input)).toEqual(['textbox'])
166171
})

src/__tests__/role.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,7 @@ test('can be filtered by accessible name', () => {
214214
expect(deliveryForm).not.toBeNull()
215215

216216
expect(
217-
// TODO: upstream bug in `aria-query`; should be `button` role
218-
getQueriesForElement(deliveryForm).getByRole('textbox', {name: 'Submit'}),
217+
getQueriesForElement(deliveryForm).getByRole('button', {name: 'Submit'}),
219218
).not.toBeNull()
220219

221220
const invoiceForm = getByRole('form', {name: 'Delivery Adress'})
@@ -229,11 +228,9 @@ test('can be filtered by accessible name', () => {
229228
test('accessible name comparison is case sensitive', () => {
230229
const {getByRole} = render(`<h1>Sign <em>up</em></h1>`)
231230

232-
// actual: "Sign up",
233-
// queried: "Sign Up"
234-
expect(() => getByRole('heading', {name: 'Sign Up'}))
231+
expect(() => getByRole('heading', {name: 'something that does not match'}))
235232
.toThrowErrorMatchingInlineSnapshot(`
236-
"Unable to find an accessible element with the role "heading" and name "Sign Up"
233+
"Unable to find an accessible element with the role "heading" and name "something that does not match"
237234
238235
Here are the accessible roles:
239236
@@ -277,9 +274,9 @@ test('accessible name filter implements TextMatch', () => {
277274
test('TextMatch serialization in error message', () => {
278275
const {getByRole} = render(`<h1>Sign <em>up</em></h1>`)
279276

280-
expect(() => getByRole('heading', {name: /Login/}))
277+
expect(() => getByRole('heading', {name: /something that does not match/}))
281278
.toThrowErrorMatchingInlineSnapshot(`
282-
"Unable to find an accessible element with the role "heading" and name \`/Login/\`
279+
"Unable to find an accessible element with the role "heading" and name \`/something that does not match/\`
283280
284281
Here are the accessible roles:
285282

src/role-helpers.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,16 @@ function getImplicitAriaRoles(currentNode) {
7676
function buildElementRoleList(elementRolesMap) {
7777
function makeElementSelector({name, attributes = []}) {
7878
return `${name}${attributes
79-
.map(({name: attributeName, value}) =>
80-
value ? `[${attributeName}=${value}]` : `[${attributeName}]`,
81-
)
79+
.map(({name: attributeName, value, constraints = []}) => {
80+
const shouldNotExist = constraints.indexOf('undefined') !== -1
81+
if (shouldNotExist) {
82+
return `:not([${attributeName}])`
83+
} else if (value) {
84+
return `[${attributeName}="${value}"]`
85+
} else {
86+
return `[${attributeName}]`
87+
}
88+
})
8289
.join('')}`
8390
}
8491

0 commit comments

Comments
 (0)