Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ARIA id-ref reflection for ElementInternals #4452

Merged
merged 1 commit into from Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions LayoutTests/accessibility/custom-elements/controls-expected.txt
@@ -0,0 +1,16 @@
This tests that aria fallback roles work correctly.

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


PASS labelForControl(accessibilityController.accessibleElementById("custom-tab-1").ariaControlsElementAtIndex(0)) is "AXValue: Panel 1"
PASS labelForControl(accessibilityController.accessibleElementById("custom-tab-1").ariaControlsElementAtIndex(1)) is "AXValue: Panel 2"
PASS labelForControl(accessibilityController.accessibleElementById("custom-tab-2").ariaControlsElementAtIndex(0)) is "AXValue: Panel 3"
PASS accessibilityController.accessibleElementById("custom-tab-2").ariaControlsElementAtIndex(1) is null
PASS successfullyParsed is true

TEST COMPLETE
Panel 1
Panel 2
Panel 3
Panel 4
41 changes: 41 additions & 0 deletions LayoutTests/accessibility/custom-elements/controls.html
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<body>
<script src="../../resources/js-test.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
<custom-tab id="custom-tab-1"></custom-tab>
<div class="control">Panel 1</div>
<div class="control">Panel 2</div>
<custom-tab id="custom-tab-2" aria-controls="panel3"></custom-tab>
<div id="panel3" class="control">Panel 3</div>
<div id="panel4" class="control">Panel 4</div>
<script>

customElements.define('custom-tab', class CustomElement extends HTMLElement {
constructor()
{
super();
const internals = this.attachInternals();
internals.role = 'tab';
internals.ariaControlsElements = Array.from(document.querySelectorAll('.control'));
}
});

description("This tests that aria fallback roles work correctly.");
if (!window.accessibilityController)
debug('This test requires accessibilityController');
else {
function labelForControl(control) {
if (accessibilityController.platformName == "mac")
return control.childAtIndex(0).stringValue;
return control.stringValue;
}
shouldBeEqualToString('labelForControl(accessibilityController.accessibleElementById("custom-tab-1").ariaControlsElementAtIndex(0))', 'AXValue: Panel 1');
shouldBeEqualToString('labelForControl(accessibilityController.accessibleElementById("custom-tab-1").ariaControlsElementAtIndex(1))', 'AXValue: Panel 2');
shouldBeEqualToString('labelForControl(accessibilityController.accessibleElementById("custom-tab-2").ariaControlsElementAtIndex(0))', 'AXValue: Panel 3');
shouldBe('accessibilityController.accessibleElementById("custom-tab-2").ariaControlsElementAtIndex(1)', 'null');
}

</script>
</body>
</html>
28 changes: 28 additions & 0 deletions LayoutTests/accessibility/custom-elements/describedby-expected.txt
@@ -0,0 +1,28 @@
This tests that aria fallback roles work correctly.

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


PASS accessibilityController.accessibleElementById("custom-1").role is "AXRole: AXCheckBox"
PASS accessibilityController.accessibleElementById("custom-1").helpText is "AXHelp: some description other description"
PASS accessibilityController.accessibleElementById("custom-1").detailsElements().length is 2
PASS accessibilityController.accessibleElementById("custom-1").detailsElements()[0].domIdentifier is "details1"
PASS accessibilityController.accessibleElementById("custom-1").detailsElements()[1].domIdentifier is "details2"
PASS accessibilityController.accessibleElementById("custom-1").errorMessageElements().length is 2
PASS accessibilityController.accessibleElementById("custom-1").errorMessageElements()[0].domIdentifier is "error1"
PASS accessibilityController.accessibleElementById("custom-1").errorMessageElements()[1].domIdentifier is "error2"
PASS accessibilityController.accessibleElementById("custom-2").role is "AXRole: AXCheckBox"
PASS accessibilityController.accessibleElementById("custom-2").helpText is "AXHelp: some description"
PASS accessibilityController.accessibleElementById("custom-2").detailsElements().length is 1
PASS accessibilityController.accessibleElementById("custom-2").detailsElements()[0].domIdentifier is "details2"
PASS accessibilityController.accessibleElementById("custom-2").errorMessageElements().length is 1
PASS accessibilityController.accessibleElementById("custom-2").errorMessageElements()[0].domIdentifier is "error2"
PASS successfullyParsed is true

