Skip to content

Commit

Permalink
Implement aria-tooltip-name rule
Browse files Browse the repository at this point in the history
Co-authored-by: Michiel Pauw <[email protected]>
Co-authored-by: onkar75 <[email protected]>
  • Loading branch information
3 people committed Jun 19, 2024
1 parent 4a6cbaf commit ff6c1ce
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
|| aria-roledescription | https://dequeuniversity.com/rules/axe/4.4/aria-roledescription?application=RuleDescription | Ensure aria-roledescription is only used on elements with an implicit or explicit role | Serious | cat.aria, wcag2a, wcag412 | failure, needs&nbsp;review | |
|| aria-roles | https://dequeuniversity.com/rules/axe/4.4/aria-roles?application=RuleDescription | Ensures all elements with a role attribute use a valid value | Minor, Serious, Critical | cat.aria, wcag2a, wcag412 | failure | [674b10](https://act-rules.github.io/rules/674b10) |
|| aria-toggle-field-name | https://dequeuniversity.com/rules/axe/4.4/aria-toggle-field-name?application=RuleDescription | Ensures every ARIA toggle field has an accessible name | Moderate, Serious | cat.aria, wcag2a, wcag412, ACT | failure, needs&nbsp;review | [e086e5](https://act-rules.github.io/rules/e086e5) |
| | aria-tooltip-name | https://dequeuniversity.com/rules/axe/4.4/aria-tooltip-name?application=RuleDescription | Ensures every ARIA tooltip node has an accessible name | Serious | cat.aria, wcag2a, wcag412 | failure, needs&nbsp;review | |
| | aria-tooltip-name | https://dequeuniversity.com/rules/axe/4.4/aria-tooltip-name?application=RuleDescription | Ensures every ARIA tooltip node has an accessible name | Serious | cat.aria, wcag2a, wcag412 | failure, needs&nbsp;review | |
|| aria-valid-attr-value | https://dequeuniversity.com/rules/axe/4.4/aria-valid-attr-value?application=RuleDescription | Ensures all ARIA attributes have valid values | Serious, Critical | cat.aria, wcag2a, wcag412 | failure, needs&nbsp;review | [6a7281](https://act-rules.github.io/rules/6a7281) |
|| aria-valid-attr | https://dequeuniversity.com/rules/axe/4.4/aria-valid-attr?application=RuleDescription | Ensures attributes that begin with aria- are valid ARIA attributes | Critical | cat.aria, wcag2a, wcag412 | failure | [5f99a7](https://act-rules.github.io/rules/5f99a7) |
|| audio-caption | https://dequeuniversity.com/rules/axe/4.4/audio-caption?application=RuleDescription | Ensures &lt;audio&gt; elements have captions | Critical | cat.time-and-media, wcag2a, wcag121, section508, section508.22.a | needs&nbsp;review | [2eb176](https://act-rules.github.io/rules/2eb176), [afb423](https://act-rules.github.io/rules/afb423) |
Expand Down
48 changes: 48 additions & 0 deletions src/rules/aria-tooltip-name.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { AccessibilityError } from "../scanner";
import { labelledByIsValid, querySelectorAll } from "../utils";

// Metadata
const id = "aria-tooltip-name";
const text = "ARIA tooltip must have an accessible name";
const url = `https://dequeuniversity.com/rules/axe/4.4/${id}?application=RuleDescription`;

/**
* Make sure that a elements text is "visible" to a screenreader user.
*
* - Inner text that is discernible to screen reader users.
* - Non-empty aria-label attribute.
* - aria-labelledby pointing to element with text which is discernible to screen reader users.
*/
function hasAccessibleText(el: Element): boolean {
if (el.hasAttribute("aria-label")) {
return el.getAttribute("aria-label")!.trim() !== "";
}

if (!labelledByIsValid(el)) return false;

if (el.getAttribute("title")) {
return el.getAttribute("title")!.trim() !== "";
}

if (el.textContent) {
return el.textContent.trim() !== "";
}

return true;
}

export function ariaTooltipName(el: Element): AccessibilityError[] {
const errors = [];
const tooltips = querySelectorAll("[role=tooltip]", el);
if (el.matches("[role=tooltip]")) tooltips.push(el);
for (const tooltip of tooltips) {
if (!hasAccessibleText(tooltip)) {
errors.push({
element: tooltip,
url,
text,
});
}
}
return errors;
}
58 changes: 58 additions & 0 deletions tests/aria-tooltip-name.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { fixture, html, expect } from "@open-wc/testing";
import { Scanner } from "../src/scanner";
import { ariaTooltipName } from "../src/rules/aria-tooltip-name";

const scanner = new Scanner([ariaTooltipName]);

const passes = [
`<div role="tooltip" id="al" aria-label="Name"></div>`,
`<div>
<div role="tooltip" id="alb" aria-labelledby="labeldiv"></div>
<div id="labeldiv">Hello world!</div>
</div>`,
`<div role="tooltip" id="combo" aria-label="Aria Name">Name</div>`,
`<div role="tooltip" id="title" title="Title"></div>`,
];

const violations = [
`<div role="tooltip" id="empty"></div>`,
`<div role="tooltip" id="alempty" aria-label=""></div>`,
`<div
role="tooltip"
id="albmissing"
aria-labelledby="nonexistent"
></div>`,
`<div>
<div role="tooltip" id="albempty" aria-labelledby="emptydiv"></div>
<div id="emptydiv"></div>
</div>`,
];

describe("aria-tooltip-name", async function () {
for (const markup of passes) {
const el = await fixture(html`${markup}`);
it(el.outerHTML, async () => {
const results = (await scanner.scan(el)).map(({ text, url }) => {
return { text, url };
});

expect(results).to.be.empty;
});
}

for await (const markup of violations) {
const el = await fixture(html`${markup}`);
it(el.outerHTML, async () => {
const results = (await scanner.scan(el)).map(({ text, url }) => {
return { text, url };
});

expect(results).to.eql([
{
text: "ARIA tooltip must have an accessible name",
url: "https://dequeuniversity.com/rules/axe/4.4/aria-tooltip-name?application=RuleDescription",
},
]);
});
}
});

0 comments on commit ff6c1ce

Please sign in to comment.