Skip to content

Commit

Permalink
AX: Table accessibility text does not update when its caption dynamic…
Browse files Browse the repository at this point in the history
…ally changes it descendant text or is removed

https://bugs.webkit.org/show_bug.cgi?id=273456
rdar://127263464

Reviewed by Chris Fleizach.

When the descendants of caption elements change, we need to update the accessibility text of the associated table, as
tables use the caption as a type of label.

* LayoutTests/accessibility/dynamic-table-caption-expected.txt: Added.
* LayoutTests/accessibility/dynamic-table-caption.html: Added.
* Source/WebCore/accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::handleChildrenChanged):

Canonical link: https://commits.webkit.org/278164@main
  • Loading branch information
twilco committed Apr 30, 2024
1 parent 42fadaa commit 3de4518
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
26 changes: 26 additions & 0 deletions LayoutTests/accessibility/dynamic-table-caption-expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
This test ensures we maintain the right accessibility text for tables after dynamic caption changes.

AXTitle: Initial caption
AXDescription:
AXHelp:
PASS: text.includes('Initial caption') === true
AXTitle: Second caption
AXDescription:
AXHelp:
PASS: text.includes('Second caption') === true
AXTitle:
AXDescription:
AXHelp:
PASS: !text.includes('caption') === true
AXTitle: Final caption
AXDescription:
AXHelp:
PASS: text.includes('Final caption') === true

PASS successfullyParsed is true

TEST COMPLETE
Final caption
Author Title
Stephen Hawking A Brief History of Time
Carl Sagan Cosmos
79 changes: 79 additions & 0 deletions LayoutTests/accessibility/dynamic-table-caption.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/accessibility-helper.js"></script>
<script src="../resources/js-test.js"></script>
</head>
<body id="body">

<table id="table">
<caption id="caption">Initial caption</caption>
<thead>
<tr>
<th>Author</th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr>
<td>Stephen Hawking</td>
<td>A Brief History of Time</td>
</tr>
<tr>
<td>Carl Sagan</td>
<td>Cosmos</td>
</tr>
</tbody>
</table>

<script>
var output = "This test ensures we maintain the right accessibility text for tables after dynamic caption changes.\n\n";

if (window.accessibilityController) {
window.jsTestIsAsync = true;

var table = accessibilityController.accessibleElementById("table");
var text = platformTextAlternatives(table);
output += `${text}\n`;
output += expect("text.includes('Initial caption')", "true");

setTimeout(async function() {
// Wait for page updates caused by initial load to settle down so we don't pass the test by accident.
await sleep(20);
document.getElementById("caption").innerText = "Second caption";

await waitFor(() => {
text = platformTextAlternatives(table);
return text.includes("Second caption");
});
output += `${text}\n`;
output += expect("text.includes('Second caption')", "true");

document.getElementById("body").appendChild(document.getElementById("caption"));
document.getElementById("caption").innerText = "Final caption";

await waitFor(() => {
text = platformTextAlternatives(table);
return !text.includes("caption");
});
output += `${text}\n`;
output += expect("!text.includes('caption')", "true");

let domTable = document.getElementById("table");
domTable.insertBefore(document.getElementById("caption"), domTable.firstElementChild);

await waitFor(() => {
text = platformTextAlternatives(table);
return text.includes("Final caption");
});
output += `${text}\n`;
output += expect("text.includes('Final caption')", "true");

debug(output);
finishJSTest();
}, 0);
}
</script>
</body>
</html>

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
This test ensures we maintain the right accessibility text for tables after dynamic caption changes.

AXTitle: Initial caption
AXDescription:
PASS: text.includes('Initial caption') === true
AXTitle: Second caption
AXDescription:
PASS: text.includes('Second caption') === true
AXTitle:
AXDescription:
PASS: !text.includes('caption') === true
AXTitle: Final caption
AXDescription:
PASS: text.includes('Final caption') === true

PASS successfullyParsed is true

TEST COMPLETE
Final caption
Author Title
Stephen Hawking A Brief History of Time
Carl Sagan Cosmos
8 changes: 8 additions & 0 deletions Source/WebCore/accessibility/AXObjectCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,7 @@ void AXObjectCache::handleChildrenChanged(AccessibilityObject& object)

// Go up the existing ancestors chain and fire the appropriate notifications.
bool shouldUpdateParent = true;
bool foundTableCaption = false;
for (RefPtr parent = &object; parent; parent = parent->parentObjectIfExists()) {
if (shouldUpdateParent)
parent->setNeedsToUpdateChildren();
Expand All @@ -1337,6 +1338,13 @@ void AXObjectCache::handleChildrenChanged(AccessibilityObject& object)
// A label's descendant was added or removed. Update its LabelFor relationships.
handleLabelChanged(parent.get());
}

if (parent->hasTagName(captionTag))
foundTableCaption = true;
else if (foundTableCaption && parent->isTable()) {
postNotification(parent.get(), nullptr, AXTextChanged);
foundTableCaption = false;
}
}

// The role of list objects is dependent on their children, so we'll need to re-compute it here.
Expand Down

0 comments on commit 3de4518

Please sign in to comment.