Skip to content

feat(selenium-devtools-py): A11y tree and element overlay in Python traces - #343

Open
vishnuv688 wants to merge 20 commits into
mainfrom
vv/341-python-a11y-elements
Open

feat(selenium-devtools-py): A11y tree and element overlay in Python traces#343
vishnuv688 wants to merge 20 commits into
mainfrom
vv/341-python-a11y-elements

Conversation

@vishnuv688

@vishnuv688 vishnuv688 commented Aug 31, 2026

Copy link
Copy Markdown
Member

What & why

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Polish (an improvement to an existing feature)
  • Breaking change (existing behavior changes for users)
  • Documentation
  • Internal (build, CI, dependencies, tooling)

Packages touched

  • shared (types and contracts)
  • core (framework-agnostic capture/reporting)
  • elements (published element/snapshot API — @wdio/elements)
  • service (WebdriverIO adapter)
  • nightwatch-devtools (Nightwatch adapter)
  • selenium-devtools (Selenium adapter)
  • backend (server)
  • app (UI)
  • script (page-injected runtime)
  • selenium-devtools-py
  • trace

Notes for reviewers

Screenshots / recordings

@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds accessibility trees, element rectangles, and overlay points to Python Selenium trace archives by serving shared browser scripts and streaming per-action snapshots through the backend.

  • Moves browser element extraction scripts into the shared package and adds a backend delivery route.
  • Captures and exports Python action snapshots for accessibility and overlay views.
  • Adds trace serialization and focused backend, shared, trace, and Python tests.

Confidence Score: 2/5

The PR is not yet safe to merge because portable traces can expose non-password secrets and multi-session runs can still attach snapshots to the wrong commands.

Element capture preserves non-password values and hrefs through verbatim archive serialization, while the Python instrumentation continues to append snapshots from every driver to one session-unattributed global list.

Files Needing Attention: packages/shared/src/element-scripts.ts and packages/selenium-devtools-py/src/selenium_devtools/instrumentation.py

Security Review

Non-password inputs and href attributes can still carry secrets into portable trace resources even though password fields are now blanked.

How this was verified: The values flow from the shared element script through Python action-snapshot streaming to verbatim JSON serialization in an archive resource.

Important Files Changed

Filename Overview
packages/shared/src/element-scripts.ts Centralizes browser extraction scripts and adds password-only value redaction, but other secret-bearing values and hrefs remain persisted.
packages/selenium-devtools-py/src/selenium_devtools/instrumentation.py Captures accessibility and element data after commands, while snapshots remain globally accumulated without session identity.
packages/selenium-devtools-py/src/selenium_devtools/trace_export.py Streams captured action snapshots to the backend in bounded batches before trace export.
packages/backend/src/trace-export.ts Passes accumulated action snapshots into trace generation and serializes raw accessibility trees for the viewer.
packages/trace/src/a11y-snapshot.ts Provides the extracted web accessibility-tree serializer used by backend trace generation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  DOM[Browser DOM] --> Scripts[Shared element and accessibility scripts]
  Scripts --> Python[Python per-action capture]
  Python --> Socket[Action snapshot WebSocket batches]
  Socket --> Backend[Backend active run]
  Backend --> Trace[Trace serializer]
  Trace --> Archive[Portable trace archive]
Loading

Reviews (3): Last reviewed commit: "fix(examples): a login example that logs..." | Re-trigger Greptile

Comment on lines +412 to +432
snapshot: ActionSnapshot = {"timestamp": timestamp, "command": command}
if shot:
snapshot["screenshot"] = shot
# Two reads, two panes: `elements` carries the interactable boxes, the
# accessibility tree becomes the A11y tab's text. Capturing only the first
# left that tab reporting "no accessibility snapshot for this command" with
# 39 element files sitting in the same archive.
for key, script in (
("elements", scripts["elements"]),
("accessibilityTree", scripts["accessibilityTree"]),
):
try:
value = run(f"return {script}")
except Exception as exc: # noqa: BLE001 — a missing pane, not a failed run
_log.debug("%s read failed: %s", key, exc)
continue
if isinstance(value, list) and value:
snapshot[key] = value
if "elements" not in snapshot and "accessibilityTree" not in snapshot:
return
_state["action_snapshots"].append(snapshot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Snapshots lose session attribution

If two WebDriver sessions issue interleaved commands, their snapshots enter one global list without session identity and are later matched to commands only by timestamp, causing actions to display another session's screenshot, accessibility tree, element rectangles, or overlay point.

Knowledge Base Used:

Comment thread packages/shared/src/element-scripts.ts Outdated
Comment on lines +455 to +456
value: elType.toLowerCase() === 'password' ? '' : inputEl.value || '',
href: htmlEl.getAttribute('href') || '',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Other secrets enter traces

When a traced page contains an OTP, API token, or other secret in a non-password input—or a signed or bearer token in an href—the element script captures it unmodified and the trace writer serializes it into a portable *-elements.json resource, exposing the secret to anyone with the archive.

How this was verified: The captured values flow through Python action-snapshot streaming to verbatim JSON serialization in the trace archive.

Knowledge Base Used:

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.

A11y tree is empty in a Python trace: no per-action element snapshots

1 participant