[BE-0280] feat(conformance): actuate text-editing and tap_point in the driver contract#1204
Merged
Merged
Conversation
…ontract Extend the driver conformance contract (BE-0114) to the Driver operations no lane actuated under it: select_all / copy_selection, the delete_text round-trip, and tap_point (BE-0280). - Add a `Capability.TEXT_SELECTION` token for select-all + clipboard copy on the focused field. XCUITest / adb / Playwright / fake declare it; idb, coordinate- only with no select-all handle, does not and raises `UnsupportedAction`. - Gate `select` / `copy` steps on it in the preflight (`capability_preflight.py`), exactly like `selectOption`, so an idb scenario fails up front rather than late. `delete` / `clear` stay ungated — every backend backs `delete_text`. - Add three contract bodies to `tests/driver_conformance.py`: text-selection actuate-vs-raise, delete-reduces-length, and tap_point focusing the field like a semantic tap. Each conformance screen (iOS `ConformanceView`, Compose `ConformanceScreen`, web `_render`, and the reactive `FakeConformanceHarness` on the gate) grows one always-present editable field, whose known frame doubles as the coordinate tap's target. - Update docs/drivers.md, docs/architecture.md (both languages) and flip the roadmap item to Implemented. Verified: `make check` green (FakeDriver lane) and the web lane green against real Chromium; idb / XCUITest / adb lanes verify in the E2E workflows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fb-idb's client.text() maps each character through KEY_MAP, which has no entry for the backspace control character and raises "No keycode found for". Route delete_text through client.key_sequence with the Delete/Backspace HID keycode instead, the hardware backspace the field honors natively. Splits the shared companion helper so typing keeps client.text and deleting uses key events, and pins the seam with a Fake-lane test (skipped without the idb extra). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The conformance TextField carried an explicit .accessibilityValue(fieldText) bound to its per-keystroke state, which made SwiftUI re-create the field's accessibility element on every change, so an XCUITest handle resolved just before a keystroke went stale under the element. A SwiftUI TextField already surfaces its bound text as its accessibility value natively (as SearchView's field does), so drop the explicit modifier: the round-trip value stays observable while the node identity stabilizes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A text-editing conformance test leaves iOS transient UI up — the keyboard, and after select-all/copy the system edit menu (a PopoverDismissRegion backdrop). That floats above ConformanceView, so re-rendering the seeded content on a reseed does not clear it; it obscured the next screen's readiness marker, and the harness's readiness probe saw only PopoverDismissRegion — the field/marker gone. It also churned the XCUITest field handle to stale. Resign the field and end editing app-wide when the screen is reseeded (identifiers change). Deterministic (no fixed sleep), app-side, so the backend-agnostic contract stays free of any iOS-specific teardown. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reuse the shared geometry helper (BE-0251) the backends use rather than a second copy of the (x + w/2, y + h/2) arithmetic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hirosassa
marked this pull request as ready for review
July 19, 2026 20:12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends the driver conformance contract (BE-0114) to the
Driveroperations no lane actuated under the contract before: the text-editing family (select_all/copy_selection/delete_text) andtap_point. Previously each backend's command construction was unit-tested with a mocked subprocess, but no lane exercised the round-trip from a step to an observed field change — a capability the tool advertised but no lane observed. This closes that gap with one spec that runs on every backend. Implements BE-0280.What changed
Capability.TEXT_SELECTION(bajutsu/drivers/base.py) for select-all + clipboard copy on the focused field. XCUITest / adb / Playwright /fakedeclare it; idb — coordinate-only, no select-all handle — does not and raisesUnsupportedAction, the same actuate-or-raise promise asMULTI_TOUCH.bajutsu/capability_preflight.py):select/copysteps requireTEXT_SELECTION, so an idb scenario using them fails up front (likeselectOption) instead of late.delete/clearstay ungated — every backend backsdelete_text.tests/driver_conformance.py: text-selection actuate-vs-raise,delete_textreduces the field length, andtap_pointfocuses the field like a semantic tap.ConformanceView, ComposeConformanceScreen, web_render, and the now-reactiveFakeConformanceHarnesson the gate. Its known, queryable frame doubles as the coordinate tap's target, so no separate known-frame element is needed. The typed text surfaces as the elementvalueon every backend (iOSAXValue, webinput.value, adb via a content-desc mirror since adb mapstext→label).docs/drivers.md(capability table + preflight),docs/architecture.md(conformance invariants), both with theirdocs/ja/mirrors.Prime-directive compliance
make checkand the E2E workflows.sleep; the round-trip is observed viaquery()deltas. A backend that declaresTEXT_SELECTIONmust actuate; one that does not must raise loudly (no silent no-op).Verification
make check— green (FakeDriver conformance lane, preflight, all unit tests; 92.4% coverage).-m web) — green against real headless Chromium locally (the 3 new bodies included).ios-e2e.yml/android-e2e.ymlon this PR; the new field surfaces its value on each so the round-trip is observed on-device.Roadmap
Flips BE-0280 to Implemented in both language files and reindexes.
🤖 Generated with Claude Code