summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/wai-aria/role
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/wai-aria/role
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/wai-aria/role')
-rw-r--r--testing/web-platform/tests/wai-aria/role/ReadMe.md16
-rw-r--r--testing/web-platform/tests/wai-aria/role/abstract-roles.html36
-rw-r--r--testing/web-platform/tests/wai-aria/role/basic.html33
-rw-r--r--testing/web-platform/tests/wai-aria/role/button-roles.html32
-rw-r--r--testing/web-platform/tests/wai-aria/role/contextual-roles.html91
-rw-r--r--testing/web-platform/tests/wai-aria/role/fallback-roles.html57
-rw-r--r--testing/web-platform/tests/wai-aria/role/form-roles.html28
-rw-r--r--testing/web-platform/tests/wai-aria/role/generic-roles.html23
-rw-r--r--testing/web-platform/tests/wai-aria/role/grid-roles.html59
-rw-r--r--testing/web-platform/tests/wai-aria/role/invalid-roles.html135
-rw-r--r--testing/web-platform/tests/wai-aria/role/list-roles.html29
-rw-r--r--testing/web-platform/tests/wai-aria/role/listbox-roles.html43
-rw-r--r--testing/web-platform/tests/wai-aria/role/menu-roles.html82
-rw-r--r--testing/web-platform/tests/wai-aria/role/region-roles.html27
-rw-r--r--testing/web-platform/tests/wai-aria/role/role_none_conflict_resolution.html38
-rw-r--r--testing/web-platform/tests/wai-aria/role/roles.html140
-rw-r--r--testing/web-platform/tests/wai-aria/role/synonym-roles.html34
-rw-r--r--testing/web-platform/tests/wai-aria/role/tab-roles.html94
-rw-r--r--testing/web-platform/tests/wai-aria/role/table-roles.html156
-rw-r--r--testing/web-platform/tests/wai-aria/role/tree-roles.html150
20 files changed, 1303 insertions, 0 deletions
diff --git a/testing/web-platform/tests/wai-aria/role/ReadMe.md b/testing/web-platform/tests/wai-aria/role/ReadMe.md
new file mode 100644
index 0000000000..eb89da7846
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/ReadMe.md
@@ -0,0 +1,16 @@
+
+# WPT Roles Tests
+
+/wai-aria/roles/ includes various files broken up by test type
+
+- **roles.html** covers simple assignment/verification of most core WAI-ARIA roles, and includes a list of cross-references to other specific files and spec directories.
+- role testing of *host language* implicit roles (E.g., `<main> -> main`) are in other directories (E.g., [html-aam](https://github.com/web-platform-tests/interop-accessibility/issues/13))
+- role testing of **ARIA extension specs** are in other directories (E.g., [graphics-aria](https://github.com/web-platform-tests/interop-accessibility/issues/9))
+- basic.html was the first to ensure basic test coverage of webdriver getcomputedrole
+- other context-dependent role tests, error handling, and edge cases are covered in separate files
+ - list-roles.html
+ - region-roles.html
+ - grid, listbox, menu, tree, etc
+ - fallback roles
+ - invalid roles
+ - error handling, etc.
diff --git a/testing/web-platform/tests/wai-aria/role/abstract-roles.html b/testing/web-platform/tests/wai-aria/role/abstract-roles.html
new file mode 100644
index 0000000000..520ecf2dbb
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/abstract-roles.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+<head>
+ <title>Abstract Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+
+<p>Tests <a href="https://w3c.github.io/aria/#abstract_roles">Abstract Roles</a> and related <a href="https://w3c.github.io/aria/#document-handling_author-errors_roles">9.1 Roles - handling author errors</a></p>
+
+ <nav role="command" data-testname="command role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="composite" data-testname="composite role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="input" data-testname="input role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="landmark" data-testname="landmark role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="range" data-testname="range role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="roletype" data-testname="roletype role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="section" data-testname="section role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="sectionhead" data-testname="sectionhead role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="select" data-testname="select role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="structure" data-testname="structure role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="widget" data-testname="widget role" data-expectedrole="navigation" class="ex">x</nav>
+ <nav role="window" data-testname="window role" data-expectedrole="navigation" class="ex">x</nav>
+
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/basic.html b/testing/web-platform/tests/wai-aria/role/basic.html
new file mode 100644
index 0000000000..5fbe1fe2aa
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/basic.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<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>
+
+<!--
+
+These tests should remain solid and passing in any implementation that supports get_computed_role.
+
+It uses a standard promise_test (rather than aria-util.js) to reduce other dependencies.
+
+If you're adding something you expect to fail in one or more implementations, you probably want a different file.
+
+-->
+
+<div id='d' style='height: 100px; width: 100px' role="group" aria-label="test label"></div>
+<h1 id="h">test heading</h1>
+<script>
+
+promise_test(async t => {
+ const role = await test_driver.get_computed_role(document.getElementById('d'));
+ assert_equals(role, "group");
+}, "tests explicit role");
+
+
+promise_test(async t => {
+ const role = await test_driver.get_computed_role(document.getElementById('h'));
+ assert_equals(role, "heading");
+}, "tests implicit role");
+
+</script>
diff --git a/testing/web-platform/tests/wai-aria/role/button-roles.html b/testing/web-platform/tests/wai-aria/role/button-roles.html
new file mode 100644
index 0000000000..23d0cd22d6
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/button-roles.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+<head>
+ <title>Button-related Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#button">button</a> and related roles.</p>
+
+<div role="button" aria-haspopup="false" data-testname="button aria-haspopup false" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-haspopup="true" data-testname="button aria-haspopup true" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-haspopup="menu" data-testname="button aria-haspopup menu" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-haspopup="dialog" data-testname="button aria-haspopup dialog" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-haspopup="listbox" data-testname="button aria-haspopup listbox" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-haspopup="tree" data-testname="button aria-haspopup tree" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-haspopup="grid" data-testname="button aria-haspopup grid" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-pressed="true" data-testname="button aria-pressed true" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-pressed="false" data-testname="button aria-pressed false" data-expectedrole="button" class="ex"></div>
+<div role="button" aria-pressed="" data-testname="button aria-pressed undefined" data-expectedrole="button" class="ex"></div>
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/wai-aria/role/contextual-roles.html b/testing/web-platform/tests/wai-aria/role/contextual-roles.html
new file mode 100644
index 0000000000..90b1842f08
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/contextual-roles.html
@@ -0,0 +1,91 @@
+<!doctype html>
+<html>
+<head>
+ <title>Contextual Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+ <p>Verifies Required Accessibility Parent Roles from <a href="https://w3c.github.io/aria/#scope">5.2.7 Required Accessibility Parent Role</a></p>
+ <p>Also verifies Allowed Accessibility Child Roles from <a href="https://w3c.github.io/aria/#mustContain">5.2.6 Allowed Accessibility Child Roles</a></p>
+
+<!-- Notes for "required context" testing:
+
+ - See Computed Role for more details on role computation when an element lacks required context:
+ https://w3c.github.io/core-aam/#roleMappingComputedRole
+
+ - See ARIA spec for full listing of "Required Accessibility Parent Role" for each element:
+ https://w3c.github.io/aria/#scope
+
+ Identified roles with "Required Context" excluding abstract roles (e.g., child -> parent):
+
+ - caption -> {figure, grid, table, treegrid}
+ - cell -> row
+ - columnheader -> row
+ - gridcell -> row
+ - listitem -> {list, directory} *Note: directory role is deprecated as of ARIA 1.2
+ - menuitem -> {group, menu, menubar}
+ - menuitemcheckbox -> {group, menu, menubar}
+ - menuitemradio -> {group, menu, menubar}
+ - option -> {group, listbox}
+ - row -> {grid, rowgroup, table, treegrid}
+ - rowgroup -> {grid, table, treegrid}
+ - rowheader -> row
+ - tab -> tablist
+ - treeitem -> {group, tree}
+
+ -->
+
+<!-- Required Context Roles Testing -->
+
+ <!-- caption -> ./table-roles.html -->
+
+ <!-- cell -> ./table-roles.html -->
+
+ <!-- columnheader -> ./grid-roles.html, ./table-roles.html -->
+
+ <!-- gridcell -> ./grid-roles.html -->
+
+ <!-- listitem -> ./list-roles.html -->
+
+ <!-- menuitem, menuitemcheckbox, menuitemradio -> ./menu-roles.html -->
+
+ <!-- option -> ./listbox-roles.html -->
+
+ <!-- row -> ./grid-roles.html, ./table-roles.html -->
+
+ <!-- rowgroup -> ./grid-roles.html, ./table-roles.html -->
+
+ <!-- rowheader -> ./grid-roles.html, ./table-roles.html -->
+
+ <!-- tab -> ./tab-roles.html -->
+
+ <!-- treeitem -> ./tree-roles.html -->
+
+<!-- Misc Contextual Role Testing -->
+
+ <!-- Testing contentinfo role computation when scoped to <main> or not:
+ 1. If <footer> is a descendant of <main>, it should become 'generic'
+ 2. If <footer> is scoped to <body>, it should be 'contentinfo' as expected
+
+ see: https://w3c.github.io/html-aam/#el-footer-ancestorbody -->
+ <main>
+ <footer data-testname="footer element scoped to main element is generic" class="ex-generic">x</footer>
+ <div role="contentinfo" data-testname="contentinfo region scoped to main element is generic" class="ex-generic">x</div>
+ </main>
+
+ <footer data-testname="footer scoped to body element is contentinfo" data-expectedrole="contentinfo" class="ex">x</footer>
+ <div role="contentinfo" data-testname="contentinfo region scoped to body element is contentinfo" data-expectedrole="contentinfo" class="ex">x</div>
+
+<script>
+ AriaUtils.verifyRolesBySelector(".ex");
+ AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/fallback-roles.html b/testing/web-platform/tests/wai-aria/role/fallback-roles.html
new file mode 100644
index 0000000000..98011570b4
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/fallback-roles.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Fallback Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+ </head>
+ <body>
+
+ <p>Tests <a href="https://w3c.github.io/aria/#host_general_role">8.1 Role Attribute</a> role token list selection and <a href="https://w3c.github.io/aria/#document-handling_author-errors_roles">9.1 Roles - handling author errors</a>.</p>
+
+ <!-- known el and two known ARIA 1.0 roles -->
+ <nav role="region group" data-testname="fallback role w/ region with no label" data-expectedrole="group" class="ex">x</nav>
+ <nav role="region group" data-testname="fallback role w/ region with label" aria-label="x" data-expectedrole="region" class="ex">x</nav>
+
+ <!-- known el and known ARIA 1.1 with 1.0 role backup -->
+ <div role="switch checkbox" aria-checked="true" data-testname="aria 1.1 switch role w/ fallback to aria 1.0 checkbox role" aria-label="x" data-expectedrole="switch" class="ex">x</div>
+
+ <!-- known el and invalid role token with valid backup -->
+ <div role="foo button" data-testname="div[role=button] ignoring invalid foo role token" aria-label="x" data-expectedrole="button" class="ex">x</div>
+
+ <!-- unknown el and invalid role token with valid backup -->
+ <unknown role="foo button" data-testname="unknown[role=button] ignoring invalid foo role token" aria-label="x" data-expectedrole="button" class="ex">x</unknown>
+
+ <!-- known el and invalid role(s) -->
+ <button role="foo" data-testname="button ignoring single invalid role token" aria-label="x" data-expectedrole="button" class="ex">x</unknown>
+ <button role="foo bar" data-testname="button ignoring multiple invalid role tokens" aria-label="x" data-expectedrole="button" class="ex">x</unknown>
+
+ <!-- known el with invalid punctuation -->
+ <div role="invalid, punctuation, tests, link, button" data-testname="div[role=button] ignoring invalid foo role token including punctuation-contaminated known link role" aria-label="x" data-expectedrole="button" class="ex">x</div>
+
+
+
+ <!-- extra line breaks here to account for rendering of unicode diacritic etc char glitch tests -->
+
+
+
+ <div role="l̷̨̢̡̖̻̗̤̺̟̱͚͔͇͍͇̫̫̜͔̗̟̘̫̟̰̼̘͗̌̃͐̔̈́̚͝į̵̡̲̯̠̮͈͖̥̮̲͓̦̗̗̱̞͍̗̪͙͇͚͂̍͐̔̍͌̐̇̏̎͘͝ǹ̶̨̧̢̜̲̫͇̮͉̬͎͎͕̝̱͔̙̱̦̰̦̠̰̣̝͂̓̋̊͜ķ̷̧̧̨̨̨̘̳͕̰͎̮̠̘̪͇͕̥̭̼̼̜̤̫̥̼̤̰̦͖̪̀͒̆͑̒̅͑̓̒͂̽̈́̽̉̀̕͘͜͝ ̷̡̮̦̘͓̫̜͕͖̰̙̘͓̼͎̳̹͇̮͐͂́͛̃́̊̈͌̄̓̌̂̈̇̀̌̈́́̀̈́̍̈́̇̄̊̔͒̾̾̇́͒̽͂̾̕̚͜͜͝͠ͅͅg̸̨̧̧̧̧̛̺̦̣͇͈͙͇͎͕̠̞̳̹̣͋͑̑̓͛̓̉̔̉͑̇́̈́̉̃́̑̍̂̒͐͛͗̑̏̓̾͌̈̅́̇̕̕̚̚͝͝ͅr̶̛̤̲̘̮̟̭̲̋̾̀́́̒̀̀͑̎̀̌̈̀̍̂̏̊̎͐͒͗͗̀͘͘͘͠͠ȍ̴̧̡̢̡̢̞̝̠̙̬̗͍͍͉̺͔͙̫̝̰̮̜̩̙̳͉̻̻̼͍̊͋͐̐͆̈̿̒̊̄͑̈́̔͋̔̃͐̓̓͛́͊̉͑̊̔͆͘͘͜͠ͅu̴̱̯̞̞̞̺̼̳̳͚̞̇̈͒͠p̶̛͉̮̙̯̮̱͉̖͚͉̩̱̺̩̦̺͈̫͍͔̲̣̗̟̜̂̐̌̏͌̈́͗̾͌̿̓͒̋̆͆̾͛̐̈́̓͋̀͘̚͝͝͝ ̶͔͚̩̬͈̍̈́͗͐̀̊̏͛̃̈́͋̅͝ button" data-testname="div[role=button] ignoring invalid unicode diacritics etc on link and group role tokens" aria-label="x" data-expectedrole="button" class="ex">x</div>
+
+
+ <!-- known el and known role with whitespace edge cases -->
+ <div role=" button" data-testname="div[role=button] ignoring tab char" aria-label="x" data-expectedrole="button" class="ex">x</div>
+ <div role="
+button" data-testname="div[role=button] ignoring line break" aria-label="x" data-expectedrole="button" class="ex">x</div>
+ <div role="⠀ button" data-testname="div[role=button] ignoring braille whitespace char" aria-label="x" data-expectedrole="button" class="ex">x</div>
+
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/form-roles.html b/testing/web-platform/tests/wai-aria/role/form-roles.html
new file mode 100644
index 0000000000..935899c583
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/form-roles.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+<head>
+ <title>Form Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Verifies <a href="https://w3c.github.io/aria/#document-handling_author-errors_roles">9.1 Roles - handling author errors</a> and the <a href="https://w3c.github.io/aria/#form">form</a> role.</p>
+
+
+<!-- no label -->
+<nav role="form" data-testname="form without label" data-expectedrole="navigation" class="ex">x</nav>
+
+<!-- w/ label -->
+<nav role="form" data-testname="form with label" data-expectedrole="form" aria-label="x" class="ex">x</nav>
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/generic-roles.html b/testing/web-platform/tests/wai-aria/role/generic-roles.html
new file mode 100644
index 0000000000..9a67312dd8
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/generic-roles.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<head>
+ <title>Generic Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#generic">generic</a>.</p>
+
+<p role="generic" data-testname="generic role on p element is generic" class="ex-generic">x</p>
+
+<script>
+AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/wai-aria/role/grid-roles.html b/testing/web-platform/tests/wai-aria/role/grid-roles.html
new file mode 100644
index 0000000000..c40771ba9f
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/grid-roles.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Grid Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+ </head>
+ <body>
+
+ <p>Tests <a href="https://w3c.github.io/aria/#grid">grid</a> and related roles.</p>
+
+ <!-- ARIA table roles tested in ./table-roles.html -->
+
+ <div role="grid" data-testname="role is grid" data-expectedrole="grid" class="ex">
+ <div role="row" data-testname="role is row (in grid)" data-expectedrole="row" class="ex">
+ <span role="columnheader" data-testname="role is columnheader (in row, in grid)" data-expectedrole="columnheader" class="ex">x</span>
+ <span role="columnheader">x</span>
+ </div>
+ <div role="row">
+ <span role="rowheader" data-testname="role is rowheader (in row, in grid)" data-expectedrole="rowheader" class="ex">x</span>
+ <span role="gridcell" data-testname="role is gridcell (in row, in grid)" data-expectedrole="gridcell" class="ex">x</span>
+ </div>
+ </div>
+
+ <div role="grid">
+ <div role="rowgroup" data-testname="role is rowgroup (in grid)" data-expectedrole="rowgroup" class="ex">
+ <div role="row" data-testname="role is row (in rowgroup, in grid)" data-expectedrole="row" class="ex">
+ <span role="columnheader" data-testname="role is columnheader (in row, in rowgroup, in grid)" data-expectedrole="columnheader" class="ex">x</span>
+ <span role="columnheader">x</span>
+ <span role="columnheader">x</span>
+ </div>
+ </div>
+ <div role="rowgroup">
+ <div role="row">
+ <span role="rowheader" data-testname="role is rowheader (in row, in rowgroup, in grid)" data-expectedrole="rowheader" class="ex">x</span>
+ <span role="gridcell" data-testname="role is gridcell (in row, in rowgroup, in grid)" data-expectedrole="gridcell" class="ex">x</span>
+ <span role="gridcell">x</span>
+ </div>
+ </div>
+ </div>
+
+ <span role="row" data-testname="orphaned row outside the context of table" class="ex-generic">x</span>
+ <span role="rowgroup" data-testname="orphaned rowgroup outside the context of row" class="ex-generic">x</span>
+ <div role="gridcell" data-testname="orphaned div with gridcell role outside the context of row" class="ex-generic">x</div>
+ <button role="gridcell" data-testname="orphaned button with gridcell role outside the context of row" data-expectedrole="button" class="ex">x</button>
+ <div role="rowheader" data-testname="orphaned rowheader outside the context of row" class="ex-generic">x</div>
+ <div role="columnheader" data-testname="orphaned columnheader outside the context of row" class="ex-generic">x</div>
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/invalid-roles.html b/testing/web-platform/tests/wai-aria/role/invalid-roles.html
new file mode 100644
index 0000000000..3f4255083e
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/invalid-roles.html
@@ -0,0 +1,135 @@
+<!doctype html>
+<html>
+<head>
+ <title>Invalid Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+ <meta charset="utf-8">
+</head>
+<body>
+
+<p>Tests invalid ARIA roles from <a href="https://w3c.github.io/aria/#document-handling_author-errors_roles">9.1 Roles - handling author errors</a>.</p>
+
+<!-- Tests fallback for <nav> when 1/2/3 invalid roles are supplied -->
+<nav role="foo" data-testname="nav with invalid role name foo" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="foo bar" data-testname="nav with two invalid role names" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="foo bar baz" data-testname="nav with three invalid role names" data-expectedrole="navigation" class="ex">x</nav>
+
+<!-- Tests fallback for <button> when 1/2/3 invalid roles are supplied -->
+<button role="foo" data-testname="button with invalid role name foo" data-expectedrole="button" class="ex">x</button>
+<button role="foo bar" data-testname="button with two invalid role names" data-expectedrole="button" class="ex">x</button>
+<button role="foo bar baz" data-testname="button with three invalid role names" data-expectedrole="button" class="ex">x</button>
+
+<!-- Tests fallback for semantically neutral elements when 1/2/3 invalid roles are supplied -->
+<span role="foo" data-testname="span with invalid role name foo" class="ex-generic">x</span>
+<span role="foo bar" data-testname="span with two invalid role names" class="ex-generic">x</span>
+<span role="foo bar baz" data-testname="span with three invalid role names" class="ex-generic">x</span>
+<div role="foo" data-testname="div with invalid role name foo" class="ex-generic">x</div>
+<div role="foo bar" data-testname="div with two invalid role names" class="ex-generic">x</div>
+<div role="foo bar baz" data-testname="div with three invalid role names"class="ex-generic">x</div>
+
+<!-- Whitespace tests with <nav> (including line breaks, tabs, zero-width space, braille space, non-breaking space, standard space) -->
+<nav role=" " data-testname="nav with empty character as role" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="&#13" data-testname="nav with line break (&#13) character as role" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="&#9" data-testname="nav with tab (&#9) as role (should be treated as whitespace)" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="&#8203" data-testname="nav with zero-width space as role (should be treated as whitespace)" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="&#10240" data-testname="nav with braille space (10240) as role" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="&#x2800" data-testname="nav with braille space (x2800) as role" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="&nbsp;" data-testname="nav with non-breaking space (nbsp) as role" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="&#20" data-testname="nav with standard space (nbsp) as role" data-expectedrole="navigation" class="ex">x</nav>
+
+<!-- Escaped whitespace tests with <span> (including line breaks, tabs, zero-width space, braille space, non-breaking space, standard space) -->
+<span role=" " data-testname="span with escaped empty character as role" class="ex-generic">x</span>
+<span role="&#13" data-testname="span with escaped line break (&#13) character as role" class="ex-generic">x</span>
+<span role="&#9" data-testname="span with escaped tab (&#9) as role (should be treated as whitespace)" class="ex-generic">x</span>
+<span role="&#8203" data-testname="span with escaped zero-width space as role (should be treated as whitespace)" class="ex-generic">x</span>
+<span role="&#10240" data-testname="span with escaped braille space (10240) as role" class="ex-generic">x</span>
+<span role="&#x2800" data-testname="span with escaped braille space (x2800) as role" class="ex-generic">x</span>
+<span role="&nbsp;" data-testname="span with escaped non-breaking space (nbsp) as role" class="ex-generic">x</span>
+<span role="&#20" data-testname="span with escaped standard space (nbsp) as role" class="ex-generic">x</span>
+
+<!-- Unescaped whitespace tests with <span> (including line breaks, tabs, zero-width space, braille space, non-breaking space, standard space) -->
+ <span role=" " data-testname="span with empty character as role" class="ex-generic">x</span>
+ <span role="
+ " data-testname="span with line break (&#13) character as role" class="ex-generic">x</span>
+ <span role=" " data-testname="span with tab (&#9) as role (should be treated as whitespace)" class="ex-generic">x</span>
+ <span role="‍" data-testname="span with zero-width space as role (should be treated as whitespace)" class="ex-generic">x</span>
+ <span role="⠀" data-testname="span with braille space (10240) as role" class="ex-generic">x</span>
+ <span role=" " data-testname="span with non-breaking space (nbsp) as role" class="ex-generic">x</span>
+ <span role=" " data-testname="span with standard space as role" class="ex-generic">x</span>
+
+<!-- Diacritics with <a> -->
+<a href="#" role="&#771" data-testname="link with role set to tilde diacritic" data-expectedrole="link" class="ex">x</a>
+<a href="#" role="foo&#771" data-testname="link with role foo that has tilde diacritic" data-expectedrole="link" class="ex">x</a>
+<a href="#" role="&#773" data-testname="link with role set to overline diacritic" data-expectedrole="link" class="ex">x</a>
+<a href="#" role="foo&#773" data-testname="link with role foo that has overline diacritic" data-expectedrole="link" class="ex">x</a>
+<a href="#" role="&#813" data-testname="link with role set to circumflex diacritic below" data-expectedrole="link" class="ex">x</a>
+<a href="#" role="foo&#813" data-testname="link with role foo that has circumflex diacritic below" data-expectedrole="link" class="ex">x</a>
+<a href="#" role="button&#771" data-testname="link with role set to button with tilde diacritic" data-expectedrole="link" class="ex">x</a>
+
+<!-- Diacritics with <div> -->
+<div role="&#771" data-testname="div with role set to tilde diacritic" class="ex-generic">x</div>
+<div role="foo&#771" data-testname="div with role foo that has tilde diacritic" class="ex-generic">x</div>
+<div role="button&#771" data-testname="div with role set to button with tilde diacritic" class="ex-generic">x</div>
+<div role="button´" data-testname="div with role set to button with unescaped tilde diacritic" class="ex-generic">x</div>
+
+<!-- Zero-width joiners (e.g., ZWJ like emoji variants use) with <button> -->
+<!-- [sic] role="‍" should include an invisible ZWJ], and role="link‍" ends with an invisible ZWJ. Use caution when editing. -->
+<button role="‍" data-testname="button with role set to zero-width joiner" data-expectedrole="button" class="ex">x</button>
+<button role="link‍" data-testname="button with role set to foo with zero-width joiner" data-expectedrole="button" class="ex">x</button>
+
+<!-- Non-western chars with <nav> -->
+<nav role="Θ" data-testname="nav with role set to theta (Θ)" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="ژ" data-testname="nav with role set to Persian character (ژ)" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="ژ ♮" data-testname="nav with multiple non-latin character roles, Persian character (ژ) and ♮" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="漢字" data-testname="nav with role set to Japanese kanji" data-expectedrole="navigation" class="ex">x</nav>
+
+<!-- Non-western chars with <span> -->
+<span role="Θ" data-testname="span with role set to theta (Θ)" class="ex-generic">x</span>
+<span role="ژ" data-testname="span with role set to Persian character (ژ)" class="ex-generic">x</span>
+<span role="ژ ♮" data-testname="span with multiple non-latin character roles, Persian character (ژ) and ♮" class="ex-generic">x</span>
+<span role="漢字" data-testname="span with role set to Japanese kanji" class="ex-generic">x</span>
+
+<!-- RTL strings (Hebrew & Arabic) with <nav> -->
+<nav role="سلام" data-testname="nav with role set to Arabic text" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="سلام حبيب" data-testname="nav with multiple role assignments set to Arabic text" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="שלום" data-testname="nav with role set to Hebrew text" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="שלום חבר" data-testname="nav with multiple role assignments set to Hebrew text" data-expectedrole="navigation" class="ex">x</nav>
+
+<!-- RTL strings (Hebrew & Arabic) with <div> -->
+<div role="سلام" data-testname="div with role set to Arabic text" class="ex-generic">x</div>
+<div role="سلام حبيب" data-testname="div with multiple role assignments set to Arabic text" class="ex-generic">x</div>
+<div role="שלום" data-testname="div with role set to Hebrew text" class="ex-generic">x</div>
+<div role="שלום חבר" data-testname="div with multiple role assignments set to Hebrew text" class="ex-generic">x</div>
+
+<!-- Escaped chars, URL-encoded chars with <a> -->
+<a href="https://www.apple.com/" role="&amp" data-testname="link with role set to ampersand character" data-expectedrole="link" class="ex">x</a>
+<a href="https://www.apple.com/" role="&lt" data-testname="link with role set to less than angle bracket character" data-expectedrole="link" class="ex">x</a>
+
+<!-- Escaped chars, URL-encoded chars with <span> -->
+<span role="&amp" data-testname="span with role set to ampersand character" class="ex-generic">x</span>
+<span role="&lt" data-testname="span with role set to less than angle bracket character" class="ex-generic">x</span>
+<span role="&" data-testname="span with role set to unescaped ampersand character" class="ex-generic">x</span>
+<span role="<" data-testname="span with role set to unescaped less than angle bracket character" class="ex-generic">x</span>
+
+<!-- Backslash closing quote and other malformed roles with characters with <nav> -->
+<nav role="region\" data-testname="nav with role set to region followed by backslash" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="\region" data-testname="nav with role set to backslash followed by region" data-expectedrole="navigation" class="ex">x</nav>
+<nav role="re/gion" data-testname="nav with role set to region with backslash after e character" data-expectedrole="navigation" class="ex">x</nav>
+
+<!-- Backslash closing quote and other malformed roles with characters with <span> -->
+<span role="region\" data-testname="span with role set to region followed by backslash" class="ex-generic">x</span>
+<span role="\region" data-testname="span with role set to backslash followed by region" class="ex-generic">x</span>
+<span role="re/gion" data-testname="span with role set to region with forward slash after e character" class="ex-generic">x</span>
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/list-roles.html b/testing/web-platform/tests/wai-aria/role/list-roles.html
new file mode 100644
index 0000000000..71c672c601
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/list-roles.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+<head>
+ <title>List-related Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#list">list</a> and related roles.</p>
+
+<div role="list" data-testname="first simple list" data-expectedrole="list" class="ex">
+ <div role="listitem" data-testname="first simple listitem" data-expectedrole="listitem" class="ex">x</div>
+ <div role="listitem" data-testname="last simple listitem" data-expectedrole="listitem" class="ex">x</div>
+</div>
+
+<div role="listitem" data-testname="orphan div with listitem role" class="ex-generic">x</div>
+<p role="listitem" data-testname="orphan p with listitem role" data-expectedrole="paragraph" class="ex">x</p>
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/listbox-roles.html b/testing/web-platform/tests/wai-aria/role/listbox-roles.html
new file mode 100644
index 0000000000..5020822927
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/listbox-roles.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+<head>
+ <title>Listbox-related Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#listbox">listbox</a> and related roles.</p>
+
+<div role="listbox" data-testname="div role is listbox" data-expectedrole="listbox" class="ex">
+ <div role="option" data-testname="role is option (in div listbox)" data-expectedrole="option" class="ex">x</div>
+ <div role="group" data-testname="role is group (in div listbox)" data-expectedrole="group" class="ex">
+ <span role="option" data-testname="role is option (in group, in div listbox)" data-expectedrole="option" class="ex">x</span>
+ <span role="option">x</span>
+ </div>
+ <div role="option">x</div>
+</div>
+
+<ul role="listbox" data-testname="ul role is listbox" data-expectedrole="listbox" class="ex">
+ <li role="option" data-testname="li role is option (in ul listbox)" data-expectedrole="option" class="ex">
+ x
+ </li>
+ <li role="option">
+ x
+ </li>
+</ul>
+
+<nav role="option" data-testname="orphaned option outside the context of listbox" data-expectedrole="navigation"
+ class="ex">x
+</nav>
+
+<script>
+ AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/menu-roles.html b/testing/web-platform/tests/wai-aria/role/menu-roles.html
new file mode 100644
index 0000000000..4af4d8d2ff
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/menu-roles.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<html>
+<head>
+ <title>Menu-related Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<style>
+ /* Typically horizontal */
+ [role="menubar"] {
+ display: flex;
+ }
+</style>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#menu">menu</a> and related roles.</p>
+
+<div role="menu" data-testname="role is menu" data-expectedrole="menu" class="ex">
+ <div role="menuitem" data-testname="role is menuitem (in menu)" data-expectedrole="menuitem" class="ex">x</div>
+ <div role="menuitem">x</div>
+ <div role="menuitem">x</div>
+ <div role="group" data-testname="role is group (in menu)" data-expectedrole="group" class="ex">
+ <div role="menuitem" data-testname="role is menuitem (in group, in menu)" data-expectedrole="menuitem" class="ex">x</div>
+ <div role="menuitem">x</div>
+ </div>
+ <div role="group">
+ <div role="menuitemradio" aria-checked="true" data-testname="role is menuitemradio (in group, in menu)" data-expectedrole="menuitemradio" class="ex">x</div>
+ <div role="menuitemradio">x</div>
+ </div>
+ <div role="group">
+ <div role="menuitemcheckbox" aria-checked="true" data-testname="role is menuitemcheckbox (in group, in menu)" data-expectedrole="menuitemcheckbox" class="ex">x</div>
+ <div role="menuitemcheckbox">x</div>
+ </div>
+</div>
+
+<div role="menubar" data-testname="role is menubar" data-expectedrole="menubar" class="ex">
+ <div role="menuitem" data-testname="role is menuitem (in menubar)" data-expectedrole="menuitem" class="ex">x</div>
+ <div role="menuitem">x</div>
+ <div role="menuitem">x</div>
+ <div role="group" data-testname="role is group (in menubar)" data-expectedrole="group" class="ex">
+ <div role="menuitem" data-testname="role is menuitem (in group, in menubar)" data-expectedrole="menuitem" class="ex">x</div>
+ <div role="menuitem">x</div>
+ </div>
+ <div role="group">
+ <div role="menuitemradio" aria-checked="true" data-testname="role is menuitemradio (in group, in menubar)" data-expectedrole="menuitemradio" class="ex">x</div>
+ <div role="menuitemradio">x</div>
+ </div>
+ <div role="group">
+ <div role="menuitemcheckbox" aria-checked="true" data-testname="role is menuitemcheckbox (in group, in menubar)" data-expectedrole="menuitemcheckbox" class="ex">x</div>
+ <div role="menuitemcheckbox">x</div>
+ </div>
+</div>
+
+<nav role="menuitem" data-testname="orphaned menuitem outside the context of menu/menubar" data-expectedrole="navigation"
+ class="ex">x
+</nav>
+<nav role="menuitemradio" data-testname="orphaned menuitemradio outside the context of menu/menubar" data-expectedrole="navigation"
+ class="ex">x
+</nav>
+<nav role="menuitemcheckbox" data-testname="orphaned menuitemcheckbox outside the context of menu/menubar" data-expectedrole="navigation"
+ class="ex">x
+</nav>
+
+<button role="menuitem" data-testname="orphan button with menuitem role" data-expectedrole="button" class="ex">x</button>
+<div role="menuitem" data-testname="orphan div with menuitem role" class="ex-generic">x</div>
+
+<button role="menuitemcheckbox" data-testname="orphan button with menuitemcheckbox role" data-expectedrole="button" class="ex">x</button>
+<div role="menuitemcheckbox" data-testname="orphan div with menuitemcheckbox role" class="ex-generic">x</div>
+
+<button role="menuitemradio" data-testname="orphan button with menuitemradio role" data-expectedrole="button" class="ex">x</button>
+<div role="menuitemradio" data-testname="orphan div with menuitemradio role" class="ex-generic">x</div>
+
+<script>
+ AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/region-roles.html b/testing/web-platform/tests/wai-aria/role/region-roles.html
new file mode 100644
index 0000000000..d80570a97b
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/region-roles.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+<head>
+ <title>Region Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#region">region</a> and related roles, as well as the "name from author" rule in <a href="https://w3c.github.io/aria/#document-handling_author-errors_roles">9.1 Roles - handling author errors</a>.</p>
+
+<!-- no label -->
+<nav role="region" data-testname="region without label" data-expectedrole="navigation" class="ex">x</nav>
+
+<!-- w/ label -->
+<nav role="region" data-testname="region with label" data-expectedrole="region" aria-label="x" class="ex">x</nav>
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/role_none_conflict_resolution.html b/testing/web-platform/tests/wai-aria/role/role_none_conflict_resolution.html
new file mode 100644
index 0000000000..9e2ee6ccfe
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/role_none_conflict_resolution.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+<head>
+ <title>Role None Conflict Resolution Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Verifies <a href="https://w3c.github.io/aria/#conflict_resolution_presentation_none"></a>conflict resolution</a> requirements for the ARIA <a href="https://w3c.github.io/aria/#none">none</a> and <a href="https://w3c.github.io/aria/#presentation">presentation</a> roles.</p>
+
+<!-- none with label(global) on header -->
+<h1 role="none" data-testname="heading role none with global attr aria-label" data-expectedrole="heading" aria-label="x" class="ex">x</h1>
+
+<!-- none with label(global) on paragraph -->
+<p role="none" data-testname="p role none with global attr aria-label (prohibited role)" data-expectedrole="paragraph" aria-label="x" class="ex">x</p>
+<p role="none" data-testname="p role none without global attr aria-label (prohibited role)" class="ex-generic">x</p>
+
+<!-- none with focusable header -->
+<h1 role="none" data-testname="focusable heading role none with tabindex=0" data-expectedrole="heading" tabindex="0" class="ex">x</h1>
+<h1 role="none" data-testname="focusable heading role none with tabindex=-1" data-expectedrole="heading" tabindex="-1" class="ex">x</h1>
+<h1 role="none" data-testname="non-focusable heading role none" class="ex-generic">x</h1>
+
+<!-- none with non-global-->
+<h1 role="none" data-testname="none with non-global" class="ex-generic" aria-level="2"> Sample Content </h1>
+
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/roles.html b/testing/web-platform/tests/wai-aria/role/roles.html
new file mode 100644
index 0000000000..844da3ce47
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/roles.html
@@ -0,0 +1,140 @@
+<!doctype html>
+<html>
+<head>
+ <title>Simple Core ARIA Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests most <a href="https://w3c.github.io/aria/#role_definitions">ARIA role definitions</a>. See comments for more info.</p>
+
+<script>
+
+/*
+
+Tests simple role assignment: <div role="alert">x</div>
+
+- Nested role structures (table>row>cell, etc) and
+ Abstract roles (e.g. widget, composite) are
+ commented with pointers to a separate test file.
+
+- ARIA extension specs (e.g. doc-*, graphics-*) are
+ commented with pointers to a separate spec directory.
+
+*/
+
+AriaUtils.assignAndVerifyRolesByRoleNames([
+ "alert",
+ "alertdialog",
+ "application",
+ "article",
+ // "associationlist" [AT-RISK: ARIA #1662] or possibly -> ./list-roles.html
+ // "associationlistitemkey" [AT-RISK: ARIA #1662] or possibly -> ./list-roles.html
+ // "associationlistitemvalue" [AT-RISK: ARIA #1662] or possibly -> ./list-roles.html
+ "banner",
+ "blockquote",
+ "button",
+ "caption",
+ // "cell" -> ./grid-roles.html
+ "checkbox",
+ "code",
+ // "columnheader" -> ./grid-roles.html
+ "combobox",
+ // "command" -> ./abstract-roles.html
+ // "comment" -> [AT-RISK: ARIA #1885]
+ "complementary",
+ // "composite" -> ./abstract-roles.html
+ "contentinfo",
+ "definition",
+ "deletion",
+ "dialog",
+ // "directory" -> FAIL. WONTFIX. Deprecated in ARIA 1.2; re-mapped to list role.
+ "document",
+ // doc-* roles -> TBD /dpub-aria or /dpub-aam
+ "emphasis",
+ "feed",
+ "figure",
+ // form -> ./form-roles.html
+ "generic",
+ // graphics-* roles -> /graphics-aria
+ // "grid" -> ./grid-roles.html
+ // "gridcell" -> ./grid-roles.html
+ "group",
+ "heading",
+ // "image" -> ./synonym-roles.html
+ // "img" -> ./synonym-roles.html
+ // "input" -> ./abstract-roles.html
+ "insertion",
+ // "landmark" -> ./abstract-roles.html
+ "link",
+ // "list" -> ./list-roles.html
+ // "listitem" -> ./list-roles.html
+ // "listitemkey" [See: ARIA #1662] or possibly -> ./list-roles.html
+ // "listitemvalue" [See: ARIA #1662] or possibly -> ./list-roles.html
+ // "listbox" -> ./listbox-roles.html
+ "log",
+ "main",
+ "marquee",
+ "math",
+ // "menu" -> ./menu-roles.html
+ // "menuitem" -> ./menu-roles.html
+ // "menuitemcheckbox" -> ./menu-roles.html
+ // "menuitemradio" -> ./menu-roles.html
+ // "menubar" -> ./menu-roles.html
+ "meter",
+ "navigation",
+ // "none" -> ./synonym-roles.html
+ "note",
+ // "option" -> ./listbox-roles.html
+ "paragraph",
+ // "presentation" -> ./synonym-roles.html
+ "progressbar",
+ "radio",
+ "radiogroup",
+ // "range" -> ./abstract-roles.html
+ // "region" -> ./region-roles.html
+ // "roletype" -> ./abstract-roles.html
+ // "row" -> ./grid-roles.html
+ // "rowgroup" -> ./grid-roles.html
+ // "rowheader" -> ./grid-roles.html
+ "scrollbar",
+ "search",
+ "searchbox",
+ // "section" -> ./abstract-roles.html
+ // "sectionhead" -> ./abstract-roles.html
+ // "select" -> ./abstract-roles.html
+ "separator",
+ "slider",
+ "spinbutton",
+ "status",
+ "strong",
+ // "structure" -> ./abstract-roles.html
+ "subscript",
+ "suggestion",
+ "superscript",
+ "switch",
+ // "tab" -> ./tab-roles.html
+ // "table" -> ./grid-roles.html
+ // "tablist" -> ./tab-roles.html
+ // "tabpanel" -> ./tab-roles.html
+ "term",
+ "textbox",
+ "time",
+ "timer",
+ "toolbar",
+ "tooltip",
+ // "tree" -> ./tree-roles.html
+ // "treeitem" -> ./tree-roles.html
+ // "treegrid" -> ./treegrid-roles.html
+ // "widget" -> ./abstract-roles.html
+ // "window" -> ./abstract-roles.html
+]);
+
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/synonym-roles.html b/testing/web-platform/tests/wai-aria/role/synonym-roles.html
new file mode 100644
index 0000000000..f9d3d7d0a9
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/synonym-roles.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<head>
+ <title>Region Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests synonym roles image/img and none/presentation via <a href="https://w3c.github.io/core-aam/#roleMappingComputedRole">Core-AAM Computed Role</a>.</p>
+
+<!-- spec resolution https://github.com/w3c/core-aam/issues/166 -->
+
+<div role="none" id="none" data-testname="none role == computedrole none" class="ex-generic">x</div><!-- preferred -->
+<div role="presentation" id="presentation" data-testname="synonym presentation role == computedrole none" class="ex-generic">x</div><!-- synonym -->
+
+<div role="image" id="image" data-expectedrole="image" data-testname="image role == computedrole image" class="ex">x</div><!-- preferred -->
+<div role="img" id="img" data-expectedrole="image" data-testname="synonym img role == computedrole image" class="ex">x</div><!-- synonym -->
+
+<!-- `directory` synonym deprecated in ARIA 1.2; these examples should all return computedrole `list` -->
+<ul role="list" id="list2" data-expectedrole="list" data-testname="list role == computedrole list" class="ex"><li>x</li></ul>
+<ul role="directory" id="directory" data-expectedrole="list" data-testname="directory role == computedrole list" class="ex"><li>x</li></ul>
+<div role="directory" id="div" data-expectedrole="list" data-testname="div w/directory role == computedrole list" class="ex"><div role="listitem">x</div></div>
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/tab-roles.html b/testing/web-platform/tests/wai-aria/role/tab-roles.html
new file mode 100644
index 0000000000..e3d14741c8
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/tab-roles.html
@@ -0,0 +1,94 @@
+<!doctype html>
+<html>
+<head>
+ <title>Tab-related Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#tab">tab</a> and related roles.</p>
+
+<!--<div> tab with tablist/tab/tabpanel semantics-->
+<div role="tablist" data-testname="div role is tablist" data-expectedrole="tablist" class="ex">
+ <div role="tab" data-testname="role is tab (in div tablist)" data-expectedrole="tab" class="ex">x</div>
+</div>
+<div role="tabpanel" data-testname="role is tabpanel (with sibling div tablist)" data-expectedrole="tabpanel" class="ex"></div>
+
+<!--<div> tabs with tablist/tab/tabpanel semantics, selection, no focus management-->
+<div role="tablist" data-testname="div role is tablist (with selection)" data-expectedrole="tablist" class="ex">
+ <div role="tab" aria-selected="true" data-testname="role is tab and tab is selected" data-expectedrole="tab" class="ex">x</div>
+ <div role="tab" aria-selected="false" data-testname="role is tab and tab is not selected" data-expectedrole="tab" class="ex">y</div>
+</div>
+<div role="tabpanel" data-testname="role is tabpanel (faux selected)" data-expectedrole="tabpanel" class="ex"></div>
+<div role="tabpanel" data-testname="role is tabpanel (faux unselected)" data-expectedrole="tabpanel" class="ex"></div>
+
+<!--<div> tabs with tablist/tab/tabpanel semantics, selection, roving tabindex-->
+<div role="tablist" data-testname="div role is tablist (with selection, roving tabindex)" data-expectedrole="tablist" class="ex">
+ <div role="tab" aria-selected="true" tabindex = "0" data-testname="role is tab, tab is selected and in tab order" data-expectedrole="tab" class="ex">x</div>
+ <div role="tab" aria-selected="false" tabindex = "-1" data-testname="role is tab and tab is not selected, not tabbable" data-expectedrole="tab" class="ex">y</div>
+ <div role="tab" aria-selected="false" tabindex = "-1" data-testname="role is tab and tab is not selected, not tabbable (duplicate)" data-expectedrole="tab" class="ex">z</div>
+</div>
+<div role="tabpanel" data-testname="role is tabpanel with selection, roving tabindex" data-expectedrole="tabpanel" class="ex"></div>
+<div role="tabpanel" data-testname="role is tabpanel with selection, roving tabindex (duplicate)" data-expectedrole="tabpanel" class="ex"></div>
+<div role="tabpanel" data-testname="role is tabpanel with selection, roving tabindex (duplicate 2)" data-expectedrole="tabpanel" class="ex"></div>
+
+<!--<div> tabs with tablist/tab/tabpanel semantics and non-empty tabpanel-->
+<div role="tablist" data-testname="div role is tablist (with non-empty tabpanel)" data-expectedrole="tablist" class="ex">
+ <div role="tab" aria-selected="true" data-testname="role is tab and tab is selected (with non-empty tabpanel content)" data-expectedrole="tab" class="ex">x</div>
+ <div role="tab" aria-selected="false" data-testname="role is tab and tab is not selected (with non-empty tabpanel content)" data-expectedrole="tab" class="ex">y</div>
+</div>
+<div role="tabpanel" data-testname="role is tabpanel with selection, non-empty content" data-expectedrole="tabpanel" class="ex">Tab one's stuff</div>
+<div role="tabpanel" data-testname="role is tabpanel with selection, non-empty content (duplicate)" data-expectedrole="tabpanel" class="ex">Tab two's stuff</div>
+
+<!--<div> tabs with tablist/tab/tabpanel semantics, non-empty tabpanel and aria-controls-->
+<div role="tablist" data-testname="div role is tablist (with non-empty tabpanel and aria-controls)" data-expectedrole="tablist" class="ex">
+ <div role="tab" aria-controls = "tabpanel1" aria-selected="true" data-testname="role is tab, tab is selected (with aria-controls)" data-expectedrole="tab" class="ex">x</div>
+ <div role="tab" aria-controls = "tabpanel2" aria-selected="false" data-testname="role is tab, tab is not selected (with aria-controls)" data-expectedrole="tab" class="ex">y</div>
+</div>
+<div role="tabpanel" id="tabpanel1" data-testname="role is tabpanel with aria-controls and non-empty content" data-expectedrole="tabpanel" class="ex">Tab one's stuff</div>
+<div role="tabpanel" id="tabpanel2" data-testname="role is tabpanel with aria-controls and non-empty content (duplicate)" data-expectedrole="tabpanel" class="ex">Tab one's stuff</div>
+
+<!--<div> tablist with child <button> that has explicit role="tab"-->
+<div role="tablist" data-testname="div role for button parent container is tablist" data-expectedrole="tablist" class="ex">
+ <button role="tab" data-testname="button role is tab (in div tablist)" data-expectedrole="tab" class="ex">x</div>
+</div>
+
+<!--<ul> tablist with child <divs> that have explicit role="tab"-->
+<ul role="tablist" data-testname="ul role is tablist" data-expectedrole="tablist" class="ex">
+ <li>
+ <div role="tab" aria-selected="true" tabindex = "0" data-testname="role is tab (within li), tab is selected and in tab order" data-expectedrole="tab" class="ex">x</div>
+ </li>
+ <li>
+ <div role="tab" aria-selected="false" tabindex = "-1" data-testname="role is tab (within li), tab is not selected and in tab order" data-expectedrole="tab" class="ex">y</div>
+ </li>
+</ul>
+<div role="tabpanel" data-testname="role is tabpanel as sibling to ul" data-expectedrole="tabpanel" class="ex">Tab one's stuff</div>
+<div role="tabpanel" data-testname="role is tabpanel as sibling to ul (duplicate)" data-expectedrole="tabpanel" class="ex">Tab two's stuff</div>
+
+<!--<ul> tablist with child <divs> that have explicit role="tab", role="none" on li elements-->
+ <ul role="tablist" data-testname="ul role is tablist (child li have role none)" data-expectedrole="tablist" class="ex">
+ <li role="none">
+ <div role="tab" aria-selected="true" tabindex = "0" data-testname="role is tab (within li with role none), tab is selected and in tab order" data-expectedrole="tab" class="ex">x</div>
+ </li>
+ <li role="none">
+ <div role="tab" aria-selected="false" tabindex = "-1" data-testname="role is tab (within li with role none), tab is not selected and in tab order" data-expectedrole="tab" class="ex">y</div>
+ </li>
+ </ul>
+ <div role="tabpanel" data-testname="role is tabpanel as sibling to ul with child role none li elements" data-expectedrole="tabpanel" class="ex">Tab one's stuff</div>
+ <div role="tabpanel" data-testname="role is tabpanel as sibling to ul with child role none li elements (duplicate)" data-expectedrole="tabpanel" class="ex">Tab two's stuff</div>
+
+<!--orphan tab semantics -->
+<button role="tab" data-testname="orphan button with tab role" data-expectedrole="button" class="ex">x</button>
+<span role="tab" data-testname="orphan span with tab role" class="ex-generic">x</span>
+
+<script>
+ AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/table-roles.html b/testing/web-platform/tests/wai-aria/role/table-roles.html
new file mode 100644
index 0000000000..6ffb94218d
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/table-roles.html
@@ -0,0 +1,156 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Table Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+ </head>
+<body>
+ <p>Tests <a href="https://w3c.github.io/aria/#table">table</a> and related roles.</p>
+
+<!-- HTML <table> Elements Testing -->
+
+ <!-- <caption> -> wpt/html-aam/table-roles.html -->
+
+ <!-- <table> -> wpt/html-aam/table-roles.html -->
+ <!-- <tbody> -> wpt/html-aam/table-roles.html -->
+
+ <!-- <td> -> wpt/html-aam/table-roles.html -->
+
+ <!-- <tfoot> -> wpt/html-aam/table-roles.html -->
+
+ <!-- <th> -> wpt/html-aam/table-roles.html -->
+ <!-- <thead> -> wpt/html-aam/table-roles.html -->
+
+ <!-- <tr> -> wpt/html-aam/table-roles.html -->
+
+
+<!-- ARIA Grid Elements Testing -->
+
+ <!-- Grid roles tested in ./grid-roles.html -->
+
+
+<!-- ARIA Table Roles Testing -->
+
+ <!-- caption -->
+ <div role="table">
+ <div role="caption" data-testname="div role is caption (in div with table role)" data-expectedrole="caption" class="ex">x</div>
+ </div>
+
+ <p role="caption" data-testname="orphan p role is caption" data-expectedrole="caption" class="ex">x</p>
+
+ <!-- cell -->
+ <div role="table">
+ <div role="rowgroup">
+ <div role="row">
+ <span role="columnheader">x</span>
+ <span role="columnheader">x</span>
+ </div>
+ </div>
+ <div role="rowgroup">
+ <div role="row">
+ <span role="cell" data-testname="span role is cell (in div with row role, in div with rowgroup role, in div with table role)" data-expectedrole="cell" class="ex">x</span>
+ <span role="cell">x</span>
+ </div>
+ </div>
+ </div>
+
+ <span role="cell" data-testname="orphan span role is cell" data-expectedrole="cell" class="ex">x</span>
+
+ <!-- columnheader -->
+ <div role="table">
+ <div role="rowgroup">
+ <div role="row">
+ <span role="columnheader" data-testname="span role is columnheader (in div with row role, in div with rowgroup role, in div with table role)" data-expectedrole="columnheader" class="ex">x</span>
+ <span role="columnheader">x</span>
+ <span role="columnheader">x</span>
+ </div>
+ </div>
+ <div role="rowgroup">
+ <div role="row">
+ <span role="rowheader">x</span>
+ <span role="cell">x</span>
+ <span role="cell">x</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- columnheader, orphaned -> ./grid-roles.html -->
+
+ <!-- row -->
+ <div role="table">
+ <div role="rowgroup">
+ <div role="row" data-testname="div role is row (in div with rowgroup role, in div with table role)" data-expectedrole="row" class="ex">
+ <span role="columnheader">x</span>
+ </div>
+ </div>
+ <div role="rowgroup">
+ <div role="row">
+ <span role="cell">x</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- row, orphaned -> ./grid-roles.html -->
+
+ <!-- rowgroup -->
+ <div role="table">
+ <div role="rowgroup" data-testname="div role is rowgroup (in div with table role)" data-expectedrole="rowgroup" class="ex">
+ <div role="row">
+ <span role="columnheader">x</span>
+ <span role="columnheader">x</span>
+ </div>
+ </div>
+ <div role="rowgroup">
+ <div role="row">
+ <span role="cell">x</span>
+ <span role="cell">x</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- rowgroup, orphaned -> ./grid-roles.html -->
+
+ <!-- rowheader -->
+ <div role="table">
+ <div role="rowgroup">
+ <div role="row">
+ <span role="columnheader">x</span>
+ <span role="columnheader">x</span>
+ <span role="columnheader">x</span>
+ </div>
+ </div>
+ <div role="rowgroup">
+ <div role="row">
+ <span role="rowheader" data-testname="role is rowheader (in div with row role, in div with rowgroup role, in div with table role)" data-expectedrole="rowheader" class="ex">x</span>
+ <span role="cell">x</span>
+ <span role="cell">x</span>
+ <span role="cell">x</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- rowheader, orphaned -> ./grid-roles.html -->
+
+ <!-- table -->
+ <div role="table" data-testname="div role is table" data-expectedrole="table" class="ex">
+ <div role="row">
+ <span role="columnheader">x</span>
+ <span role="columnheader">x</span>
+ </div>
+ <div role="row">
+ <span role="cell">x</span>
+ <span role="cell">x</span>
+ </div>
+ </div>
+
+<script>
+ AriaUtils.verifyRolesBySelector(".ex");
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/wai-aria/role/tree-roles.html b/testing/web-platform/tests/wai-aria/role/tree-roles.html
new file mode 100644
index 0000000000..eb1084040d
--- /dev/null
+++ b/testing/web-platform/tests/wai-aria/role/tree-roles.html
@@ -0,0 +1,150 @@
+<!doctype html>
+<html>
+<head>
+ <title>Tree related Role Verification Tests</title>
+ <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>
+ <script src="/wai-aria/scripts/aria-utils.js"></script>
+</head>
+<style>
+ /* Hide collapsed rows */
+ [role="treegrid"] tr.hidden {
+ display: none;
+ }
+
+ /* Indents */
+ [role="treegrid"] tr[aria-level="2"] > td:first-child {
+ padding-left: 2ch;
+ }
+
+ [role="treegrid"] tr[aria-level="3"] > td:first-child {
+ padding-left: 4ch;
+ }
+
+ /* Collapse/expand icons */
+ [role="treegrid"] tr > td:first-child::before {
+ content: "";
+ display: inline-block;
+ width: 2ch;
+ height: 11px;
+ transition: transform 0.3s;
+ transform-origin: 5px 5px;
+ }
+
+ [role="treegrid"] tr[aria-expanded] > td:first-child::before,
+ [role="treegrid"] td[aria-expanded]:first-child::before {
+ cursor: pointer;
+
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpolygon fill='black' points='2,0 2,10 10,5'%3E%3C/polygon%3E%3C/svg%3E%0A");
+ background-repeat: no-repeat;
+ }
+
+ [role="treegrid"] tr[aria-expanded="true"] > td:first-child::before,
+ [role="treegrid"] td[aria-expanded="true"]:first-child::before {
+ transform: rotate(90deg);
+ }
+</style>
+<body>
+
+<p>Tests <a href="https://w3c.github.io/aria/#tree">tree</a> and related roles.</p>
+
+<ul role="tree" data-testname="role is tree" data-expectedrole="tree" class="ex">
+ <li role="treeitem" data-testname="role is treeitem (in tree)" data-expectedrole="treeitem" class="ex">
+ x
+ <ul role="group" data-testname="role is group (in treeitem)" data-expectedrole="group" class="ex">
+ <li role="treeitem" data-testname="role is treeitem (in group, in treeitem)" data-expectedrole="treeitem" class="ex">x</li>
+ <li role="treeitem">x</li>
+ </ul>
+ </li>
+ <li role="treeitem">x</li>
+</ul>
+
+<table role="treegrid" data-testname="role is treegrid" data-expectedrole="treegrid" class="ex">
+ <tbody>
+ <tr role="row" aria-expanded="true" aria-level="1" aria-posinset="1" aria-setsize="2" data-testname="role is row (in treegrid)" data-expectedrole="row" class="ex expander">
+ <td role="gridcell" data-testname="role is gridcell (in row, in treegrid)" data-expectedrole="gridcell" class="ex">x</td>
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ </tr>
+ <tr role="row" aria-level="2" aria-posinset="1" aria-setsize="2">
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ </tr>
+ <tr aria-expanded="false" aria-level="2" aria-posinset="2" aria-setsize="2" role="row" class="expander">
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ </tr>
+ <tr role="row" aria-level="3" aria-posinset="1" aria-setsize="1" class="hidden">
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ </tr>
+ <tr role="row" aria-expanded="false" aria-level="1" aria-posinset="2" aria-setsize="2" class="expander">
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ </tr>
+ <tr role="row" aria-level="2" aria-posinset="1" aria-setsize="2" class="hidden">
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ </tr>
+ <tr role="row" aria-level="2" aria-posinset="1" aria-setsize="2" class="hidden">
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ <td role="gridcell">x</td>
+ </tr>
+ </tbody>
+</table>
+
+<nav role="treeitem" data-testname="orphaned treeitem outside the context of tree" data-expectedrole="navigation" class="ex">x</nav>
+<button role="treeitem" data-testname="orphaned button with treeitem role outside tree context" data-expectedrole="button" class="ex">x</button>
+
+<script>
+ AriaUtils.verifyRolesBySelector(".ex");
+
+ const expanders = document.querySelectorAll(".expander");
+ expanders.forEach((expander) => {
+ expander.addEventListener("click", () => {
+
+ const expanderLevel = parseInt(expander.getAttribute("aria-level"))
+ let nextSibling = expander.nextElementSibling;
+
+ // Toggle aria-expanded for the row being expanded
+ let isExpanding = expander.getAttribute("aria-expanded") !== "true";
+ expander.setAttribute("aria-expanded", isExpanding.toString());
+
+ while (nextSibling) {
+ const nextSiblingLevel = parseInt(nextSibling.getAttribute("aria-level"));
+
+ // Don't expand rows found on the same level
+ if (nextSiblingLevel === expanderLevel) nextSibling = null;
+
+ if (isExpanding) {
+ // Don't expand rows beyond the next level if an ".expander" row is found as the nextSibling
+ if (nextSiblingLevel - expanderLevel === 1) {
+ nextSibling.classList.remove("hidden");
+ // Don't expand sub rows found
+ if (nextSibling.hasAttribute("aria-expanded")) nextSibling.setAttribute("aria-expanded", "false");
+ }
+ } else {
+ // Only expand rows that are more "indented" than the ".expander" row. A higher aria-level indicates a
+ // higher "level"
+ if (nextSiblingLevel > expanderLevel) {
+ nextSibling.classList.add("hidden");
+ }
+ }
+
+ nextSibling = nextSibling.nextElementSibling;
+ }
+ });
+ });
+</script>
+
+</body>
+</html> \ No newline at end of file