TEST COMPLETE
some description
other description
some details
other details
some error
other error
50 changes: 50 additions & 0 deletions LayoutTests/accessibility/custom-elements/describedby.html
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<body id="body">
<script src="../../resources/js-test.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
<custom-element id="custom-1"></custom-element>
<custom-element id="custom-2" aria-describedby="some" aria-details="details2" aria-errormessage="error2"></custom-element>
<div id="some" class="note">some description</div>
<div class="note">other description</div>
<div id="details1" class="details">some details</div>
<div id="details2" class="details">other details</div>
<div id="error1" class="error">some error</div>
<div id="error2" class="error">other error</div>
<script>

customElements.define('custom-element', class CustomElement extends HTMLElement {
constructor()
{
super();
const internals = this.attachInternals();
internals.role = 'checkbox';
internals.ariaDescribedByElements = Array.from(document.querySelectorAll('.note'));
internals.ariaDetailsElements = Array.from(document.querySelectorAll('.details'));
internals.ariaErrorMessageElements = Array.from(document.querySelectorAll('.error'));
}
});

description("This tests that aria fallback roles work correctly.");
if (!window.accessibilityController)
debug('This test requires accessibilityController');
else {
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").role', 'AXRole: AXCheckBox');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").helpText', 'AXHelp: some description other description');
shouldBe('accessibilityController.accessibleElementById("custom-1").detailsElements().length', '2');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").detailsElements()[0].domIdentifier', 'details1');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").detailsElements()[1].domIdentifier', 'details2');
shouldBe('accessibilityController.accessibleElementById("custom-1").errorMessageElements().length', '2');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").errorMessageElements()[0].domIdentifier', 'error1');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").errorMessageElements()[1].domIdentifier', 'error2');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-2").role', 'AXRole: AXCheckBox');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-2").helpText', 'AXHelp: some description');
shouldBe('accessibilityController.accessibleElementById("custom-2").detailsElements().length', '1');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-2").detailsElements()[0].domIdentifier', 'details2');
shouldBe('accessibilityController.accessibleElementById("custom-2").errorMessageElements().length', '1');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-2").errorMessageElements()[0].domIdentifier', 'error2');
}

</script>
</body>
</html>
24 changes: 24 additions & 0 deletions LayoutTests/accessibility/custom-elements/flowto-expected.txt
@@ -0,0 +1,24 @@
This tests that aria fallback roles work correctly.

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


PASS accessibilityController.accessibleElementById("custom-1").role is "AXRole: AXCheckBox"
PASS platformValueForW3CName(accessibilityController.accessibleElementById("custom-1")) is "label 1 label 2"
PASS accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(0).role is "AXRole: AXButton"
PASS accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(0).title is "AXTitle: FlowTo1"
PASS accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(1).role is "AXRole: AXButton"
PASS accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(1).title is "AXTitle: FlowTo2"
PASS accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(2) is null
PASS accessibilityController.accessibleElementById("custom-2").role is "AXRole: AXCheckBox"
PASS platformValueForW3CName(accessibilityController.accessibleElementById("custom-2")) is "label 2"
PASS accessibilityController.accessibleElementById("custom-2").ariaFlowToElementAtIndex(0).role is "AXRole: AXButton"
PASS accessibilityController.accessibleElementById("custom-2").ariaFlowToElementAtIndex(0).title is "AXTitle: FlowTo2"
PASS accessibilityController.accessibleElementById("custom-2").ariaFlowToElementAtIndex(1) is null
PASS successfullyParsed is true

TEST COMPLETE
FlowTo1
FlowTo2
label 1
label 2
45 changes: 45 additions & 0 deletions LayoutTests/accessibility/custom-elements/flowto.html
@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<body id="body">
<script src="../../resources/js-test.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
<custom-element id="custom-1"></custom-element>
<custom-element id="custom-2" aria-flowto="flowto2" aria-labelledby="label2"></custom-element>
<div role="button" class="flowto">FlowTo1</div>
<div id="flowto2" role="button" class="flowto">FlowTo2</div>
<div class="label">label 1</div>
<div id="label2" class="label">label 2</div>
<script>

