diff --git a/internal/driver/chrome/driver.go b/internal/driver/chrome/driver.go index 97498ee..074cae3 100644 --- a/internal/driver/chrome/driver.go +++ b/internal/driver/chrome/driver.go @@ -413,8 +413,13 @@ func (d *Driver) Hierarchy(ctx context.Context) (string, error) { visit(document); return out; } + const TAPPABLE_ROLES = [ + 'button', 'link', 'checkbox', 'radio', 'switch', 'tab', 'option', + 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'treeitem']; const clickableSet = new Set(deepQuery( - 'a, button, input, select, textarea, [role="button"], [onclick]')); + 'a, button, input, select, textarea, ' + + TAPPABLE_ROLES.map(role => '[role="' + role + '"]').join(', ') + + ', [onclick]')); const editableSet = new Set(deepQuery( 'input, textarea, [contenteditable]').filter(isEditableElement)); function buildTree(el, isRoot) { diff --git a/internal/driver/chrome/testdata/fact-parity.html b/internal/driver/chrome/testdata/fact-parity.html index dba230a..c29d0ed 100644 --- a/internal/driver/chrome/testdata/fact-parity.html +++ b/internal/driver/chrome/testdata/fact-parity.html @@ -56,6 +56,22 @@
bio
+ + + + +
switch
+ + +
menu item checkbox
+
menu item radio
+
tree item
+
attribute click
delegating root
plain
diff --git a/pkg/spec/src/web-runtime.ts b/pkg/spec/src/web-runtime.ts index 244bc34..5e4b89b 100644 --- a/pkg/spec/src/web-runtime.ts +++ b/pkg/spec/src/web-runtime.ts @@ -569,7 +569,22 @@ function sanitizeAt(value: unknown, depth: number, seen: WeakSet): unkno // only how the DOM answers "is this clickable" / "is this editable", the two // facts with no direct DOM equivalent of the accessibility attributes native // platforms expose. -const TAPPABLE_SELECTOR = 'a, button, input, select, textarea, [role="button"], [onclick]'; +// +// TAPPABLE_ROLES are the ARIA roles whose whole contract is that a user +// activates the element. Covering only role="button" left every other one +// invisible to the enumeration, however plain the control looked: the replay UI +// builds its step rows as
  • , and the spec dogfooding it had to +// hand-write an action to reach them because no default verb could see a single +// row. internal/driver/chrome/driver.go resolves the same set for the hierarchy +// dump the goja host reads, and the two are compared element by element by +// TestHierarchy_DerivesTheSameFactsAsTheWebRuntime. +const TAPPABLE_ROLES = [ + "button", "link", "checkbox", "radio", "switch", "tab", "option", + "menuitem", "menuitemcheckbox", "menuitemradio", "treeitem", +]; +const TAPPABLE_SELECTOR = `a, button, input, select, textarea, ${ + TAPPABLE_ROLES.map((role) => `[role="${role}"]`).join(", ") +}, [onclick]`; const EDITABLE_SELECTOR = "input, textarea, [contenteditable]"; const NON_TEXT_INPUT_TYPES = [