Add supports for Accessibility domain#378
Add supports for Accessibility domain#378j0j1j2 wants to merge 1 commit intoautoscrape-labs:mainfrom
Conversation
📝 WalkthroughWalkthroughThis pull request introduces a new Accessibility domain implementation for the pydoll Chrome DevTools Protocol library, including command factory methods, comprehensive type definitions, event structures, and test coverage for accessibility tree operations. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
pydoll/protocol/accessibility/methods.py (1)
52-57: Makeidrequired inGetChildAXNodesParams.The CDP docs define
getChildAXNodesaround anAXNodeId, and onlyframeIdis described as omittable. Keeping thisTypedDictastotal=Falseweakens the public type and lets empty/invalid param shapes pass static checks. (chromedevtools.github.io)💡 Proposed fix
-class GetChildAXNodesParams(TypedDict, total=False): +class GetChildAXNodesParams(TypedDict): """Parameters for getChildAXNodes command.""" id: AXNodeId - frameId: str + frameId: NotRequired[str]Add the missing import at the top of the file:
from typing_extensions import NotRequired, TypedDict🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pydoll/protocol/accessibility/methods.py` around lines 52 - 57, GetChildAXNodesParams currently uses total=False making all keys optional; change the TypedDict so AXNodeId 'id' is required and 'frameId' remains optional by importing and using NotRequired from typing_extensions (or make total=True and mark frameId as NotRequired) so that GetChildAXNodesParams requires id: AXNodeId while frameId stays optional.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pydoll/commands/accessibility_commands.py`:
- Around line 190-225: The query_ax_tree function currently allows no selector
params and sends empty QueryAXTreeParams to the protocol; add a local validation
at the start of query_ax_tree to ensure at least one of node_id,
backend_node_id, or object_id is provided and raise a ValueError with a clear
message if none are set, then proceed to build params (QueryAXTreeParams) and
return the Command (AccessibilityMethod.QUERY_AX_TREE) as before; also update
the function docstring briefly to state that one of
node_id/backend_node_id/object_id is required.
In `@pydoll/protocol/accessibility/types.py`:
- Around line 57-107: AXPropertyName enum is missing many Accessibility domain
values causing payloads to be unsupported; update the AXPropertyName class to
include the remaining property names from the Chrome DevTools Protocol schema —
add "actions" and "url" plus the 17 hidden-reason values (the
hidden/visibility-related keys starting from activeFullscreenElement through
uninteresting) as enum members, keeping the existing str, Enum inheritance and
docstring; ensure the member names follow existing naming style (UPPER_SNAKE or
exact names used elsewhere) and string values match the protocol (e.g.,
'actions', 'url', 'activeFullscreenElement', ..., 'uninteresting'), so code that
parses Accessibility payloads finds all valid AXPropertyName values.
---
Nitpick comments:
In `@pydoll/protocol/accessibility/methods.py`:
- Around line 52-57: GetChildAXNodesParams currently uses total=False making all
keys optional; change the TypedDict so AXNodeId 'id' is required and 'frameId'
remains optional by importing and using NotRequired from typing_extensions (or
make total=True and mark frameId as NotRequired) so that GetChildAXNodesParams
requires id: AXNodeId while frameId stays optional.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 47f39e82-dca1-498f-af25-3da57cb6fc12
📒 Files selected for processing (7)
pydoll/commands/__init__.pypydoll/commands/accessibility_commands.pypydoll/protocol/accessibility/__init__.pypydoll/protocol/accessibility/events.pypydoll/protocol/accessibility/methods.pypydoll/protocol/accessibility/types.pytests/test_commands/test_accessibility_commands.py
| def query_ax_tree( | ||
| node_id: Optional[int] = None, | ||
| backend_node_id: Optional[int] = None, | ||
| object_id: Optional[str] = None, | ||
| accessible_name: Optional[str] = None, | ||
| role: Optional[str] = None, | ||
| ) -> QueryAXTreeCommand: | ||
| """ | ||
| Queries the accessibility tree for a DOM subtree for nodes with a | ||
| given name and/or role. | ||
|
|
||
| Args: | ||
| node_id: Identifier of the node for the root of the subtree to | ||
| search in. | ||
| backend_node_id: Identifier of the backend node for the root of | ||
| the subtree to search in. | ||
| object_id: JavaScript object id of the node wrapper for the root | ||
| of the subtree to search in. | ||
| accessible_name: Find nodes with this computed name. | ||
| role: Find nodes with this computed role. | ||
|
|
||
| Returns: | ||
| QueryAXTreeCommand: CDP command to query the AX tree. | ||
| """ | ||
| params = QueryAXTreeParams() | ||
| if node_id is not None: | ||
| params['nodeId'] = node_id | ||
| if backend_node_id is not None: | ||
| params['backendNodeId'] = backend_node_id | ||
| if object_id is not None: | ||
| params['objectId'] = object_id | ||
| if accessible_name is not None: | ||
| params['accessibleName'] = accessible_name | ||
| if role is not None: | ||
| params['role'] = role | ||
| return Command(method=AccessibilityMethod.QUERY_AX_TREE, params=params) |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Chrome DevTools Protocol Accessibility queryAXTree parameters requirements
💡 Result:
Accessibility.queryAXTree requires you to specify the root DOM node to query, using exactly one of these identifiers (otherwise CDP returns an error): nodeId, backendNodeId, or objectId. [1]
Filtering parameters are optional:
accessibleName(string): match nodes by computed accessible name. [1]role(string): match nodes by computed accessible role. [1]- If neither
accessibleNamenorroleis provided, it returns all accessibility nodes in the specified node’s subtree. [1]
Related note: Accessibility.enable() is not listed as a prerequisite for queryAXTree, but enabling the domain is what makes AXNodeIds remain consistent across calls. [1]
Sources
[1] Chrome DevTools Protocol (tip-of-tree): Accessibility domain – Accessibility.queryAXTree documentation. (chromedevtools.github.io)
Citations:
🏁 Script executed:
# Find test files related to query_ax_tree
find . -type f -name "*.py" | xargs grep -l "query_ax_tree" | head -20Repository: autoscrape-labs/pydoll
Length of output: 162
🏁 Script executed:
# Get context around the test assertions for query_ax_tree
rg -A 10 -B 5 "query_ax_tree" --type py | head -100Repository: autoscrape-labs/pydoll
Length of output: 8195
Add validation: query_ax_tree() requires one of node_id, backend_node_id, or object_id.
The Chrome DevTools Protocol requires exactly one DOM node selector for queryAXTree; the protocol returns an error when none are specified. The current implementation permits calling with no arguments (resulting in params={}), and the new tests explicitly assert this invalid state is acceptable. Validate locally to fail fast with a clear ValueError rather than a round-trip protocol failure.
Proposed fix
def query_ax_tree(
node_id: Optional[int] = None,
backend_node_id: Optional[int] = None,
object_id: Optional[str] = None,
accessible_name: Optional[str] = None,
role: Optional[str] = None,
) -> QueryAXTreeCommand:
@@
+ if node_id is None and backend_node_id is None and object_id is None:
+ raise ValueError(
+ 'query_ax_tree requires one of node_id, backend_node_id, or object_id'
+ )
+
params = QueryAXTreeParams()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pydoll/commands/accessibility_commands.py` around lines 190 - 225, The
query_ax_tree function currently allows no selector params and sends empty
QueryAXTreeParams to the protocol; add a local validation at the start of
query_ax_tree to ensure at least one of node_id, backend_node_id, or object_id
is provided and raise a ValueError with a clear message if none are set, then
proceed to build params (QueryAXTreeParams) and return the Command
(AccessibilityMethod.QUERY_AX_TREE) as before; also update the function
docstring briefly to state that one of node_id/backend_node_id/object_id is
required.
| class AXPropertyName(str, Enum): | ||
| """Values of AXProperty name. | ||
|
|
||
| See https://chromedevtools.github.io/devtools-protocol/tot/Accessibility/#type-AXPropertyName | ||
| """ | ||
|
|
||
| # States | ||
| BUSY = 'busy' | ||
| DISABLED = 'disabled' | ||
| EDITABLE = 'editable' | ||
| FOCUSABLE = 'focusable' | ||
| FOCUSED = 'focused' | ||
| HIDDEN = 'hidden' | ||
| HIDDEN_ROOT = 'hiddenRoot' | ||
| INVALID = 'invalid' | ||
| KEYSHORTCUTS = 'keyshortcuts' | ||
| SETTABLE = 'settable' | ||
| ROLEDESCRIPTION = 'roledescription' | ||
| # Live region attributes | ||
| LIVE = 'live' | ||
| ATOMIC = 'atomic' | ||
| RELEVANT = 'relevant' | ||
| ROOT = 'root' | ||
| # Widget attributes | ||
| AUTOCOMPLETE = 'autocomplete' | ||
| HAS_POPUP = 'hasPopup' | ||
| LEVEL = 'level' | ||
| MULTISELECTABLE = 'multiselectable' | ||
| ORIENTATION = 'orientation' | ||
| MULTILINE = 'multiline' | ||
| READONLY = 'readonly' | ||
| REQUIRED = 'required' | ||
| VALUEMIN = 'valuemin' | ||
| VALUEMAX = 'valuemax' | ||
| VALUETEXT = 'valuetext' | ||
| # Widget states | ||
| CHECKED = 'checked' | ||
| EXPANDED = 'expanded' | ||
| MODAL = 'modal' | ||
| PRESSED = 'pressed' | ||
| SELECTED = 'selected' | ||
| # Relationship attributes | ||
| ACTIVEDESCENDANT = 'activedescendant' | ||
| CONTROLS = 'controls' | ||
| DESCRIBEDBY = 'describedby' | ||
| DETAILS = 'details' | ||
| ERRORMESSAGE = 'errormessage' | ||
| FLOWTO = 'flowto' | ||
| LABELLEDBY = 'labelledby' | ||
| OWNS = 'owns' | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n pydoll/protocol/accessibility/types.py | sed -n '57,107p'Repository: autoscrape-labs/pydoll
Length of output: 1758
🌐 Web query:
Chrome DevTools Protocol Accessibility AXPropertyName allowed values schema
💡 Result:
In the Chrome DevTools Protocol (CDP) Accessibility domain, AXPropertyName is a string enum defined in the protocol schema.
Where it’s defined (schema)
- In the published protocol JSON schema (npm
devtools-protocol), seejson/browser_protocol.json→domains[]→Accessibility→types[]→id: "AXPropertyName"→"enum": [...]. The enum values there are:
busy,disabled,hidden,hiddenRoot,invalid,keyshortcuts,roledescription,live,atomic,relevant,root,autocomplete,haspopup,level,multiselectable,orientation,multiline,readonly,required,valuemin,valuemax,valuetext,checked,expanded,modal,pressed,selected,activedescendant,controls,describedby,details,errormessage,flowto,labelledby,owns. [2]
Protocol viewer (“Allowed Values”)
The protocol viewer page for Accessibility.AXPropertyName often shows a larger set of “Allowed Values” (including additional/internal names such as actions, editable, focusable, focused, settable, plus various internal flags like uninteresting, etc.). [1]
If you need the authoritative list for codegen/validation, use the JSON schema enum from browser_protocol.json; if you’re matching what DevTools UI may surface, consult the protocol viewer list too. [1][2]
🌐 Web query:
devtools-protocol npm AXPropertyName complete enum values browser_protocol.json
💡 Result:
In browser_protocol.json (CDP Accessibility.AXPropertyName), the enum values are:
actions
busy
disabled
editable
focusable
focused
hidden
hiddenRoot
invalid
keyshortcuts
settable
roledescription
live
atomic
relevant
root
autocomplete
hasPopup
level
multiselectable
orientation
multiline
readonly
required
valuemin
valuemax
valuetext
checked
expanded
modal
pressed
selected
activedescendant
controls
describedby
details
errormessage
flowto
labelledby
owns
url
activeFullscreenElement
activeModalDialog
activeAriaModalDialog
ariaHiddenElement
ariaHiddenSubtree
emptyAlt
emptyText
inertElement
inertSubtree
labelContainer
labelFor
notRendered
notVisible
presentationalRole
probablyPresentational
inactiveCarouselTabContent
uninteresting[1]
🏁 Script executed:
# Check if there's any reference documentation or schema in the repo
find . -type f -name "*protocol*" -o -name "*schema*" | grep -i access | head -20Repository: autoscrape-labs/pydoll
Length of output: 48
Complete the AXPropertyName enum with all valid Accessibility domain values.
The enum is incomplete. According to the official Chrome DevTools Protocol schema, it should include actions, url, and 17 hidden-reason values (activeFullscreenElement through uninteresting). The current implementation stops at owns, leaving 23 valid property names out of the enum, which breaks support for legitimate Accessibility payloads.
💡 Proposed fix
class AXPropertyName(str, Enum):
"""Values of AXProperty name.
See https://chromedevtools.github.io/devtools-protocol/tot/Accessibility/#type-AXPropertyName
"""
# States
+ ACTIONS = 'actions'
BUSY = 'busy'
DISABLED = 'disabled'
EDITABLE = 'editable'
FOCUSABLE = 'focusable'
FOCUSED = 'focused'
HIDDEN = 'hidden'
HIDDEN_ROOT = 'hiddenRoot'
INVALID = 'invalid'
KEYSHORTCUTS = 'keyshortcuts'
SETTABLE = 'settable'
ROLEDESCRIPTION = 'roledescription'
# Live region attributes
LIVE = 'live'
ATOMIC = 'atomic'
RELEVANT = 'relevant'
ROOT = 'root'
# Widget attributes
AUTOCOMPLETE = 'autocomplete'
HAS_POPUP = 'hasPopup'
LEVEL = 'level'
MULTISELECTABLE = 'multiselectable'
ORIENTATION = 'orientation'
MULTILINE = 'multiline'
READONLY = 'readonly'
REQUIRED = 'required'
VALUEMIN = 'valuemin'
VALUEMAX = 'valuemax'
VALUETEXT = 'valuetext'
# Widget states
CHECKED = 'checked'
EXPANDED = 'expanded'
MODAL = 'modal'
PRESSED = 'pressed'
SELECTED = 'selected'
# Relationship attributes
ACTIVEDESCENDANT = 'activedescendant'
CONTROLS = 'controls'
DESCRIBEDBY = 'describedby'
DETAILS = 'details'
ERRORMESSAGE = 'errormessage'
FLOWTO = 'flowto'
LABELLEDBY = 'labelledby'
OWNS = 'owns'
URL = 'url'
# Hidden reasons
+ ACTIVE_FULLSCREEN_ELEMENT = 'activeFullscreenElement'
+ ACTIVE_MODAL_DIALOG = 'activeModalDialog'
+ ACTIVE_ARIA_MODAL_DIALOG = 'activeAriaModalDialog'
+ ARIA_HIDDEN_ELEMENT = 'ariaHiddenElement'
+ ARIA_HIDDEN_SUBTREE = 'ariaHiddenSubtree'
+ EMPTY_ALT = 'emptyAlt'
+ EMPTY_TEXT = 'emptyText'
+ INERT_ELEMENT = 'inertElement'
+ INERT_SUBTREE = 'inertSubtree'
+ LABEL_CONTAINER = 'labelContainer'
+ LABEL_FOR = 'labelFor'
+ NOT_RENDERED = 'notRendered'
+ NOT_VISIBLE = 'notVisible'
+ PRESENTATIONAL_ROLE = 'presentationalRole'
+ PROBABLY_PRESENTATIONAL = 'probablyPresentational'
+ INACTIVE_CAROUSEL_TAB_CONTENT = 'inactiveCarouselTabContent'
+ UNINTERESTING = 'uninteresting'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pydoll/protocol/accessibility/types.py` around lines 57 - 107, AXPropertyName
enum is missing many Accessibility domain values causing payloads to be
unsupported; update the AXPropertyName class to include the remaining property
names from the Chrome DevTools Protocol schema — add "actions" and "url" plus
the 17 hidden-reason values (the hidden/visibility-related keys starting from
activeFullscreenElement through uninteresting) as enum members, keeping the
existing str, Enum inheritance and docstring; ensure the member names follow
existing naming style (UPPER_SNAKE or exact names used elsewhere) and string
values match the protocol (e.g., 'actions', 'url', 'activeFullscreenElement',
..., 'uninteresting'), so code that parses Accessibility payloads finds all
valid AXPropertyName values.
|
thanks @j0j1j2 ! I'll review as soon as I can |
Pull Request
Description
I have added support for the Chrome DevTools Protocol's Accessibility domain. Users can now inspect the accessibility tree and retrieve essential accessibility metadata directly, facilitating easier auditing and support for accessible web development. Furthermore, this structured data enhances the LLM's ability to parse and understand the page document more accurately.
Related Issue(s)
Type of Change
How Has This Been Tested?
I've created test code on
tests/test_commands/test_accessibility_commands.py.In addition to test, you can test accessiblity domain with this code snippet.
Testing Checklist
Screenshots
Implementation Details
API Changes
Additional Info
Checklist before requesting a review
poetry run task lintand fixed any issuespoetry run task testand all tests passSummary by CodeRabbit
New Features
Tests