customElements.define('custom-element', class CustomElement extends HTMLElement {
constructor()
{
super();
const internals = this.attachInternals();
internals.role = 'checkbox';
internals.ariaFlowToElements = Array.from(document.querySelectorAll('.flowto'));
internals.ariaLabelledByElements = Array.from(document.querySelectorAll('.label'));
}
});

description("This tests that aria fallback roles work correctly.");
if (!window.accessibilityController)
debug('This test requires accessibilityController');
else {
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").role', 'AXRole: AXCheckBox');
shouldBeEqualToString('platformValueForW3CName(accessibilityController.accessibleElementById("custom-1"))', 'label 1 label 2');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(0).role', 'AXRole: AXButton');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(0).title', 'AXTitle: FlowTo1');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(1).role', 'AXRole: AXButton');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(1).title', 'AXTitle: FlowTo2');
shouldBe('accessibilityController.accessibleElementById("custom-1").ariaFlowToElementAtIndex(2)', 'null');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-2").role', 'AXRole: AXCheckBox');
shouldBeEqualToString('platformValueForW3CName(accessibilityController.accessibleElementById("custom-2"))', 'label 2');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-2").ariaFlowToElementAtIndex(0).role', 'AXRole: AXButton');
shouldBeEqualToString('accessibilityController.accessibleElementById("custom-2").ariaFlowToElementAtIndex(0).title', 'AXTitle: FlowTo2');
shouldBe('accessibilityController.accessibleElementById("custom-2").ariaFlowToElementAtIndex(1)', 'null');
}

</script>
</body>
</html>
Expand Up @@ -3,6 +3,12 @@ This tests that aria fallback roles work correctly.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS accessibilityController.accessibleElementById("menu-1").selectedChildrenCount is 1
PASS platformValueForW3CName(accessibilityController.accessibleElementById("menu-1").selectedChildAtIndex(0)) is "item 2"
PASS accessibilityController.accessibleElementById("menu-1").selectedChildAtIndex(0).isSelected is true
PASS accessibilityController.accessibleElementById("menu-2").selectedChildrenCount is 1
PASS platformValueForW3CName(accessibilityController.accessibleElementById("menu-2").selectedChildAtIndex(0)) is "item 3"
PASS accessibilityController.accessibleElementById("menu-2").selectedChildAtIndex(0).isSelected is true
PASS accessibilityController.accessibleElementById("item-1").isEnabled is false
PASS accessibilityController.accessibleElementById("item-1").isExpanded is true
PASS accessibilityController.accessibleElementById("item-1").hasPopup is true
Expand Down
27 changes: 25 additions & 2 deletions LayoutTests/accessibility/custom-elements/menuitem.html
Expand Up @@ -3,10 +3,27 @@
<body>
<script src="../../resources/js-test.js"></script>
<script src="../../resources/accessibility-helper.js"></script>
<custom-menuitem id="item-1"></custom-menuitem>
<custom-menuitem id="item-2" aria-disabled="false" aria-expanded="false" aria-haspopup="false"></custom-menuitem>
<custom-menu id="menu-1">
<custom-menuitem id="item-1" aria-label="item 1"></custom-menuitem>
<custom-menuitem id="item-2" aria-label="item 2" aria-disabled="false" aria-expanded="false" aria-haspopup="false"></custom-menuitem>
</custom-menu>
<custom-menu id="menu-2" aria-activedescendant="item-3">
<custom-menuitem id="item-3" aria-label="item 3"></custom-menuitem>
<custom-menuitem id="item-4" aria-label="item 4"></custom-menuitem>
</custom-menu>
<script>

customElements.define('custom-menu', class CustomElement extends HTMLElement {
constructor()
{
super();
const internals = this.attachInternals();
internals.role = 'menubar';
internals.ariaActiveDescendantElement = document.getElementById('item-2');
window.customMenuInternals = internals;
}
});

