AX: AXPropertyName::IsSelected should be updated when AXObjectCache receives a selected-state change
https://bugs.webkit.org/show_bug.cgi?id=257668
rdar://problem/110190482

Reviewed by Chris Fleizach.

* LayoutTests/accessibility/display-contents/tree-and-treeitems.html:
Make this test async so we wait for AX to update after DOM changes.
* Source/WebCore/accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::onSelectedChanged):

Canonical link: https://commits.webkit.org/264851@main
diff --git a/LayoutTests/accessibility/display-contents/tree-and-treeitems.html b/LayoutTests/accessibility/display-contents/tree-and-treeitems.html
index 2192e89..7e6eaaa 100644
--- a/LayoutTests/accessibility/display-contents/tree-and-treeitems.html
+++ b/LayoutTests/accessibility/display-contents/tree-and-treeitems.html
@@ -84,30 +84,31 @@
     output += expect("treeitem3.subrole", "'AXSubrole: AXOutlineRow'");
     output += expect("treeitem3.isExpanded", "true");
 
+    var selectedRow, treeitem4, treeitem5, treeitem6;
     // Test that the row can be selected correctly.
     output += expect("treeitem3.isSelected", "false");
     document.getElementById("treeitem3").setAttribute("aria-selected", true);
-    output += expect("treeitem3.isSelected", "true");
-
-    // Test that the tree reports the right selected row (treeitem3)
-    var selectedRow = tree.selectedRowAtIndex(0);
-    output += expect("selectedRow.isEqual(treeitem3)", "true");
-
-    // Test that hierarchicalLevel can be computed automatically, and that it's consistent with the ARIA level.
-    var treeitem4 = accessibilityController.accessibleElementById("treeitem4");
-    output += expect("treeitem4.hierarchicalLevel", "0");
-
-    var treeitem5 = accessibilityController.accessibleElementById("treeitem5");
-    output += expect("treeitem5.hierarchicalLevel", "1");
-
-    var treeitem6 = accessibilityController.accessibleElementById("treeitem6");
-    output += expect("treeitem6.hierarchicalLevel", "1");
-
-    output += "\nUpdating aria-level of #treeitem2 to 3.\n";
-    document.getElementById("treeitem2").setAttribute("aria-level", "3");
     setTimeout(async function() {
-        await waitFor(() => treeitem2.hierarchicalLevel === 2);
-        output += expect("treeitem2.hierarchicalLevel", "2");
+        output += await expectAsync("treeitem3.isSelected", "true");
+
+        // Test that the tree reports the right selected row (treeitem3)
+        selectedRow = tree.selectedRowAtIndex(0);
+        output += expect("selectedRow.isEqual(treeitem3)", "true");
+
+        // Test that hierarchicalLevel can be computed automatically, and that it's consistent with the ARIA level.
+        treeitem4 = accessibilityController.accessibleElementById("treeitem4");
+        output += expect("treeitem4.hierarchicalLevel", "0");
+
+        treeitem5 = accessibilityController.accessibleElementById("treeitem5");
+        output += expect("treeitem5.hierarchicalLevel", "1");
+
+        treeitem6 = accessibilityController.accessibleElementById("treeitem6");
+        output += expect("treeitem6.hierarchicalLevel", "1");
+
+        output += "\nUpdating aria-level of #treeitem2 to 3.\n";
+        document.getElementById("treeitem2").setAttribute("aria-level", "3");
+
+        output += await expectAsync("treeitem2.hierarchicalLevel", "2");
 
         debug(output);
         finishJSTest();
diff --git a/Source/WebCore/accessibility/AXObjectCache.cpp b/Source/WebCore/accessibility/AXObjectCache.cpp
index b3ac064..a0fa72b 100644
--- a/Source/WebCore/accessibility/AXObjectCache.cpp
+++ b/Source/WebCore/accessibility/AXObjectCache.cpp
@@ -1547,8 +1547,10 @@
     else if (auto* axObject = getOrCreate(node)) {
         if (auto* ancestor = Accessibility::findAncestor<AccessibilityObject>(*axObject, false, [] (const auto& object) {
             return object.canHaveSelectedChildren();
-        }))
+        })) {
             selectedChildrenChanged(ancestor->node());
+            postNotification(axObject, &node->document(), AXSelectedStateChanged);
+        }
     }
 
     handleMenuItemSelected(node);