Skip to content
Permalink
Browse files
AX: Update the isolated tree in response to dynamic aria-grabbed and …
…aria-posinset changes

https://bugs.webkit.org/show_bug.cgi?id=240844

Reviewed by Chris Fleizach.

Added test cases to accessibility/aria-setsize-posinset.html and
accessibility/mac/aria-drag-drop.html.

* Source/WebCore/accessibility/AXLogger.cpp:
(WebCore::operator<<):
* Source/WebCore/accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::handleAttributeChange):
(WebCore::AXObjectCache::updateIsolatedTree):
* Source/WebCore/accessibility/AXObjectCache.h:
* Source/WebCore/accessibility/isolatedtree/AXIsolatedTree.cpp:
(WebCore::AXIsolatedTree::updateNodeProperty):
* LayoutTests/accessibility/aria-setsize-posinset-expected.txt:
* LayoutTests/accessibility/aria-setsize-posinset.html:
* LayoutTests/accessibility/mac/aria-drag-drop-expected.txt:
* LayoutTests/accessibility/mac/aria-drag-drop.html:

Canonical link: https://commits.webkit.org/250995@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@294863 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
twilco committed May 26, 2022
1 parent 411a48c commit abe15825d9ecbc1ee87f83384ec38a9eb9528424
Showing 8 changed files with 102 additions and 65 deletions.
@@ -1,17 +1,21 @@
This tests verifies that aria-posinset and aria-setsize are exposed to accessibility correctly.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


Verify that the first item in the list exposes setsize and posinset attributes.
PASS list.childAtIndex(0).isAttributeSupported('AXARIASetSize') is true
PASS list.childAtIndex(0).isAttributeSupported('AXARIAPosInSet') is true
PASS: firstListItem.isAttributeSupported('AXARIASetSize') === true
PASS: firstListItem.isAttributeSupported('AXARIAPosInSet') === true

Verify that the first item in the list returns the correct value for setsize and posinset.
PASS list.childAtIndex(0).numberAttributeValue('AXARIASetSize') is 100
PASS list.childAtIndex(0).numberAttributeValue('AXARIAPosInSet') is 3
PASS: firstListItem.numberAttributeValue('AXARIASetSize') === 100
PASS: firstListItem.numberAttributeValue('AXARIAPosInSet') === 3

Verify that the second item in the list does not support setsize and posinset.
PASS list.childAtIndex(1).isAttributeSupported('AXARIASetSize') is false
PASS list.childAtIndex(1).isAttributeSupported('AXARIAPosInSet') is false
PASS: secondListItem.isAttributeSupported('AXARIASetSize') === false
PASS: secondListItem.isAttributeSupported('AXARIAPosInSet') === false

Updating aria-posinset to 4 for element #first-list-item.
PASS: firstListItem.numberAttributeValue('AXARIAPosInSet') === 4

PASS successfullyParsed is true

TEST COMPLETE
@@ -1,43 +1,49 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
<script src="../resources/accessibility-helper.js"></script>
<script src="../resources/js-test.js"></script>
</head>
<body id="body">
<body>

<ul id="list">
<li aria-setsize="100" aria-posinset="3">3</li>
<li>4</li>
<li id="first-list-item" aria-setsize="100" aria-posinset="3">3</li>
<li id="second-list-item">4</li>
</ul>

<p id="description"></p>
<div id="console"></div>

<script>

description("This tests verifies that aria-posinset and aria-setsize are exposed to accessibility correctly.");
var testOutput = "This tests verifies that aria-posinset and aria-setsize are exposed to accessibility correctly.\n\n";

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

var list = accessibilityController.accessibleElementById("list");
var firstListItem = accessibilityController.accessibleElementById("first-list-item");
var secondListItem = accessibilityController.accessibleElementById("second-list-item");

debug("Verify that the first item in the list exposes setsize and posinset attributes.");
shouldBeTrue("list.childAtIndex(0).isAttributeSupported('AXARIASetSize')");
shouldBeTrue("list.childAtIndex(0).isAttributeSupported('AXARIAPosInSet')");
testOutput += "\nVerify that the first item in the list exposes setsize and posinset attributes.\n";
testOutput += expect("firstListItem.isAttributeSupported('AXARIASetSize')", "true");
testOutput += expect("firstListItem.isAttributeSupported('AXARIAPosInSet')", "true");

debug("Verify that the first item in the list returns the correct value for setsize and posinset.");
shouldBe("list.childAtIndex(0).numberAttributeValue('AXARIASetSize')", "100");
shouldBe("list.childAtIndex(0).numberAttributeValue('AXARIAPosInSet')", "3");
testOutput += "\nVerify that the first item in the list returns the correct value for setsize and posinset.\n";
testOutput += expect("firstListItem.numberAttributeValue('AXARIASetSize')", "100");
testOutput += expect("firstListItem.numberAttributeValue('AXARIAPosInSet')", "3");