customElements.define('custom-menuitem', class CustomElement extends HTMLElement {
constructor()
{
Expand All @@ -23,6 +40,12 @@
if (!window.accessibilityController)
debug('This test requires accessibilityController');
else {
shouldBe('accessibilityController.accessibleElementById("menu-1").selectedChildrenCount', '1');
shouldBeEqualToString('platformValueForW3CName(accessibilityController.accessibleElementById("menu-1").selectedChildAtIndex(0))', 'item 2');
shouldBeTrue('accessibilityController.accessibleElementById("menu-1").selectedChildAtIndex(0).isSelected');
shouldBe('accessibilityController.accessibleElementById("menu-2").selectedChildrenCount', '1');
shouldBeEqualToString('platformValueForW3CName(accessibilityController.accessibleElementById("menu-2").selectedChildAtIndex(0))', 'item 3');
shouldBeTrue('accessibilityController.accessibleElementById("menu-2").selectedChildAtIndex(0).isSelected');
shouldBe('accessibilityController.accessibleElementById("item-1").isEnabled', 'false');
shouldBe('accessibilityController.accessibleElementById("item-1").isExpanded', 'true');
shouldBe('accessibilityController.accessibleElementById("item-1").hasPopup', 'true');
Expand Down
@@ -1,34 +1,34 @@

PASS role is defined in ElementInternals
FAIL ariaActiveDescendantElement is defined in ElementInternals assert_inherits: property "ariaActiveDescendantElement" not found in prototype chain
PASS ariaActiveDescendantElement is defined in ElementInternals
PASS ariaAtomic is defined in ElementInternals
PASS ariaAutoComplete is defined in ElementInternals
PASS ariaBusy is defined in ElementInternals
PASS ariaChecked is defined in ElementInternals
PASS ariaColCount is defined in ElementInternals
PASS ariaColIndex is defined in ElementInternals
PASS ariaColSpan is defined in ElementInternals
FAIL ariaControlsElements is defined in ElementInternals assert_inherits: property "ariaControlsElements" not found in prototype chain
PASS ariaControlsElements is defined in ElementInternals
PASS ariaCurrent is defined in ElementInternals
FAIL ariaDescribedByElements is defined in ElementInternals assert_inherits: property "ariaDescribedByElements" not found in prototype chain
FAIL ariaDetailsElements is defined in ElementInternals assert_inherits: property "ariaDetailsElements" not found in prototype chain
PASS ariaDescribedByElements is defined in ElementInternals
PASS ariaDetailsElements is defined in ElementInternals
PASS ariaDisabled is defined in ElementInternals
FAIL ariaErrorMessageElement is defined in ElementInternals assert_inherits: property "ariaErrorMessageElement" not found in prototype chain
PASS ariaExpanded is defined in ElementInternals
FAIL ariaFlowToElements is defined in ElementInternals assert_inherits: property "ariaFlowToElements" not found in prototype chain
PASS ariaFlowToElements is defined in ElementInternals
PASS ariaHasPopup is defined in ElementInternals
PASS ariaHidden is defined in ElementInternals
PASS ariaInvalid is defined in ElementInternals
PASS ariaKeyShortcuts is defined in ElementInternals
PASS ariaLabel is defined in ElementInternals
FAIL ariaLabelledByElements is defined in ElementInternals assert_inherits: property "ariaLabelledByElements" not found in prototype chain
PASS ariaLabelledByElements is defined in ElementInternals
PASS ariaLevel is defined in ElementInternals
PASS ariaLive is defined in ElementInternals
PASS ariaModal is defined in ElementInternals
PASS ariaMultiLine is defined in ElementInternals
PASS ariaMultiSelectable is defined in ElementInternals
PASS ariaOrientation is defined in ElementInternals
FAIL ariaOwnsElements is defined in ElementInternals assert_inherits: property "ariaOwnsElements" not found in prototype chain
PASS ariaOwnsElements is defined in ElementInternals
PASS ariaPlaceholder is defined in ElementInternals
PASS ariaPosInSet is defined in ElementInternals
PASS ariaPressed is defined in ElementInternals
Expand Down