Skip to content

feat: add page.accessibility CDP domain API#595

Open
myabc wants to merge 1 commit into
rubycdp:mainfrom
myabc:feature/accessibility
Open

feat: add page.accessibility CDP domain API#595
myabc wants to merge 1 commit into
rubycdp:mainfrom
myabc:feature/accessibility

Conversation

@myabc

@myabc myabc commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Problem

Reading an element's computed accessibility properties (role, name, description, ARIA state) under Ferrum means reaching past the public API into raw CDP:

page.command("Accessibility.getPartialAXTree",
  nodeId: node.node_id, fetchRelatives: false)["nodes"]

This leaks the CDP wire shape into callers, is undiscoverable, and leaves no home for the rest of the Accessibility domain.

Fix

Add a first-class page.accessibility domain object, mirroring Ferrum::Network:

  • node_for, partial_tree, snapshot, query, root, enable/disable. Node-scoped commands run on the node's own page, so they resolve correctly across same-process iframes.
  • Ferrum::Accessibility::AXNode value object wraps a CDP AXNode: role, name, description, value, properties, ignored?, ignored_reasons, node_id, backend_dom_node_id, child_ids, to_h. Params are deep-frozen; value is untyped since CDP AXValue.value may be a string, number, or boolean.
  • Ferrum::Node#axnode convenience, mirroring #computed_style.

Query commands work without Accessibility.enable (that governs live events only); enable/disable are thin wrappers. root uses getFullAXTree(depth: 1) and query falls back to the document root node id, because CDP getRootAXNode/queryAXTree require those respectively.

Testing

RBS signatures plus unit and browser-driven specs, including subtree-scoping proof and same-process iframe coverage for node_for, partial_tree, and query. CHANGELOG updated.

Downstream validation

🤖 Validated against a real consumer: capybara_accessible_selectors#157 (Cuprite driver support) resolves computed name/role/description from the accessibility tree.

Swapping its hand-rolled Accessibility.getPartialAXTree + ignored-node filtering + hash-digging for node.axnode&.name / .role / .description removed the raw-CDP coupling entirely. Full suite green on Cuprite — 1813 examples, 0 failures.

Before:

nodes = node.page.command("Accessibility.getPartialAXTree",
                          nodeId: node.node_id, fetchRelatives: false)["nodes"]
Array(nodes).find { |n| n["ignored"] == false }&.dig("name", "value")

After:

node.axnode&.name

Copilot AI review requested due to automatic review settings June 27, 2026 20:09
@myabc myabc changed the title Add page.accessibility CDP domain API feat: add page.accessibility CDP domain API Jun 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a first-class page.accessibility domain API for interacting with Chrome DevTools Protocol (CDP) Accessibility domain data through Ferrum, plus a Node#axnode convenience accessor and accompanying RBS + specs.

Changes:

  • Add Ferrum::Accessibility (domain wrapper) and Ferrum::Accessibility::AXNode (value object) to encapsulate CDP Accessibility queries.
  • Expose the API via Page#accessibility, Browser#accessibility delegation, and Node#axnode.
  • Add unit + browser-driven specs, test fixture pages, and update RBS + CHANGELOG.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
spec/unit/accessibility/ax_node_spec.rb Adds unit coverage for AXNode behavior and immutability.
spec/support/views/accessibility.erb Adds a fixture page for accessibility tree querying tests.
spec/support/views/accessibility_iframe.erb Adds an iframe fixture page for cross-frame accessibility tests.
spec/support/views/accessibility_iframe_child.erb Adds iframe child content for frame-resident node accessibility tests.
spec/node_spec.rb Adds integration coverage for Node#axnode.
spec/accessibility_spec.rb Adds browser-driven coverage for page.accessibility APIs (node_for/partial_tree/query/root/value, incl. iframe).
sig/ferrum/page.rbs Exposes Page#accessibility in RBS.
sig/ferrum/node.rbs Exposes Node#axnode in RBS.
sig/ferrum/accessibility/ax_node.rbs Adds RBS signature for Accessibility::AXNode.
sig/ferrum/accessibility.rbs Adds RBS signature for Ferrum::Accessibility.
lib/ferrum/page.rb Wires Accessibility into Page initialization and adds accessor docs.
lib/ferrum/node.rb Adds Node#axnode convenience method.
lib/ferrum/browser.rb Delegates accessibility from Browser to the current page.
lib/ferrum/accessibility/ax_node.rb Implements AXNode value object and deep-freeze.
lib/ferrum/accessibility.rb Implements the Accessibility domain wrapper methods.
CHANGELOG.md Documents the new page.accessibility API and Node#axnode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread spec/unit/accessibility/ax_node_spec.rb
Comment thread spec/unit/accessibility/ax_node_spec.rb Outdated
Comment thread lib/ferrum/accessibility/ax_node.rb Outdated
@myabc myabc force-pushed the feature/accessibility branch from 73968b8 to 2ba5186 Compare June 27, 2026 20:18
Expose a first-class `page.accessibility` domain object (mirroring
Ferrum::Network) wrapping the CDP Accessibility domain, replacing
ad-hoc `Accessibility.getPartialAXTree` command calls downstream.

- Ferrum::Accessibility (page.accessibility, delegated as
  browser.accessibility): node_for, partial_tree, snapshot, query,
  root, enable/disable. Node-scoped commands run on the node's own
  page so they resolve correctly across same-process iframes.
- Ferrum::Accessibility::AXNode value object: role, name, description,
  value, properties, ignored?, ignored_reasons, node_id,
  backend_dom_node_id, child_ids, to_h. Params are deep-frozen for
  immutability; value is untyped since CDP AXValue.value may be a
  string, number, or boolean.
- Ferrum::Node#axnode convenience, mirroring #computed_style.

Adds RBS signatures, specs (unit and browser-driven, including subtree
scoping and iframe coverage), fixtures, and a CHANGELOG entry.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants