Skip to content

Commit

Permalink
[Fix] handle interactive/noninteractive changes from aria-query
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Sep 20, 2024
1 parent e517937 commit 4925ba8
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 60 deletions.
22 changes: 14 additions & 8 deletions __mocks__/genInteractives.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ const interactiveElementsMap = {
'input[type="time"]': [{ prop: 'type', value: 'time' }],
'input[type="url"]': [{ prop: 'type', value: 'url' }],
'input[type="week"]': [{ prop: 'type', value: 'week' }],
link: [{ prop: 'href', value: '#' }],
menuitem: [],
option: [],
select: [],
summary: [],
// Whereas ARIA makes a distinction between cell and gridcell, the AXObject
// treats them both as CellRole and since gridcell is interactive, we consider
// cell interactive as well.
// td: [],
td: [],
th: [],
tr: [],
textarea: [],
Expand All @@ -61,34 +61,38 @@ const interactiveElementsMap = {

const nonInteractiveElementsMap: {[string]: Array<{[string]: string}>} = {
abbr: [],
aside: [],
address: [],
article: [],
aside: [],
blockquote: [],
body: [],
br: [],
caption: [],
code: [],
dd: [],
del: [],
details: [],
dfn: [],
dialog: [],
dir: [],
dl: [],
dt: [],
em: [],
fieldset: [],
figcaption: [],
figure: [],
footer: [],
form: [],
frame: [],
h1: [],
h2: [],
h3: [],
h4: [],
h5: [],
h6: [],
hr: [],
html: [],
iframe: [],
img: [],
ins: [],
label: [],
legend: [],
li: [],
Expand All @@ -107,20 +111,22 @@ const nonInteractiveElementsMap: {[string]: Array<{[string]: string}>} = {
ruby: [],
'section[aria-label]': [{ prop: 'aria-label' }],
'section[aria-labelledby]': [{ prop: 'aria-labelledby' }],
strong: [],
sub: [],
sup: [],
table: [],
tbody: [],
td: [],
tfoot: [],
thead: [],
time: [],
ul: [],
};

const indeterminantInteractiveElementsMap: { [key: string]: Array<any> } = fromEntries(domElements.map((name: string) => [name, []]));
const indeterminantInteractiveElementsMap: { [key: string]: Array<any> } = fromEntries(domElements.map((name) => [name, []]));

Object.keys(interactiveElementsMap)
.concat(Object.keys(nonInteractiveElementsMap))
.forEach((name: string) => delete indeterminantInteractiveElementsMap[name]);
.forEach((name) => delete indeterminantInteractiveElementsMap[name]);

const abstractRoles = roleNames.filter((role) => roles.get(role).abstract);

Expand Down
2 changes: 1 addition & 1 deletion __tests__/src/rules/control-has-associated-label-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ const alwaysValid = [
{ code: '<section />' },
{ code: '<table />' },
{ code: '<tbody />' },
{ code: '<td />' },
{ code: '<tfoot />' },
{ code: '<thead />' },
{ code: '<time />' },
Expand Down Expand Up @@ -263,6 +262,7 @@ const neverValid = [
{ code: '<menuitem />', errors: [expectedError] },
{ code: '<option />', errors: [expectedError] },
{ code: '<th />', errors: [expectedError] },
{ code: '<td />', errors: [expectedError] },
// Interactive Roles
{ code: '<div role="button" />', errors: [expectedError] },
{ code: '<div role="checkbox" />', errors: [expectedError] },
Expand Down
24 changes: 12 additions & 12 deletions __tests__/src/rules/no-noninteractive-element-interactions-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const alwaysValid = [
{ code: '<a onClick={() => void 0} href="http://x.y.z" />' },
{ code: '<a onClick={() => void 0} href="http://x.y.z" tabIndex="0" />' },
{ code: '<area onClick={() => {}} />;' },
{ code: '<body onClick={() => {}} />;' },
{ code: '<button onClick={() => void 0} className="foo" />' },
{ code: '<menuitem onClick={() => {}} />;' },
{ code: '<option onClick={() => void 0} className="foo" />' },
Expand All @@ -77,7 +78,6 @@ const alwaysValid = [
{ code: '<tr onClick={() => {}} />;' },
/* HTML elements with neither an interactive or non-interactive valence (static) */
{ code: '<acronym onClick={() => {}} />;' },
{ code: '<address onClick={() => {}} />;' },
{ code: '<applet onClick={() => {}} />;' },
{ code: '<audio onClick={() => {}} />;' },
{ code: '<b onClick={() => {}} />;' },
Expand All @@ -90,13 +90,11 @@ const alwaysValid = [
{ code: '<canvas onClick={() => {}} />;' },
{ code: '<center onClick={() => {}} />;' },
{ code: '<cite onClick={() => {}} />;' },
{ code: '<code onClick={() => {}} />;' },
{ code: '<col onClick={() => {}} />;' },
{ code: '<colgroup onClick={() => {}} />;' },
{ code: '<content onClick={() => {}} />;' },
{ code: '<data onClick={() => {}} />;' },
{ code: '<datalist onClick={() => {}} />;' },
{ code: '<del onClick={() => {}} />;' },
{ code: '<div />;' },
{ code: '<div className="foo" />;' },
{ code: '<div className="foo" {...props} />;' },
Expand All @@ -107,7 +105,6 @@ const alwaysValid = [
{ code: '<div onClick={() => void 0} {...props} />;' },
{ code: '<div onClick={null} />;' },
{ code: '<div onKeyUp={() => void 0} aria-hidden={false} />;' },
{ code: '<em onClick={() => {}} />;' },
{ code: '<embed onClick={() => {}} />;' },
{ code: '<font onClick={() => {}} />;' },
{ code: '<font onSubmit={() => {}} />;' },
Expand All @@ -121,11 +118,11 @@ const alwaysValid = [
</form>
`,
},
{ code: '<frame onClick={() => {}} />;' },
{ code: '<frameset onClick={() => {}} />;' },
{ code: '<head onClick={() => {}} />;' },
{ code: '<header onClick={() => {}} />;' },
{ code: '<hgroup onClick={() => {}} />;' },
{ code: '<html onClick={() => {}} />;' },
{ code: '<i onClick={() => {}} />;' },
{ code: '<iframe onLoad={() => {}} />;' },
{
Expand Down Expand Up @@ -153,7 +150,6 @@ const alwaysValid = [
/>
`,
},
{ code: '<ins onClick={() => {}} />;' },
{ code: '<kbd onClick={() => {}} />;' },
{ code: '<keygen onClick={() => {}} />;' },
{ code: '<link onClick={() => {}} />;' },
Expand All @@ -178,14 +174,12 @@ const alwaysValid = [
{ code: '<spacer onClick={() => {}} />;' },
{ code: '<span onClick={() => {}} />;' },
{ code: '<strike onClick={() => {}} />;' },
{ code: '<strong onClick={() => {}} />;' },
{ code: '<style onClick={() => {}} />;' },
{ code: '<sub onClick={() => {}} />;' },
{ code: '<summary onClick={() => {}} />;' },
{ code: '<sup onClick={() => {}} />;' },
{ code: '<th onClick={() => {}} />;' },
{ code: '<title onClick={() => {}} />;' },
{ code: '<track onClick={() => {}} />;' },
{ code: '<td onClick={() => {}} />;' },
{ code: '<tt onClick={() => {}} />;' },
{ code: '<u onClick={() => {}} />;' },
{ code: '<var onClick={() => {}} />;' },
Expand Down Expand Up @@ -286,33 +280,37 @@ const alwaysValid = [
const neverValid = [
/* HTML elements with an inherent, non-interactive role */
{ code: '<main onClick={() => void 0} />;', errors: [expectedError] },
{ code: '<address onClick={() => {}} />;', errors: [expectedError] },
{ code: '<article onClick={() => {}} />;', errors: [expectedError] },
{ code: '<aside onClick={() => {}} />;', errors: [expectedError] },
{ code: '<blockquote onClick={() => {}} />;', errors: [expectedError] },
{ code: '<body onClick={() => {}} />;', errors: [expectedError] },
{ code: '<br onClick={() => {}} />;', errors: [expectedError] },
{ code: '<caption onClick={() => {}} />;', errors: [expectedError] },
{ code: '<code onClick={() => {}} />;', errors: [expectedError] },
{ code: '<dd onClick={() => {}} />;', errors: [expectedError] },
{ code: '<del onClick={() => {}} />;', errors: [expectedError] },
{ code: '<details onClick={() => {}} />;', errors: [expectedError] },
{ code: '<dfn onClick={() => {}} />;', errors: [expectedError] },
{ code: '<dl onClick={() => {}} />;', errors: [expectedError] },
{ code: '<dir onClick={() => {}} />;', errors: [expectedError] },
{ code: '<dt onClick={() => {}} />;', errors: [expectedError] },
{ code: '<em onClick={() => {}} />;', errors: [expectedError] },
{ code: '<fieldset onClick={() => {}} />;', errors: [expectedError] },
{ code: '<figcaption onClick={() => {}} />;', errors: [expectedError] },
{ code: '<figure onClick={() => {}} />;', errors: [expectedError] },
{ code: '<footer onClick={() => {}} />;', errors: [expectedError] },
{ code: '<form onClick={() => {}} />;', errors: [expectedError] },
{ code: '<frame onClick={() => {}} />;', errors: [expectedError] },
{ code: '<h1 onClick={() => {}} />;', errors: [expectedError] },
{ code: '<h2 onClick={() => {}} />;', errors: [expectedError] },
{ code: '<h3 onClick={() => {}} />;', errors: [expectedError] },
{ code: '<h4 onClick={() => {}} />;', errors: [expectedError] },
{ code: '<h5 onClick={() => {}} />;', errors: [expectedError] },
{ code: '<h6 onClick={() => {}} />;', errors: [expectedError] },
{ code: '<hr onClick={() => {}} />;', errors: [expectedError] },
{ code: '<html onClick={() => {}} />;', errors: [expectedError] },
{ code: '<iframe onClick={() => {}} />;', errors: [expectedError] },
{ code: '<img onClick={() => {}} />;', errors: [expectedError] },
{ code: '<ins onClick={() => {}} />;', errors: [expectedError] },
{ code: '<label onClick={() => {}} />;', errors: [expectedError] },
{ code: '<legend onClick={() => {}} />;', errors: [expectedError] },
{ code: '<li onClick={() => {}} />;', errors: [expectedError] },
Expand All @@ -330,9 +328,11 @@ const neverValid = [
{ code: '<ruby onClick={() => {}} />;', errors: [expectedError] },
{ code: '<section onClick={() => {}} aria-label="Aardvark" />;', errors: [expectedError] },
{ code: '<section onClick={() => {}} aria-labelledby="js_1" />;', errors: [expectedError] },
{ code: '<strong onClick={() => {}} />;', errors: [expectedError] },
{ code: '<sub onClick={() => {}} />;', errors: [expectedError] },
{ code: '<sup onClick={() => {}} />;', errors: [expectedError] },
{ code: '<table onClick={() => {}} />;', errors: [expectedError] },
{ code: '<tbody onClick={() => {}} />;', errors: [expectedError] },
{ code: '<td onClick={() => {}} />;', errors: [expectedError] },
{ code: '<tfoot onClick={() => {}} />;', errors: [expectedError] },
{ code: '<thead onClick={() => {}} />;', errors: [expectedError] },
{ code: '<time onClick={() => {}} />;', errors: [expectedError] },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ const alwaysValid = [
{ code: '<area role="button" />;' },
{ code: '<area role="menuitem" />;' },
{ code: '<button className="foo" role="button" />' },
{ code: '<body role="button" />;' },
{ code: '<frame role="button" />;' },
{ code: '<td role="button" />;' },
{ code: '<frame role="menuitem" />;' },
{ code: '<td role="menuitem" />;' },
/* All flavors of input */
{ code: '<input role="button" />' },
{ code: '<input type="button" role="button" />' },
Expand Down Expand Up @@ -154,7 +159,6 @@ const alwaysValid = [
{ code: '<tr role="listitem" />;' },
/* HTML elements with neither an interactive or non-interactive valence (static) */
{ code: '<acronym role="button" />;' },
{ code: '<address role="button" />;' },
{ code: '<applet role="button" />;' },
{ code: '<audio role="button" />;' },
{ code: '<b role="button" />;' },
Expand All @@ -166,13 +170,11 @@ const alwaysValid = [
{ code: '<canvas role="button" />;' },
{ code: '<center role="button" />;' },
{ code: '<cite role="button" />;' },
{ code: '<code role="button" />;' },
{ code: '<col role="button" />;' },
{ code: '<colgroup role="button" />;' },
{ code: '<content role="button" />;' },
{ code: '<data role="button" />;' },
{ code: '<datalist role="button" />;' },
{ code: '<del role="button" />;' },
{ code: '<div role="button" />;' },
{ code: '<div className="foo" role="button" />;' },
{ code: '<div className="foo" {...props} role="button" />;' },
Expand All @@ -182,16 +184,13 @@ const alwaysValid = [
{ code: '<div role={undefined} role="button" />;' },
{ code: '<div {...props} role="button" />;' },
{ code: '<div onKeyUp={() => void 0} aria-hidden={false} role="button" />;' },
{ code: '<em role="button" />;' },
{ code: '<embed role="button" />;' },
{ code: '<font role="button" />;' },
{ code: '<frameset role="button" />;' },
{ code: '<head role="button" />;' },
{ code: '<header role="button" />;' },
{ code: '<hgroup role="button" />;' },
{ code: '<html role="button" />;' },
{ code: '<i role="button" />;' },
{ code: '<ins role="button" />;' },
{ code: '<kbd role="button" />;' },
{ code: '<keygen role="button" />;' },
{ code: '<link role="button" />;' },
Expand All @@ -214,11 +213,8 @@ const alwaysValid = [
{ code: '<spacer role="button" />;' },
{ code: '<span role="button" />;' },
{ code: '<strike role="button" />;' },
{ code: '<strong role="button" />;' },
{ code: '<style role="button" />;' },
{ code: '<sub role="button" />;' },
{ code: '<summary role="button" />;' },
{ code: '<sup role="button" />;' },
{ code: '<th role="button" />;' },
{ code: '<title role="button" />;' },
{ code: '<track role="button" />;' },
Expand Down Expand Up @@ -358,37 +354,41 @@ const alwaysValid = [
const neverValid = [
/* HTML elements with an inherent non-interactive role, assigned an
* interactive role. */
{ code: '<main role="button" />;', errors: [expectedError] },
{ code: '<address role="button" />;', errors: [expectedError] },
{ code: '<article role="button" />;', errors: [expectedError] },
{ code: '<aside role="button" />;', errors: [expectedError] },
{ code: '<blockquote role="button" />;', errors: [expectedError] },
{ code: '<body role="button" />;', errors: [expectedError] },
{ code: '<br role="button" />;', errors: [expectedError] },
{ code: '<caption role="button" />;', errors: [expectedError] },
{ code: '<code role="button" />;', errors: [expectedError] },
{ code: '<dd role="button" />;', errors: [expectedError] },
{ code: '<del role="button" />;', errors: [expectedError] },
{ code: '<details role="button" />;', errors: [expectedError] },
{ code: '<dfn role="button" />;', errors: [expectedError] },
{ code: '<dir role="button" />;', errors: [expectedError] },
{ code: '<dl role="button" />;', errors: [expectedError] },
{ code: '<dfn role="button" />;', errors: [expectedError] },
{ code: '<dt role="button" />;', errors: [expectedError] },
{ code: '<em role="button" />;', errors: [expectedError] },
{ code: '<fieldset role="button" />;', errors: [expectedError] },
{ code: '<figcaption role="button" />;', errors: [expectedError] },
{ code: '<figure role="button" />;', errors: [expectedError] },
{ code: '<footer role="button" />;', errors: [expectedError] },
{ code: '<form role="button" />;', errors: [expectedError] },
{ code: '<frame role="button" />;', errors: [expectedError] },
{ code: '<h1 role="button" />;', errors: [expectedError] },
{ code: '<h2 role="button" />;', errors: [expectedError] },
{ code: '<h3 role="button" />;', errors: [expectedError] },
{ code: '<h4 role="button" />;', errors: [expectedError] },
{ code: '<h5 role="button" />;', errors: [expectedError] },
{ code: '<h6 role="button" />;', errors: [expectedError] },
{ code: '<hr role="button" />;', errors: [expectedError] },
{ code: '<html role="button" />;', errors: [expectedError] },
{ code: '<iframe role="button" />;', errors: [expectedError] },
{ code: '<img role="button" />;', errors: [expectedError] },
{ code: '<ins role="button" />;', errors: [expectedError] },
{ code: '<label role="button" />;', errors: [expectedError] },
{ code: '<legend role="button" />;', errors: [expectedError] },
{ code: '<li role="button" />;', errors: [expectedError] },
{ code: '<main role="button" />;', errors: [expectedError] },
{ code: '<mark role="button" />;', errors: [expectedError] },
{ code: '<marquee role="button" />;', errors: [expectedError] },
{ code: '<menu role="button" />;', errors: [expectedError] },
Expand All @@ -400,9 +400,11 @@ const neverValid = [
{ code: '<pre role="button" />;', errors: [expectedError] },
{ code: '<progress role="button" />;', errors: [expectedError] },
{ code: '<ruby role="button" />;', errors: [expectedError] },
{ code: '<strong role="button" />;', errors: [expectedError] },
{ code: '<sub role="button" />;', errors: [expectedError] },
{ code: '<sup role="button" />;', errors: [expectedError] },
{ code: '<table role="button" />;', errors: [expectedError] },
{ code: '<tbody role="button" />;', errors: [expectedError] },
{ code: '<td role="button" />;', errors: [expectedError] },
{ code: '<tfoot role="button" />;', errors: [expectedError] },
{ code: '<thead role="button" />;', errors: [expectedError] },
{ code: '<time role="button" />;', errors: [expectedError] },
Expand All @@ -417,7 +419,6 @@ const neverValid = [
{ code: '<fieldset role="menuitem" />;', errors: [expectedError] },
{ code: '<figure role="menuitem" />;', errors: [expectedError] },
{ code: '<form role="menuitem" />;', errors: [expectedError] },
{ code: '<frame role="menuitem" />;', errors: [expectedError] },
{ code: '<h1 role="menuitem" />;', errors: [expectedError] },
{ code: '<h2 role="menuitem" />;', errors: [expectedError] },
{ code: '<h3 role="menuitem" />;', errors: [expectedError] },
Expand All @@ -432,7 +433,6 @@ const neverValid = [
{ code: '<section role="button" aria-label="Aardvark" />;', errors: [expectedError] },
{ code: '<table role="menuitem" />;', errors: [expectedError] },
{ code: '<tbody role="menuitem" />;', errors: [expectedError] },
{ code: '<td role="menuitem" />;', errors: [expectedError] },
{ code: '<tfoot role="menuitem" />;', errors: [expectedError] },
{ code: '<thead role="menuitem" />;', errors: [expectedError] },
/* Custom components */
Expand Down
Loading

0 comments on commit 4925ba8

Please sign in to comment.