Skip to content

feat(native): locators, actionability and trusted input (phase 3) - #10

Merged
unohee merged 1 commit into
masterfrom
feat/native-locators
Oct 25, 2026
Merged

unohee merged 1 commit into
masterfrom
feat/native-locators

Conversation

@unohee

@unohee unohee commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Stacked on #9 (phases 1–2). Phase 3 of the plan.

What

With this PR, these tools run on the native driver unchanged: click, type_text, press_key, hover, scroll, select_option, upload_file, set_editor, wait_for, read_page (text) and read_image.

  • selectors (native/selectors.py)
    • css: open shadow roots are pierced, and :visible / :has-text() become their own steps.
    • text= matches by substring, by "exact" text, or by /regex/.
    • role=…[name=…] is resolved through Chrome's accessibility tree (Accessibility.queryAXTree).
    • Also: xpath=, id=, data-testid=, nth=, visible=.
    • An unknown engine is refused by name, never guessed.
  • locator (native/locator.py, native/injected.py)
    • A locator is resolved again on every call, in the frame's isolated world. frame_locator enters same-process iframes.
    • Actions retry until their timeout and log in Playwright's call-log wording, which describe_failure reads: not visible, not enabled, not editable, not stable, outside of the viewport, or <x> intercepts pointer events (from a hit test at the element's centre).
    • Each attempt keeps its remote objects in its own object group, released afterwards.
  • input (native/input.py)
    • Trusted Input.dispatch*Event with a US key table and modifiers.
    • Input.insertText for Korean, IME text and anything else not on the table.
    • On macOS, Meta+A/C/X/V/Z are sent as editing commands.
  • Locator.evaluate(world="main") lets the CKEditor sync reach window.CKEDITOR.

Not in this PR: the tree view (aria_snapshot and aria-ref) is phase 4.

Verified

  • pytest: 1741 passed. The two pre-existing macOS sha256sum failures in tests/test_claude_plugin.py were deselected.

  • tests/native: 78 tests.

  • Real-Chrome smoke of the element tools (testing/native_locator_smoke_261023_v1.py): 19/19, headless and headful.

    covered
    clicks by css, text= and role=
    hidden, disabled and read-only elements reported with the right reason
    Korean typed exactly
    Enter submits; Backspace
    hover
    select by value and by label
    a hidden file input filled
    scroll to an element; wait_for
    read_page text; an element image
    set_editor into an iframe editor, with the CKEditor field synced
    an overlay reported as the element that intercepts the click
  • The phase 1–2 smoke still passes 18/18.

The native driver now acts on elements, so click, type_text, press_key,
hover, scroll, select_option, upload_file, set_editor, wait_for, read_page
(text) and read_image run on it unchanged.

- selectors: Playwright's syntax as lyra and its callers use it, parsed
  into steps: css with open shadow roots pierced and :visible / :has-text()
  peeled into their own steps, text= (substring, "exact", /regex/), role=
  resolved through Chrome's own accessibility tree (Accessibility.queryAXTree)
  so roles and names are the browser's, xpath=, id=, data-testid=, nth=,
  visible=. An unknown engine is refused by name, never guessed.
- locator: resolved afresh on every call in the frame's isolated world
  (frame_locator enters same-process iframes), first match acted on, retried
  until the timeout with Playwright's call-log wording, because
  describe_failure reads it: not visible / not enabled / not editable /
  not stable / outside of the viewport / "<x> intercepts pointer events"
  from a hit test at the element's centre. Remote objects live in a
  per-attempt object group released afterwards.
- input: Input.dispatchMouseEvent / dispatchKeyEvent with a US key table and
  modifiers, Input.insertText for everything else (Korean and any committed
  IME text), macOS editing commands for Meta+A/C/X/V/Z.
- Locator.evaluate takes world="main", so set_editor's CKEditor sync reaches
  window.CKEDITOR on native as it now does on patchright.

The tree view (aria_snapshot and aria-ref) is phase 4; until then it raises
"not implemented by the native driver yet".

Verified: pytest 1741 passed (2 pre-existing macOS sha256sum failures
deselected); tests/native 78; a real-Chrome smoke of the element tools
(testing/native_locator_smoke_261023_v1.py, 19/19 headless and headful):
clicks by css, text= and role=, hidden / disabled / read-only reported with
the right reason, Korean typed exactly, Enter submits, Backspace, hover,
select by value and label, a hidden file input filled, scroll to an
element, wait_for, read_page text, an element image, set_editor into an
iframe editor with the CKEditor field synced, and an overlay named as the
element that intercepts the click. The phase 1-2 smoke still passes 18/18.
@unohee
unohee force-pushed the feat/native-locators branch from 7ef0ae0 to 38fe0db Compare October 25, 2026 03:57
@unohee
unohee changed the base branch from feat/native-cdp-driver to master October 25, 2026 03:57
@unohee
unohee marked this pull request as ready for review October 25, 2026 03:57
@unohee
unohee merged commit b79ff86 into master Oct 25, 2026
4 checks passed
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.

1 participant