Skip to content

Fix/include native selector state into snapshot#2105

Open
imorhun wants to merge 2 commits into
browserbase:mainfrom
imorhun:fix/include-native-selector-state-into-snapshot
Open

Fix/include native selector state into snapshot#2105
imorhun wants to merge 2 commits into
browserbase:mainfrom
imorhun:fix/include-native-selector-state-into-snapshot

Conversation

@imorhun
Copy link
Copy Markdown

@imorhun imorhun commented May 11, 2026

Why

Stagehand accessibility snapshot output was missing native selection state markers (selected / checked) that are visible in Playwright ariaSnapshot({ mode: "ai" }).
That mismatch made it impossible to extract the selected/checked item for dropdowns and radio groups.

Example:

<select aria-label="Select field">
  <option>Option A</option>
  <option selected>Option B</option>
  <option>Option C</option>
</select>

Before this fix, Stagehand-style snapshot output did not indicate the selected option:

[ax-4] select: Select field
  [ax-5] option: Option A
  [ax-6] option: Option B
  [ax-7] option: Option C

Expected (and now aligned more closely with Playwright-style output): selected state is explicit:

[ax-4] select: Select field
  [ax-5] option: Option A
  [ax-6] option: Option B [selected]
  [ax-7] option: Option C

What Changed

  • Added a single state field on A11yNode:
    • state?: "selected" | "checked"
  • Updated AX mapping in a11yTree to:
    • read native AX selected / checked
    • normalize those into one state value
  • Added shared snapshot constants in snapshot/constants.ts for:
    • state names
    • roles that should display [selected]
    • boolean parsing literals (1/0, "true"/"false")
  • Updated tree formatting in treeFormatUtils to render:
    • [checked] when state is checked
    • [selected] only for selectable option-like roles (Playwright-like behavior)
  • Added/updated unit tests to cover:
    • AX state extraction/mapping
    • select/radio parent-child rendering with exactly one selected/checked child
    • no [selected] rendering on combobox / select container nodes

Test Plan

  • pnpm --filter @browserbasehq/stagehand run build:esm
  • pnpm --filter @browserbasehq/stagehand run test:core -- packages/core/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js packages/core/dist/esm/tests/unit/snapshot-tree-format-utils.test.js

imorhun added 2 commits May 11, 2026 19:26
Capture native AX selected/checked state as a single node state and render it in snapshot outlines so Stagehand logs align with Playwright-style aria snapshots for selects and radios.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 11, 2026

🦋 Changeset detected

Latest commit: 68a51d3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server-v3 Patch
@browserbasehq/stagehand-server-v4 Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run.
Approving the latest commit mirrors it into an internal PR owned by the approver.
If new commits are pushed later, the internal PR stays open but is marked stale until someone approves the latest external commit and refreshes it.

@github-actions github-actions Bot added external-contributor Tracks PRs mirrored from external contributor forks. external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. labels May 11, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 7 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant CDP as Chrome DevTools Protocol
    participant AX as a11yTree.ts
    participant Constants as constants.ts
    participant TreeFormat as treeFormatUtils.ts
    participant Snapshot as Snapshot Output

    Note over CDP,Snapshot: Accessibility Snapshot with Native Selector State

    CDP->>AX: AXNode tree with properties
    AX->>AX: decorateRoles() iterates nodes
    AX->>Constants: Read state/role constants
    AX->>AX: resolveA11yState() extracts state
    alt Node has checked=true
        AX->>AX: Set state="checked"
    else Node has selected=true
        AX->>AX: Set state="selected"
    else No boolean state
        AX->>AX: state=undefined
    end
    AX->>AX: Build A11yNode with state field
    AX-->>TreeFormat: Decorated node tree

    TreeFormat->>TreeFormat: formatTreeLine() processes each node
    TreeFormat->>Constants: Check A11Y_SELECTED_VISIBLE_ROLES
    alt state="checked"
        TreeFormat->>TreeFormat: Append [checked] to label
    else state="selected" AND role in visible set
        TreeFormat->>TreeFormat: Append [selected] to label
    else Otherwise
        TreeFormat->>TreeFormat: No state flag
    end
    TreeFormat-->>Snapshot: Formatted output with state markers

    Note over Snapshot: Final rendered snapshot<br/>e.g., option: Option B [selected]
Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. external-contributor Tracks PRs mirrored from external contributor forks.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant