Skip to content

Commit 909e56d

Browse files
committed
fix(template-no-invalid-role): preserve author casing in invalid-role message (Copilot review)
Keep the original token alongside the lowercased one; validation stays case- insensitive (lowercases against VALID_ROLES) but the reported-back token uses the author's raw casing so the error surfaces their input verbatim rather than the normalized form. Also drop a 'line 229 of rule' hard-coded reference from the aria-role peer-parity fixture — line numbers rot on every refactor.
1 parent a3a3884 commit 909e56d

3 files changed

Lines changed: 15 additions & 7 deletions

File tree

lib/rules/template-no-invalid-role.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,19 @@ module.exports = {
162162

163163
// ARIA role attribute is a whitespace-separated list of tokens
164164
// (role-fallback pattern per ARIA 1.2 §5.4). Validate each token.
165-
const tokens = raw.split(/\s+/u).map((t) => t.toLowerCase());
165+
// Keep the original casing alongside the normalized (lowercase) form
166+
// so reported-back tokens preserve author intent — the validation
167+
// is case-insensitive, the ERROR MESSAGE isn't.
168+
const rawTokens = raw.split(/\s+/u);
169+
const tokens = rawTokens.map((t) => t.toLowerCase());
166170

167171
if (catchNonexistentRoles) {
168-
const invalidToken = tokens.find((token) => !VALID_ROLES.has(token));
169-
if (invalidToken) {
172+
const invalidIdx = tokens.findIndex((token) => !VALID_ROLES.has(token));
173+
if (invalidIdx !== -1) {
170174
context.report({
171175
node: roleAttr,
172176
messageId: 'invalid',
173-
data: { role: invalidToken },
177+
data: { role: rawTokens[invalidIdx] },
174178
});
175179
return;
176180
}

tests/audit/aria-role/peer-parity.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ ruleTester.run('audit:aria-role (gts)', rule, {
9595
// === DIVERGENCE — empty role string ===
9696
// jsx-a11y: INVALID — `<div role="" />` flagged.
9797
// vue-a11y: INVALID — same.
98-
// Our rule: early-return on empty/whitespace role (line 229 of rule). NO FLAG.
98+
// Our rule: early-return on empty/whitespace role. NO FLAG.
9999
// So this case reflects OUR (non-flagging) behavior with an explicit note.
100100
// (No invalid assertion possible here — we'd need to move this to valid,
101101
// or fix the rule to flag.)

tests/lib/rules/template-no-invalid-role.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,9 @@ ruleTester.run('template-no-invalid-role', rule, {
204204
{
205205
code: '<template><div role="COMMAND INTERFACE"></div></template>',
206206
output: null,
207-
errors: [{ message: "Invalid ARIA role 'command'. Must be a valid ARIA role." }],
207+
// Validation is case-insensitive, but the error message echoes the
208+
// author-provided token verbatim so authors see their own text.
209+
errors: [{ message: "Invalid ARIA role 'COMMAND'. Must be a valid ARIA role." }],
208210
},
209211
{
210212
code: '<template><div role="command interface"></div></template>',
@@ -363,7 +365,9 @@ hbsRuleTester.run('template-no-invalid-role', rule, {
363365
{
364366
code: '<div role="COMMAND INTERFACE"></div>',
365367
output: null,
366-
errors: [{ message: "Invalid ARIA role 'command'. Must be a valid ARIA role." }],
368+
// Validation is case-insensitive, but the error message echoes the
369+
// author-provided token verbatim so authors see their own text.
370+
errors: [{ message: "Invalid ARIA role 'COMMAND'. Must be a valid ARIA role." }],
367371
},
368372
// Newly added SEMANTIC_ELEMENTS: presentation/none on iframe, video, audio, embed
369373
{

0 commit comments

Comments
 (0)