Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<meta charset="utf-8">
<title>HTML Test: focusgroup - Child implied AX role inference</title>
<meta name="assert" content="Generic child elements inside a focusgroup with implied owner role map to behavior-specific child roles; explicit and native child roles are preserved.">
<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<!-- Tablist behavior -->
<div id=fgTablist focusgroup="tablist">
<span tabindex=0 id=tabChild>Tab</span>
</div>
<!-- Radiogroup behavior -->
<div id=fgRadiogroup focusgroup="radiogroup">
<span tabindex=0 id=radioChild>Radio</span>
</div>
<!-- Listbox behavior -->
<div id=fgListbox focusgroup="listbox">
<span tabindex=0 id=listboxChild>Option</span>
</div>
<!-- Menu behavior -->
<div id=fgMenu focusgroup="menu">
<span tabindex=0 id=menuChild>Menu Item</span>
</div>
<!-- Menubar behavior -->
<div id=fgMenubar focusgroup="menubar">
<span tabindex=0 id=menubarChild>Menu Item</span>
</div>
<!-- Explicit child role (should not be overridden) -->
<div id=fgExplicitChild focusgroup="tablist">
<span id="explicitChild" tabindex=0 role=listitem>List Item</span>
</div>
<!-- Native child semantics (link) should be preserved -->
<div id=fgNativeChild focusgroup="radiogroup">
<a href="#" id=nativeChild>Link</a>
</div>
<!-- Native child semantics (input) should be preserved -->
<div id=fgNativeInput focusgroup="tablist">
<input id=nativeInputChild type="text">
</div>
<!-- Button child should be inferred (tablist) -->
<div id=fgButtonTablist focusgroup="tablist">
<button id=buttonTabChild>Tab</button>
</div>
<!-- Button child should be inferred (radiogroup) -->
<div id=fgButtonRadiogroup focusgroup="radiogroup">
<button id=buttonRadioChild>Radio</button>
</div>
<!-- Button child should be inferred (menu) -->
<div id=fgButtonMenu focusgroup="menu">
<button id=buttonMenuChild>Menu Item</button>
</div>
<!-- Button child should be inferred (menubar) -->
<div id=fgButtonMenubar focusgroup="menubar">
<button id=buttonMenubarChild>Menu Item</button>
</div>
<!-- Button child with explicit role should be preserved -->
<div id=fgButtonExplicit focusgroup="tablist">
<button id=buttonExplicitChild role="listitem">List Item</button>
</div>
<!-- Popup button child should be inferred (menu) -->
<div id=fgPopupButtonMenu focusgroup="menu">
<button id=popupButtonMenuChild aria-haspopup="menu">Submenu</button>
</div>
<!-- Popup button child should be inferred (menubar) -->
<div id=fgPopupButtonMenubar focusgroup="menubar">
<button id=popupButtonMenubarChild aria-haspopup="menu">Submenu</button>
</div>
<!-- Popup button child should be inferred (tablist) -->
<div id=fgPopupButtonTablist focusgroup="tablist">
<button id=popupButtonTablistChild aria-haspopup="menu">Tab with popup</button>
</div>
<!-- Popup button child should be inferred (radiogroup) -->
<div id=fgPopupButtonRadiogroup focusgroup="radiogroup">
<button id=popupButtonRadiogroupChild aria-haspopup="menu">Radio with popup</button>
</div>
<!-- Popup button with explicit role should be preserved -->
<div id=fgPopupButtonExplicit focusgroup="menubar">
<button id=popupButtonExplicitChild aria-haspopup="menu" role="listitem">List Item</button>
</div>
<!-- aria-haspopup="listbox" also produces kPopUpButton; should infer menuitem -->
<div id=fgPopupButtonListbox focusgroup="menubar">
<button id=popupButtonListboxChild aria-haspopup="listbox">Options</button>
</div>
<!-- aria-haspopup="dialog" produces kButton (not kPopUpButton); should still infer -->
<div id=fgPopupButtonDialog focusgroup="menubar">
<button id=popupButtonDialogChild aria-haspopup="dialog">Open Dialog</button>
</div>
<script>
// Use WebDriver get_computed_role to assert author vs implied roles.
// This mirrors pattern in wai-aria/role/basic.html.
async function assert_role_equals(idref,expected_role) {
const element = document.getElementById(idref);
const role = await test_driver.get_computed_role(element);
assert_equals(role, expected_role);
}
promise_test(async t => {
await assert_role_equals('tabChild', 'tab');
}, 'Tablist child gets implied tab role');
promise_test(async t => {
// Blink exposes role="radio" as AXRadioButton internally; computed role should be 'radio'.
await assert_role_equals('radioChild', 'radio');
}, 'Radiogroup child gets implied radio role');
promise_test(async t => {
await assert_role_equals('listboxChild', 'option');
}, 'Listbox child gets implied option role');
promise_test(async t => {
await assert_role_equals('menuChild', 'menuitem');
}, 'Menu child gets implied menuitem role');
promise_test(async t => {
// Menubar items map to menuitem.
await assert_role_equals('menubarChild', 'menuitem');
}, 'Menubar child gets implied menuitem role');
promise_test(async t => {
// Explicit author-supplied listitem role should be preserved.
await assert_role_equals('explicitChild', 'listitem');
}, 'Explicit child role preserved over implied mapping');
promise_test(async t => {
// Native link semantics must be preserved.
await assert_role_equals('nativeChild', 'link');
}, 'Native link semantics preserved over implied mapping');
promise_test(async t => {
// Native input semantics must be preserved.
await assert_role_equals('nativeInputChild', 'textbox');
}, 'Native input semantics preserved over implied mapping');
promise_test(async t => {
// Button inside tablist should be inferred as tab.
await assert_role_equals('buttonTabChild', 'tab');
}, 'Button child gets implied tab role in tablist');
promise_test(async t => {
// Button inside radiogroup should be inferred as radio.
await assert_role_equals('buttonRadioChild', 'radio');
}, 'Button child gets implied radio role in radiogroup');
promise_test(async t => {
// Button inside menu should be inferred as menuitem.
await assert_role_equals('buttonMenuChild', 'menuitem');
}, 'Button child gets implied menuitem role in menu');
promise_test(async t => {
// Button inside menubar should be inferred as menuitem.
await assert_role_equals('buttonMenubarChild', 'menuitem');
}, 'Button child gets implied menuitem role in menubar');
promise_test(async t => {
// Explicit role on button should be preserved.
await assert_role_equals('buttonExplicitChild', 'listitem');
}, 'Button child with explicit role preserved over implied mapping');
promise_test(async t => {
// Popup button inside menu should be inferred as menuitem.
await assert_role_equals('popupButtonMenuChild', 'menuitem');
}, 'Popup button child gets implied menuitem role in menu');
promise_test(async t => {
// Popup button inside menubar should be inferred as menuitem.
await assert_role_equals('popupButtonMenubarChild', 'menuitem');
}, 'Popup button child gets implied menuitem role in menubar');
promise_test(async t => {
// Popup button inside tablist should be inferred as tab.
await assert_role_equals('popupButtonTablistChild', 'tab');
}, 'Popup button child gets implied tab role in tablist');
promise_test(async t => {
// Popup button inside radiogroup should be inferred as radio.
await assert_role_equals('popupButtonRadiogroupChild', 'radio');
}, 'Popup button child gets implied radio role in radiogroup');
promise_test(async t => {
// Explicit role on popup button should be preserved.
await assert_role_equals('popupButtonExplicitChild', 'listitem');
}, 'Popup button child with explicit role preserved over implied mapping');
promise_test(async t => {
// aria-haspopup="listbox" produces kPopUpButton; should be inferred as
// menuitem inside a menubar focusgroup.
await assert_role_equals('popupButtonListboxChild', 'menuitem');
}, 'Popup button with aria-haspopup=listbox gets implied menuitem role in menubar');
promise_test(async t => {
// aria-haspopup="dialog" produces kButton (not kPopUpButton); should still
// be inferred as menuitem via the kButton branch.
await assert_role_equals('popupButtonDialogChild', 'menuitem');
}, 'Popup button with aria-haspopup=dialog gets implied menuitem role in menubar');
</script>