debug("Verify that the second item in the list does not support setsize and posinset.");
shouldBeFalse("list.childAtIndex(1).isAttributeSupported('AXARIASetSize')");
shouldBeFalse("list.childAtIndex(1).isAttributeSupported('AXARIAPosInSet')");
testOutput += "\nVerify that the second item in the list does not support setsize and posinset.\n";
testOutput += expect("secondListItem.isAttributeSupported('AXARIASetSize')", "false");
testOutput += expect("secondListItem.isAttributeSupported('AXARIAPosInSet')", "false");

document.getElementById("list").style.visibility = 'hidden';
}
testOutput += "\nUpdating aria-posinset to 4 for element #first-list-item.\n";
document.getElementById("first-list-item").ariaPosInSet = "4";
setTimeout(async function() {
await waitFor(() => firstListItem.numberAttributeValue('AXARIAPosInSet') === 4);
testOutput += expect("firstListItem.numberAttributeValue('AXARIAPosInSet')", "4");

document.getElementById("list").style.visibility = 'hidden';
debug(testOutput);
finishJSTest();
}, 0);
}
</script>

<script src="../resources/js-test-post.js"></script>
</body>
</html>

@@ -1,17 +1,17 @@
drop
grab
grab
This tests that the ARIA drag and drop attributes work as intended.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS: accessibilityController.accessibleElementById('dropeffect-div').ariaDropEffects === 'copy,move'
PASS: initiallyGrabbedDiv.ariaIsGrabbed === true
PASS: initiallyUngrabbedDiv.ariaIsGrabbed === false
PASS: initiallyGrabbedDiv.isAttributeSettable('AXGrabbed') === true
PASS: initiallyUngrabbedDiv.isAttributeSettable('AXGrabbed') === true

Setting aria-grabbed false for element #initially-grabbed-div.
PASS: initiallyGrabbedDiv.ariaIsGrabbed === false

PASS body.childAtIndex(0).ariaDropEffects is 'copy,move'
PASS body.childAtIndex(1).ariaIsGrabbed is true
PASS body.childAtIndex(2).ariaIsGrabbed is false
PASS body.childAtIndex(1).isAttributeSettable('AXGrabbed') is true
PASS body.childAtIndex(2).isAttributeSettable('AXGrabbed') is true
PASS successfullyParsed is true

TEST COMPLETE

drop
grab
grab
@@ -1,37 +1,41 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
<script src="../../resources/js-test.js"></script>
</head>
<body id="body">
<body>

<div tabindex=0 aria-dropeffect="copy move" role="button" aria-label="drop">drop</div>
<div tabindex=0 aria-grabbed=true role="button" aria-label="grab1">grab</div>
<div tabindex=0 aria-grabbed=false role="button" aria-label="grab2">grab</div>

<p id="description"></p>
<div id="console"></div>
<div id="dropeffect-div" tabindex=0 aria-dropeffect="copy move" role="button" aria-label="drop">drop</div>
<div id="initially-grabbed-div" tabindex=0 aria-grabbed=true role="button" aria-label="grab1">grab</div>
<div id="initially-ungrabbed-div" tabindex=0 aria-grabbed=false role="button" aria-label="grab2">grab</div>

<script>

description("This tests that the ARIA drag and drop attributes work as intended.");
var testOutput = "This tests that the ARIA drag and drop attributes work as intended.\n\n";

if (window.accessibilityController) {

var body = document.getElementById("body");
body.focus();
body = accessibilityController.focusedElement;

shouldBe("body.childAtIndex(0).ariaDropEffects", "'copy,move'");

shouldBe("body.childAtIndex(1).ariaIsGrabbed", "true");
shouldBe("body.childAtIndex(2).ariaIsGrabbed", "false");
shouldBe("body.childAtIndex(1).isAttributeSettable('AXGrabbed')", "true");
shouldBe("body.childAtIndex(2).isAttributeSettable('AXGrabbed')", "true");
window.jsTestIsAsync = true;

testOutput += expect("accessibilityController.accessibleElementById('dropeffect-div').ariaDropEffects", "'copy,move'");

var initiallyGrabbedDiv = accessibilityController.accessibleElementById("initially-grabbed-div");
var initiallyUngrabbedDiv = accessibilityController.accessibleElementById("initially-ungrabbed-div");
testOutput += expect("initiallyGrabbedDiv.ariaIsGrabbed", "true");
testOutput += expect("initiallyUngrabbedDiv.ariaIsGrabbed", "false");
testOutput += expect("initiallyGrabbedDiv.isAttributeSettable('AXGrabbed')", "true");
testOutput += expect("initiallyUngrabbedDiv.isAttributeSettable('AXGrabbed')", "true");

testOutput += "\nSetting aria-grabbed false for element #initially-grabbed-div.\n";
document.getElementById("initially-grabbed-div").setAttribute("aria-grabbed", "false");
setTimeout(async function() {
await waitFor(() => !initiallyGrabbedDiv.ariaIsGrabbed );
testOutput += expect("initiallyGrabbedDiv.ariaIsGrabbed", "false");

debug(testOutput);
finishJSTest();
}, 0);
}

