Skip to content

Commit dc20a4b

Browse files
committed
fix(template-require-mandatory-role-attributes): skip abstract roles in fallback walk (Copilot review)
ARIA §5.3 marks certain roles as 'Abstract' — widget, input, command, section, landmark, etc. — as ontology categories that must not be used in content. Per §4.1 role-fallback semantics, UAs skip these in the fallback resolution. Our previous impl treated any roles.get() hit as recognised, so role='widget button' resolved to 'widget' and bailed without checking button's required attrs (silent false negative). Now filter roleDefinition.abstract alongside the existing undefined check; aligns with sibling rules that already apply this filter.
1 parent 3d69b55 commit dc20a4b

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

lib/rules/template-require-mandatory-role-attributes.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ function splitRoleTokens(value) {
3434
// For an ARIA role-fallback list like "combobox listbox", check required
3535
// attributes against the FIRST recognised role (the primary) per ARIA 1.2
3636
// role-fallback semantics — a user agent picks the first role it recognises.
37+
// Abstract roles (widget, input, command, section, … — ARIA §5.3) are
38+
// ontology categories, not valid authoring roles, so UAs skip them too.
3739
// Diverges from jsx-a11y, which validates every recognised token.
3840
function getMissingRequiredAttributes(roleTokens, foundAriaAttributes) {
3941
for (const role of roleTokens) {
4042
const roleDefinition = roles.get(role);
41-
if (!roleDefinition) {
43+
if (!roleDefinition || roleDefinition.abstract) {
4244
continue;
4345
}
4446
const requiredAttributes = Object.keys(roleDefinition.requiredProps);

tests/lib/rules/template-require-mandatory-role-attributes.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ ruleTester.run('template-require-mandatory-role-attributes', rule, {
3030
'<template><div role="COMBOBOX" aria-expanded="false" aria-controls="ctrl" /></template>',
3131
// Role fallback list — primary role's required attributes are satisfied.
3232
'<template><div role="combobox listbox" aria-expanded="false" aria-controls="ctrl" /></template>',
33+
// Abstract roles (ARIA §5.3) are skipped per §4.1 fallback semantics —
34+
// `widget` isn't an authoring role, so the UA walks past it to the next
35+
// recognised token. Here `button` has no required attrs → valid.
36+
'<template><div role="widget button" /></template>',
37+
// Abstract role followed by a concrete role that IS satisfied.
38+
'<template><div role="command slider" aria-valuenow="0" /></template>',
3339
],
3440

3541
invalid: [
@@ -101,6 +107,18 @@ ruleTester.run('template-require-mandatory-role-attributes', rule, {
101107
},
102108
],
103109
},
110+
// Abstract role (`widget`) followed by a concrete role that's missing
111+
// required attrs — UA skips the abstract, lands on `slider`, which
112+
// requires aria-valuenow.
113+
{
114+
code: '<template><div role="widget slider"></div></template>',
115+
output: null,
116+
errors: [
117+
{
118+
message: 'The attribute aria-valuenow is required by the role slider',
119+
},
120+
],
121+
},
104122
],
105123
});
106124

0 commit comments

Comments
 (0)