Skip to content

Commit dfd0518

Browse files
committed
AX: Slot elements referenced with aria-labelledby not matching rendered output
https://bugs.webkit.org/show_bug.cgi?id=260772 rdar://114500560 Reviewed by Joshua Hoffman. When a slot element is referenced by aria-labelledby, we should use its assigned nodes for the accessible name, not the slot's fallback content (children). Additionally, hidden assigned nodes (display:none) should be excluded from the label calculation. The fix: 1. Moves slot handling in accessibleNameForNode() to occur before textUnderElement(), which would otherwise return fallback content. 2. Adds a check to skip hidden assigned nodes. Test: accessibility/slot-aria-labelledby.html * LayoutTests/accessibility/slot-aria-labelledby-expected.txt: Added. * LayoutTests/accessibility/slot-aria-labelledby.html: Added. * LayoutTests/resources/accessibility-helper.js: * Source/WebCore/accessibility/AccessibilityNodeObject.cpp: (WebCore::AccessibilityNodeObject::textForLabelElements const): (WebCore::accessibleNameForNode): Canonical link: https://commits.webkit.org/305882@main
1 parent f9a36f8 commit dfd0518

File tree

6 files changed

+170
-393
lines changed

6 files changed

+170
-393
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
This test ensures slot elements referenced by aria-labelledby correctly use slotted content over fallback, and exclude hidden slotted content.
2+
3+
Test 1: Button labelled by slot with slotted content should use slotted content.
4+
PASS: Text alternatives include 'Slotted'
5+
PASS: Text alternatives do not include 'Fallback'
6+
7+
Test 2: Button labelled by slot should exclude hidden slotted content.
8+
PASS: Text alternatives include 'Visible'
9+
PASS: Text alternatives do not include 'Hidden'
10+
PASS: Text alternatives do not include 'Fallback'
11+
12+
Test 3: Button labelled by slot with no slotted content should use fallback.
13+
PASS: Text alternatives include 'Fallback'
14+
15+
Test 4: Button labelled by slot with only hidden slotted content should use fallback.
16+
PASS: Text alternatives include 'Fallback'
17+
PASS: Text alternatives do not include 'Hidden'
18+
19+
Test 5: Dynamically adding slotted content should update the label.
20+
PASS: Text alternatives include 'Fallback'
21+
PASS: Text alternatives include 'Dynamic'
22+
PASS: Text alternatives do not include 'Fallback'
23+
24+
PASS successfullyParsed is true
25+
26+
TEST COMPLETE
27+
Slotted Visible Dynamic
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src="../resources/accessibility-helper.js"></script>
5+
<script src="../resources/js-test.js"></script>
6+
<style>
7+
.hidden { display: none; }
8+
</style>
9+
</head>
10+
<body>
11+
12+
<template id="slotted-label-template">
13+
<slot class="label-slot">Fallback</slot>
14+
<button class="shadow-button" aria-labelledby="label-slot">Action</button>
15+
</template>
16+
17+
<slotted-label-component id="test-slotted"><span>Slotted</span></slotted-label-component>
18+
19+
<slotted-label-component id="test-slotted-with-hidden"><span>Visible</span><span class="hidden">Hidden</span></slotted-label-component>
20+
21+
<slotted-label-component id="test-fallback">
22+
</slotted-label-component>
23+
24+
<slotted-label-component id="test-hidden-only">
25+
<span class="hidden">Hidden</span>
26+
</slotted-label-component>
27+
28+
<slotted-label-component id="test-dynamic">
29+
</slotted-label-component>
30+
31+
<script>
32+
var componentCount = 0;
33+
customElements.define(
34+
"slotted-label-component",
35+
class extends HTMLElement {
36+
constructor() {
37+
super();
38+
var template = document.getElementById("slotted-label-template").content;
39+
this.attachShadow({ mode: "open" }).appendChild(template.cloneNode(true));
40+
// Give each shadow button and slot a unique ID.
41+
this.uniqueId = componentCount++;
42+
this.shadowRoot.querySelector(".label-slot").id = "label-slot-" + this.uniqueId;
43+
this.shadowRoot.querySelector(".shadow-button").id = "shadow-button-" + this.uniqueId;
44+
this.shadowRoot.querySelector(".shadow-button").setAttribute("aria-labelledby", "label-slot-" + this.uniqueId);
45+
}
46+
47+
getButtonId() {
48+
return "shadow-button-" + this.uniqueId;
49+
}
50+
}
51+
);
52+
53+
var output = "This test ensures slot elements referenced by aria-labelledby correctly use slotted content over fallback, and exclude hidden slotted content.\n\n";
54+
55+
if (window.accessibilityController) {
56+
window.jsTestIsAsync = true;
57+
58+
var slottedButton;
59+
var slottedWithHiddenButton;
60+
var fallbackButton;
61+
var hiddenOnlyButton;
62+
var dynamicButton;
63+
64+
setTimeout(async function() {
65+
output += "Test 1: Button labelled by slot with slotted content should use slotted content.\n";
66+
slottedButton = accessibilityController.accessibleElementById(document.getElementById("test-slotted").getButtonId());
67+
output += checkTextAlternatives(slottedButton, { expected: ["Slotted"], unexpected: ["Fallback"] });
68+
69+
output += "\nTest 2: Button labelled by slot should exclude hidden slotted content.\n";
70+
slottedWithHiddenButton = accessibilityController.accessibleElementById(document.getElementById("test-slotted-with-hidden").getButtonId());
71+
output += checkTextAlternatives(slottedWithHiddenButton, { expected: ["Visible"], unexpected: ["Hidden", "Fallback"] });
72+
73+
output += "\nTest 3: Button labelled by slot with no slotted content should use fallback.\n";
74+
fallbackButton = accessibilityController.accessibleElementById(document.getElementById("test-fallback").getButtonId());
75+
output += checkTextAlternatives(fallbackButton, { expected: ["Fallback"] });
76+
77+
output += "\nTest 4: Button labelled by slot with only hidden slotted content should use fallback.\n";
78+
hiddenOnlyButton = accessibilityController.accessibleElementById(document.getElementById("test-hidden-only").getButtonId());
79+
output += checkTextAlternatives(hiddenOnlyButton, { expected: ["Fallback"], unexpected: ["Hidden"] });
80+
81+
output += "\nTest 5: Dynamically adding slotted content should update the label.\n";
82+
var dynamicComponent = document.getElementById("test-dynamic");
83+
dynamicButton = accessibilityController.accessibleElementById(dynamicComponent.getButtonId());
84+
output += checkTextAlternatives(dynamicButton, { expected: ["Fallback"] });
85+
86+
var newSpan = document.createElement("span");
87+
newSpan.textContent = "Dynamic";
88+
dynamicComponent.appendChild(newSpan);
89+
90+
await waitFor(() => {
91+
var alternatives = platformTextAlternatives(dynamicButton);
92+
return alternatives.includes("Dynamic") && !alternatives.includes("Fallback");
93+
});
94+
output += checkTextAlternatives(dynamicButton, { expected: ["Dynamic"], unexpected: ["Fallback"] });
95+
96+
debug(output);
97+
finishJSTest();
98+
}, 0);
99+
}
100+
</script>
101+
</body>
102+
</html>

LayoutTests/platform/glib/imported/w3c/web-platform-tests/accname/name/comp_host_language_label-expected.txt

Lines changed: 0 additions & 190 deletions
This file was deleted.

0 commit comments

Comments
 (0)