</script>

<script src="../../resources/js-test-post.js"></script>
</body>
</html>

@@ -391,6 +391,9 @@ TextStream& operator<<(TextStream& stream, AXObjectCache::AXNotification notific
case AXObjectCache::AXNotification::AXFrameLoadComplete:
stream << "AXFrameLoadComplete";
break;
case AXObjectCache::AXNotification::AXGrabbedStateChanged:
stream << "AXGrabbedStateChanged";
break;
case AXObjectCache::AXNotification::AXIdAttributeChanged:
stream << "AXIdAttributeChanged";
break;
@@ -412,6 +415,9 @@ TextStream& operator<<(TextStream& stream, AXObjectCache::AXNotification notific
case AXObjectCache::AXNotification::AXPageScrolled:
stream << "AXPageScrolled";
break;
case AXObjectCache::AXNotification::AXPositionInSetChanged:
stream << "AXPositionInSetChanged";
break;
case AXObjectCache::AXNotification::AXSelectedChildrenChanged:
stream << "AXSelectedChildrenChanged";
break;
@@ -1911,6 +1911,10 @@ void AXObjectCache::handleAttributeChange(const QualifiedName& attrName, Element
textChanged(element);
else if (attrName == aria_checkedAttr)
checkedStateChanged(element);
else if (attrName == aria_grabbedAttr)
postNotification(element, AXGrabbedStateChanged);
else if (attrName == aria_posinsetAttr)
postNotification(element, AXPositionInSetChanged);
else if (attrName == aria_selectedAttr)
selectedStateChanged(element);
else if (attrName == aria_expandedAttr)
@@ -3433,6 +3437,10 @@ void AXObjectCache::updateIsolatedTree(const Vector<std::pair<RefPtr<AXCoreObjec
case AXExpandedChanged:
tree->updateNodeProperty(*notification.first, AXPropertyName::IsExpanded);
break;
case AXPositionInSetChanged:
tree->updateNodeProperty(*notification.first, AXPropertyName::PosInSet);
tree->updateNodeProperty(*notification.first, AXPropertyName::SupportsPosInSet);
break;
case AXSortDirectionChanged:
tree->updateNodeProperty(*notification.first, AXPropertyName::SortDirection);
break;
@@ -3452,6 +3460,7 @@ void AXObjectCache::updateIsolatedTree(const Vector<std::pair<RefPtr<AXCoreObjec
case AXActiveDescendantChanged:
case AXAriaRoleChanged:
case AXElementBusyChanged:
case AXGrabbedStateChanged:
case AXInvalidStatusChanged:
case AXMenuListValueChanged:
case AXPressedStateChanged:
@@ -283,13 +283,15 @@ class AXObjectCache {
AXDisabledStateChanged,
AXFocusedUIElementChanged,
AXFrameLoadComplete,
AXGrabbedStateChanged,
AXIdAttributeChanged,
AXImageOverlayChanged,
AXLanguageChanged,
AXLayoutComplete,
AXLoadComplete,
AXNewDocumentLoadComplete,
AXPageScrolled,
AXPositionInSetChanged,
AXSelectedChildrenChanged,
AXSelectedStateChanged,
AXSelectedTextChanged,
@@ -359,12 +359,18 @@ void AXIsolatedTree::updateNodeProperty(AXCoreObject& axObject, AXPropertyName p
case AXPropertyName::IsSelected:
propertyMap.set(AXPropertyName::IsSelected, axObject.isSelected());
break;
case AXPropertyName::PosInSet:
propertyMap.set(AXPropertyName::PosInSet, axObject.posInSet());
break;
case AXPropertyName::ReadOnlyValue:
propertyMap.set(AXPropertyName::ReadOnlyValue, axObject.readOnlyValue().isolatedCopy());
break;
case AXPropertyName::SortDirection:
propertyMap.set(AXPropertyName::SortDirection, static_cast<int>(axObject.sortDirection()));
break;
case AXPropertyName::SupportsPosInSet:
propertyMap.set(AXPropertyName::SupportsPosInSet, axObject.supportsPosInSet());
break;
default:
return;
}

0 comments on commit abe1582

Please sign in to comment.