<!DOCTYPE HTML>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<div class="container">
<ul id="list1" role="listbox" aria-owns="item3">
<li role="option">One</li>
<li role="option">Two</li>
</ul>
<ul role="listbox" id="list2">
<li role="option" id="item3">Three</li>
<li role="option">Four</li>
</ul>
</div>
<script>
test(function(t)
{
const axList1 = accessibilityController.accessibleElementById("list1");
assert_equals(axList1.role, "AXRole: AXListBox");
assert_equals(axList1.childrenCount, 3);
const axItem = axList1.childAtIndex(0);
assert_equals(axList1.childAtIndex(0).name, "One");
assert_equals(axList1.childAtIndex(1).name, "Two");
assert_equals(axList1.childAtIndex(2).name, "Three");
const axList2 = accessibilityController.accessibleElementById("list2");
assert_equals(axList2.role, "AXRole: AXListBox");
assert_equals(axList2.childrenCount, 1);
assert_equals(axList2.childAtIndex(0).name, "Four");
}, "Aria-owns moves an element from one part of the tree to another.");
</script>
<div class="container">
<ul id="parent1" role="listbox" aria-owns="child"></ul>
<ul id="parent2" role="listbox" aria-owns="child"></ul>
<ul id="parent3" role="listbox">
<li id="child" role="option">Child</li>
</ul>
</div>
<script>
test(function(t)
{
const axParent1 = accessibilityController.accessibleElementById("parent1");
const axParent2 = accessibilityController.accessibleElementById("parent2");
const axParent3 = accessibilityController.accessibleElementById("parent3");
const axChild = accessibilityController.accessibleElementById("child");
// Either parent1 or parent2 should own the child, but either one is okay.
const axActualParent = axChild.parentElement();
assert_true(axActualParent.isEqual(axParent1) || axActualParent.isEqual(axParent2));
if (axActualParent.isEqual(axParent1)) {
assert_equals(axParent1.childrenCount, 1);
assert_equals(axParent1.childAtIndex(0).name, "Child");
assert_equals(axParent2.childrenCount, 0);
} else {
assert_equals(axParent1.childrenCount, 0);
assert_equals(axParent2.childrenCount, 1);
assert_equals(axParent2.childAtIndex(0).name, "Child");
}
assert_equals(axParent3.childrenCount, 0);
}, "If two nodes own (using aria-owns) the same element by id, only one gets to be the owner.");
</script>
<div class="container">
<div id="xyz" role="group">
<div id="x" role="group" aria-owns="y"></div>
<div id="y" role="group" aria-owns="z"></div>
<div id="z" role="group" aria-owns="x"></div>
</div>
</div>
<script>
test(function(t)
{
// Make sure we can walk the whole tree.
accessibilityController.accessibleElementById("dummy");
// Since there's no valid resolution to the cycle of aria-owns,
// just assert that each element's parent is either its real parent
// or its aria-owned parent, it doesn't matter which one.
const axXYZ = accessibilityController.accessibleElementById("xyz");
const axX = accessibilityController.accessibleElementById("x");
const axY = accessibilityController.accessibleElementById("y");
const axZ = accessibilityController.accessibleElementById("z");
assert_true(axX.parentElement().isEqual(axXYZ) ||
axX.parentElement().isEqual(axZ));
assert_true(axY.parentElement().isEqual(axXYZ) ||
axY.parentElement().isEqual(axX));
assert_true(axZ.parentElement().isEqual(axXYZ) ||
axZ.parentElement().isEqual(axY));
}, "An aria-owns relationship that would create a cycle is ignored.");
</script>
<div class="container">
<div id="real-parent" role="group">
<div id="owns-self" role="group" aria-owns="owns-self"></div>
</div>
</div>
<script>
test(function(t)
{
const axRealParent = accessibilityController.accessibleElementById("real-parent");
const axOwnsSelf = accessibilityController.accessibleElementById("owns-self");
assert_true(axOwnsSelf.parentElement().isEqual(axRealParent));
assert_equals(axOwnsSelf.childrenCount, 0);
}, "An element can't own itself.");
</script>
<div class="container">
<div id="yancy" role="group">
<div id="fry" role="group" aria-owns="yancy"></div>
</div>
</div>
<script>
test(function(t)
{
const axYancy = accessibilityController.accessibleElementById("yancy");
const axFry = accessibilityController.accessibleElementById("fry");
assert_equals(axFry.childrenCount, 0);
assert_equals(axYancy.childrenCount, 1);
assert_true(axYancy.childAtIndex(0).isEqual(axFry));
}, "An object cannot use aria-owns to own its own parent.");
</script>
<div class="container">
<div id="logical_parent" role="group" aria-owns="logical_1 logical_2 logical_3 logical_4">
<div id="logical_3">3</div>
<div id="logical_4">4</div>
<div id="logical_2">2</div>
<div id="logical_1">1</div>
</div>
</div>
<script>
test(function(t)
{
const axLogicalParent = accessibilityController.accessibleElementById("logical_parent");
assert_equals(axLogicalParent.childrenCount, 4);
assert_equals(axLogicalParent.childAtIndex(0).childAtIndex(0).name, "1");
assert_equals(axLogicalParent.childAtIndex(1).childAtIndex(0).name, "2");
assert_equals(axLogicalParent.childAtIndex(2).childAtIndex(0).name, "3");
assert_equals(axLogicalParent.childAtIndex(3).childAtIndex(0).name, "4");
}, "A parent can use aria-owns to reorder its children into a more logical AX ordering.");
</script>
<div class="container">
<ul id="dead_parent" aria-owns="orphan"></ul>
<li id="orphan">Orphan</li>
</div>
<script>
test(function(t)
{
const axDeadParent = accessibilityController.accessibleElementById(
"dead_parent");
assert_equals(axDeadParent.role, "AXRole: AXList");
assert_equals(axDeadParent.childrenCount, 1);
const axOrphan = axDeadParent.childAtIndex(0);
assert_equals(axOrphan.role, "AXRole: AXListItem");
assert_equals(axOrphan.parentElement().role, "AXRole: AXList");
const deadParent = document.getElementById("dead_parent");
deadParent.parentElement.removeChild(deadParent);
const orphan = document.getElementById("orphan");
orphan.setAttribute("id", "o2");
orphan.setAttribute("id", "orphan");
}, "No crash if an aria-owns parent is deleted and the child is re-added.");
</script>