@swmansion/argent 0.32.1-next.0 → 0.32.1-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/installer.mjs +6 -6
- package/dist/mcp-server.mjs +1 -1
- package/dist/tool-args.generated.d.ts +178 -178
- package/dist/tool-server.cjs +1261 -1455
- package/package.json +1 -1
- package/rules/argent.md +19 -183
- package/skills/argent-android-emulator-setup/SKILL.md +5 -13
- package/skills/argent-create-e2e/SKILL.md +1 -1
- package/skills/argent-create-e2e/references/e2e-yaml.md +12 -17
- package/skills/argent-create-e2e/references/live-authoring.md +25 -65
- package/skills/argent-create-e2e/references/reliability-and-recovery.md +8 -8
- package/skills/argent-device-interact/SKILL.md +65 -367
- package/skills/argent-device-interact/references/chromium.md +4 -19
- package/skills/argent-device-interact/references/foldables.md +8 -0
- package/skills/argent-device-interact/references/harmonyos.md +13 -50
- package/skills/argent-ios-device-interact/SKILL.md +0 -1
- package/skills/argent-ios-device-setup/SKILL.md +1 -1
- package/skills/argent-ios-simulator-setup/SKILL.md +3 -9
- package/skills/argent-lens/SKILL.md +20 -75
- package/skills/argent-metro-debugger/SKILL.md +35 -101
- package/skills/argent-native-profiler/SKILL.md +23 -92
- package/skills/argent-qa-e2e/SKILL.md +5 -5
- package/skills/argent-react-native-app-workflow/SKILL.md +34 -203
- package/skills/argent-react-native-optimization/SKILL.md +10 -26
- package/skills/argent-react-native-optimization/references/fix-reference.md +11 -11
- package/skills/argent-react-native-optimization/references/lint-rules.md +4 -5
- package/skills/argent-react-native-optimization/references/semantic-checklist.md +2 -2
- package/skills/argent-react-native-profiler/SKILL.md +46 -110
- package/skills/argent-screen-recording/SKILL.md +18 -37
- package/skills/argent-screenshot-diff/SKILL.md +8 -52
- package/skills/argent-settings-permissions/SKILL.md +15 -117
- package/skills/argent-test-ui-flow/SKILL.md +20 -90
- package/skills/argent-tv-interact/SKILL.md +9 -34
- package/skills/argent-tv-interact/references/vega.md +23 -0
- package/agents/argent-environment-inspector.md +0 -107
- package/agents/references/quality-control-checklist.md +0 -45
- package/skills/argent-device-interact/references/gesture-examples.md +0 -114
- package/skills/argent-device-interact/references/secrets.md +0 -23
- package/skills/argent-metro-debugger/references/failure-scenarios.md +0 -14
- package/skills/argent-metro-debugger/references/source-maps.md +0 -27
- package/skills/argent-react-native-profiler/references/diagnostic-tools.md +0 -101
package/package.json
CHANGED
package/rules/argent.md
CHANGED
|
@@ -1,198 +1,34 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Argent
|
|
2
|
+
description: Always-on Argent rules for driving, testing and profiling apps on simulators, emulators, phones, TVs and Chromium
|
|
3
3
|
alwaysApply: true
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
If argent is installed and configured in this environment, its MCP tools are the preferred form of interaction with the application for iOS simulator, physical iPhone, Android emulator, Chromium (CDP) app, and Vega (Amazon Fire TV) device control; otherwise see `<availability_check>` below before attempting any argent workflow. A "Chromium (CDP) app" is any Chromium runtime exposing a Chrome DevTools Protocol endpoint: an Electron app, or any Chromium-family browser (Chrome/Brave/Edge) launched with `--remote-debugging-port`; all are driven through the same tool surface and tagged `platform: "chromium"`. A "Vega device" is a virtual device (VVD) or physical unit, driven by tv-remote (D-pad) and tagged `platform: "vega"`. Physical iPhones (iPads are not supported) appear in `list-devices` as iOS entries with kind `"device"`; they are driven over USB cable only, and the on-device runner's signing is auto-detected from the Mac's keychain (`ARGENT_IOS_TEAM_ID` overrides). Automation there is app-scoped: `launch-app` registers the target app before anything else can act. Read `argent-ios-device-setup` to get one connected and `argent-ios-device-interact` before interacting.
|
|
8
|
-
Running MCP server and managing the Argent toolkit utilises `argent` command - if asked use `argent --help` for reference.
|
|
9
|
-
To check current version of MCP server run `argent --version` command.
|
|
6
|
+
Argent - general rules:
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
8
|
+
- do not derive tap coordinates from screenshot pixels; use inspection tools that give coordinates
|
|
9
|
+
- use the platform the user named; otherwise prefer a device `list-devices` shows already running, and don't default to iOS; in a single-platform project boot that platform.
|
|
10
|
+
- if tap fails twice, stop retrying and re-run a discovery tool
|
|
11
|
+
- Prefer mcp-tool calls over raw commands like `xcrun` or `adb`; use them as fallback.
|
|
12
|
+
- Interaction tools return screenshot and element tree automatically.
|
|
13
|
+
- prefer `launch-app` or `open-url` than tapping icons on home screen.
|
|
14
|
+
- If a task can require a saved e2e test, load `argent-create-e2e` (`argent-qa-e2e` for acceptance tests) before the first launch or in-app action; recording is not retroactive.
|
|
15
|
+
- Load the matching `argent-*` skill before React Native build/debug, profiling, a physical phone or a TV.
|
|
16
|
+
- Do not stop simulator servers when a task finishes: the next task reuses them. Call `stop-all-simulator-servers` when the user asks to clean up or ends the session, or when a skill tells you to recycle a device's services, with devices this session used. One tool-server is shared by every other agent, so unscoped call tears down their devices too. Never stop a Metro the user started unless they ask.
|
|
17
|
+
- Use the `await-ui-element` tool to block until the UI settles instead of polling using screenshot.
|
|
18
|
+
- The `argent` CLI manages the toolkit: `argent --help` lists commands, `argent --version` shows the installed version.
|
|
22
19
|
|
|
23
20
|
<availability_check>
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
Run this check once per session. Do not re-probe before later calls.
|
|
26
22
|
Confirm argent is available:
|
|
27
23
|
|
|
28
|
-
1. Are `mcp__argent__*` tools in your tool list? If none
|
|
29
|
-
2. If
|
|
24
|
+
1. Are `mcp__argent__*` tools in your tool list? If none, argent is not available.
|
|
25
|
+
2. If unsure, run `command -v argent`. Non-zero exit = the CLI is not on PATH.
|
|
30
26
|
|
|
31
27
|
If argent IS available, ignore the rest of this block and follow this rule normally.
|
|
32
28
|
|
|
33
|
-
If argent is ABSENT, treat it as an expected state, not an error to retry. Do not call `mcp__argent__*` tools, do not run `argent` commands,
|
|
29
|
+
If argent is ABSENT, treat it as an expected state, not an error to retry. Do not call `mcp__argent__*` tools, do not run `argent` commands, do not attempt any argent workflow.
|
|
30
|
+
Tell the user once, and ask if you should continue without argent:
|
|
34
31
|
|
|
35
32
|
> Argent isn't installed in this environment. To enable the mobile/Chromium tooling this repo is configured for, run `npx @swmansion/argent@latest init -y` (or `npm i -g @swmansion/argent@latest && argent init -y`).
|
|
36
|
-
> </availability_check>
|
|
37
|
-
|
|
38
|
-
<tapping_rule>
|
|
39
|
-
<important>**Never** derive tap coordinates from screenshot pixels</important>
|
|
40
|
-
Interaction tools (`gesture-tap`, `gesture-swipe`, `keyboard`, `button`, `launch-app`, `open-url`, `run-sequence`, `await-ui-element`, …) return the screen **after** the action: a screenshot AND the accessibility element tree (`--- Elements after action (describe) ---`, the same format `describe` prints, with normalized 0–1 frames). Take tap coordinates from that tree: the centre of the element's frame (`x + width/2`, `y + height/2`). You do not need a separate discovery call before a tap when the last result already lists the target.
|
|
41
|
-
|
|
42
|
-
Call a discovery tool yourself only when you have no fresh tree for the current screen: before the first action on a screen you have not touched yet, after waiting for something to load without `await-ui-element`, or when the last tree did not list your target. Preferred tools are, in order:
|
|
43
|
-
|
|
44
|
-
- `describe` - native app-level components and safely targetable foreground apps (iOS and Android).
|
|
45
|
-
- `native-describe-screen` - accessibility screen description via injected native devtools (iOS only)
|
|
46
|
-
- `debugger-component-tree` - react-native specific components
|
|
47
|
-
|
|
48
|
-
`native-user-interactable-view-at-point` / `native-view-at-point` are follow-up diagnostics once you already have a candidate point (iOS only).
|
|
49
|
-
|
|
50
|
-
If a **tap fails twice** at the same coordinates, **stop retrying** and re-run a discovery tool.
|
|
51
|
-
|
|
52
|
-
If `describe` fails, **read the exact error before reacting**, follow the recovery guidance in `argent-device-interact` to choose the correct next action.
|
|
53
|
-
|
|
54
|
-
Before starting to interact with the app, read the `argent-device-interact` skill first.
|
|
55
|
-
</tapping_rule>
|
|
56
|
-
|
|
57
|
-
<device_selection_rule>
|
|
58
|
-
Before booting, running, or interacting with any app, call `list-devices` first - prefer running devices.
|
|
59
|
-
|
|
60
|
-
Decision order:
|
|
61
|
-
|
|
62
|
-
1. **Explicit user intent** - choose the user named platform or device. Look for words "simulator" and "emulator".
|
|
63
|
-
2. **Prefer a running device.** iOS simulators - state `Booted` and Android devices - `state: "device"` come first in `list-devices`; Chromium (CDP) apps appear as `platform: "chromium"`, `state: "Running"`. A cabled physical iPhone (`platform: "ios"`, `kind: "device"`, `state: "connected"`) is listed first too, but it is not a running simulator: never pick it because it is there. Use it only when the user names the phone, a physical or real device, or hardware testing. With nothing else booted, boot a simulator or ask which target the user means.
|
|
64
|
-
3. **Single-platform project:** (per `argent-environment-inspector` flags `is_native_ios`/`is_native_android`, or RN with only one platform configured) → boot that platform.
|
|
65
|
-
</device_selection_rule>
|
|
66
|
-
|
|
67
|
-
<skill_reading_rule>
|
|
68
|
-
<important>Always read relevant skills for guidance before executing argent-mcp tool - read skill_routing reference</important>
|
|
69
|
-
</skill_reading_rule>
|
|
70
|
-
|
|
71
|
-
<general_rules>
|
|
72
|
-
|
|
73
|
-
- All simulator/emulator interactions go through argent MCP tools; never use `xcrun simctl`,
|
|
74
|
-
raw `curl` to simulator ports, or the simulator-server binary directly.
|
|
75
|
-
- Before calling any gesture tool for the first time, use ToolSearch to load its schema.
|
|
76
|
-
- Interaction tools (`gesture-tap`, `gesture-swipe`, `gesture-pinch`, `gesture-rotate`, `gesture-custom`, `launch-app`, etc.) return a screenshot and the element tree automatically.
|
|
77
|
-
Call `screenshot` or `describe` separately only for a baseline before any action or after a delay.
|
|
78
|
-
- Always open apps with `launch-app` or `open-url`; never tap home screen icons.
|
|
79
|
-
- If a task can require a saved e2e test, choose `argent-create-e2e` or `argent-qa-e2e` before the first launch or in-app action. Start the recorder before walking the path; recording is not retroactive.
|
|
80
|
-
- Always use `run-sequence` when performing multiple sequential device actions where you don't need to observe the screen between steps. More in `argent-device-interact` skill.
|
|
81
|
-
- Do not stop simulator servers when a task finishes: the next task reuses them, and stopping them makes its
|
|
82
|
-
first device action start cold again. Call `stop-all-simulator-servers` when the user asks to clean up or
|
|
83
|
-
ends the session, or when a skill tells you to recycle a device's services (e.g. before a QA proof pass).
|
|
84
|
-
Always pass `devices: [...]` naming the devices this session used. One tool-server is shared by every other
|
|
85
|
-
agent using this argent install, so an unscoped call tears down their devices too; reserve that form for a
|
|
86
|
-
deliberate machine-wide cleanup.
|
|
87
|
-
Never stop a Metro the user started unless they ask (`stop-metro`, specify the port if not 8081).
|
|
88
|
-
- If tools provided by mcp-server are not sufficient and action can be done using `xcrun`, `adb`, or other commands, use the command. Examples: changing device options, performing a device action such as lock, shake, etc. Not on a physical iPhone.
|
|
89
|
-
- When waiting for an action, do not call `screenshot` repeatedly without a proper wait mechanism. Use the `await-ui-element` tool to block until the UI settles (e.g. wait for an element to become `visible`/`hidden`, or to contain expected `text`) instead of polling.
|
|
90
|
-
</general_rules>
|
|
91
|
-
|
|
92
|
-
<react_native_detection>
|
|
93
|
-
Project type is determined by the `argent-environment-inspector` subagent (see `subagents` section).
|
|
94
|
-
When the subagent result is available, use its `is_react_native` field as the authoritative
|
|
95
|
-
source; do not re-inspect files manually.
|
|
96
|
-
|
|
97
|
-
If the subagent has not run yet and project type is unknown, run it first before proceeding. Always use subagents if available to run `gather-workspace-data` data tool, if possible do not run yourself.
|
|
98
|
-
|
|
99
|
-
When `is_react_native` is true: load `argent-react-native-app-workflow` skill. Use `debugger-component-tree` for element discovery - if the responses are large or unhelpful, try `describe`.
|
|
100
|
-
</react_native_detection>
|
|
101
|
-
|
|
102
|
-
<skill_routing>
|
|
103
|
-
Load the matching skill before starting work and executing tools from argent-mcp: skills contain the full step-by-step
|
|
104
|
-
procedure and edge-case handling for each workflow.
|
|
105
|
-
|
|
106
|
-
PLATFORM DETECTION
|
|
107
|
-
If the user did not specify a platform, call `list-devices` first and pick the booted target; do not default to iOS. Vega (Amazon Fire TV) devices appear as `platform:"vega"`, when present load `argent-tv-interact`
|
|
108
|
-
|
|
109
|
-
iOS SIMULATOR SETUP
|
|
110
|
-
Skill: `argent-ios-simulator-setup`
|
|
111
|
-
When: Beginning a task that involves the iOS simulator, no simulator booted yet, need UDID or simulator-server.
|
|
112
|
-
|
|
113
|
-
ANDROID EMULATOR SETUP
|
|
114
|
-
Skill: `argent-android-emulator-setup`
|
|
115
|
-
When: Beginning a task that involves the Android emulator, no emulator running yet, need an adb serial, or about to install an APK.
|
|
116
|
-
|
|
117
|
-
PHYSICAL iPHONE (USB)
|
|
118
|
-
Skills: `argent-ios-device-setup` (cable, trust, signing), then `argent-ios-device-interact` (the app-scoped interaction contract)
|
|
119
|
-
When: The user names a physical iPhone, a real device, or hardware, or the target `list-devices` iOS entry has kind `"device"`. Never for a simulator, and never because a cabled phone is listed first. On hardware every interaction starts with `launch-app`; `paste`, `settings-permissions`, `rotate`, `shake`, screen recording, `debugger-*`, `react-profiler-*`, `native-profiler-*` and `native-*` do not exist there.
|
|
120
|
-
Prompt keywords: physical iPhone, real device, on my phone, USB, hardware
|
|
121
|
-
|
|
122
|
-
TAPPING, SWIPING, TYPING, GESTURES, SCREENSHOTS, SCROLLING
|
|
123
|
-
Skill: `argent-device-interact`
|
|
124
|
-
When: Performing touch interactions, typing, pressing hardware buttons, launching/restarting apps, opening URLs, rotating or folding the device, taking standalone screenshots, or verifying a visible UI code change. Covers phone/tablet iOS and Android simulators and emulators plus Chromium (CDP) apps: for any TV target use the TV skill below, and for a physical iPhone use the entry above.
|
|
125
|
-
|
|
126
|
-
APP PERMISSIONS (GRANT / DENY / RESET WITHOUT THE SETTINGS UI)
|
|
127
|
-
Skill: `argent-settings-permissions`
|
|
128
|
-
When: You must change an app runtime permission (camera, microphone, photos, contacts, notifications, calendar, location, location-always, media-library, motion, reminders) that the app itself can't flip: pre-authorize or deny it before the app asks, re-enable one the user already denied (iOS never re-prompts), or reset it so the first-run dialog reappears. Works on the iOS simulator and Android emulator/device. Do NOT use it when the app has an in-app toggle or is showing its own permission dialog; tap that instead (see `argent-device-interact`); nor for permissions/settings outside that list.
|
|
129
|
-
Prompt keywords: permission, grant, deny, revoke, reset permission, privacy, camera access, location access, TCC
|
|
130
|
-
|
|
131
|
-
TV INTERACTION (APPLE TV / ANDROID TV / FIRE TV)
|
|
132
|
-
Skill: `argent-tv-interact`
|
|
133
|
-
When: Any TV target: a `list-devices` entry with `runtimeKind: "tv"` (Apple TV simulator or Android TV emulator) or `platform:"vega"` / `kind:"vvd"` (Amazon Fire TV / VVD), or the user mentions Apple TV / tvOS / Android TV / leanback / Vega / Fire TV. A TV UI is focus-driven, not touch-driven: drive it with `describe` (read focus) + `tv-remote` (D-pad presses) + `keyboard` (type); `gesture-*` tools do NOT apply. Covers booting the target, app lifecycle, focus navigation, typing, screenshots, and (Vega) VVD lifecycle + Fast Refresh + JS-runtime debugging (evaluate, console logs, network inspector).
|
|
134
|
-
Prompt keywords: apple tv, tvos, android tv, leanback, vega, fire tv, vvd, d-pad
|
|
135
|
-
Saved artifacts: on Vega, a replayable path is `argent-create-e2e` and an acceptance-criteria regression test is `argent-qa-e2e`; both record D-pad navigation as `tool: tv-remote` steps. Apple TV and Android TV have no e2e support; report that limitation.
|
|
136
|
-
|
|
137
|
-
SCREENSHOT DIFF & VISUAL REGRESSION
|
|
138
|
-
Skill: `argent-screenshot-diff`
|
|
139
|
-
When: Explicit visual regression, screenshot diff, compare screenshots, before/after visual comparison requests, or visible UI changes where stable pixel comparison would add useful evidence.
|
|
140
|
-
|
|
141
|
-
SCREEN RECORDING (VIDEO CAPTURE)
|
|
142
|
-
Skill: `argent-screen-recording`
|
|
143
|
-
When: The user wants an mp4 of an interaction, animation, or bug reproduction. Use `argent-create-e2e` instead for a replayable sequence.
|
|
144
|
-
Prompt keywords: record, recording, screen recording, video, capture video, clip, mp4
|
|
145
|
-
|
|
146
|
-
RUNNING / BUILDING / DEBUGGING REACT NATIVE APP
|
|
147
|
-
Skill: `argent-react-native-app-workflow`
|
|
148
|
-
When: Project is react-native, starting Metro or running the iOS or Android app, build failures, pod issues, lost Metro connection, reading logs, reloading JS bundle, reinstalling app.
|
|
149
|
-
|
|
150
|
-
JS EVALUATION, METRO CONNECTION, REACT NATIVE
|
|
151
|
-
Skill: `argent-metro-debugger`
|
|
152
|
-
When: evaluating expressions, inspecting React component tree at source level, finding element placement via `debugger-component-tree`.
|
|
153
|
-
|
|
154
|
-
REACT APP & COMPONENT PROFILING
|
|
155
|
-
Use skill: `argent-react-native-profiler`
|
|
156
|
-
When: To measure performance of specific components, to find app-wide bottlenecks. Investigating re-renders or CPU hotspots, producing ranked performance reports.
|
|
157
|
-
|
|
158
|
-
NATIVE PROFILING
|
|
159
|
-
Use skill: `argent-native-profiler`
|
|
160
|
-
When: Profiling native performance (CPU hotspots, UI hangs, memory leaks). iOS only today; Android on the roadmap. Useful as a reference for platform-specific investigation when running dual profiling via `argent-react-native-profiler`.
|
|
161
|
-
|
|
162
|
-
PERFORMANCE OPTIMIZATION
|
|
163
|
-
Use skill: `argent-react-native-optimization`
|
|
164
|
-
When: App feels slow, user asks to optimize, reducing bundle size, improving startup time, fixing re-renders, optimizing lists/images/navigation, or any performance-related task. This is the entry-point skill for all performance work; it delegates to `argent-react-native-profiler` for measurement.
|
|
165
|
-
|
|
166
|
-
INTERACTIVE UI TESTING (ONE-OFF, NOT SAVED)
|
|
167
|
-
Skill: `argent-test-ui-flow`
|
|
168
|
-
When: Running a one-off interact → screenshot → verify check with no saved regression artifact.
|
|
169
|
-
|
|
170
|
-
RECORDING & REPLAYING E2E TESTS
|
|
171
|
-
Use skill: `argent-create-e2e`
|
|
172
|
-
When: Saving or replaying a repeatable path for profiling, A/B comparison, retry, or reuse. For acceptance-driven regression tests, use `argent-qa-e2e`.
|
|
173
|
-
Prompt keywords: record e2e, replay e2e, run e2e, flow, repeat, test X times
|
|
174
|
-
|
|
175
|
-
GENERATED QA REGRESSION TESTS
|
|
176
|
-
Use skill: `argent-qa-e2e`
|
|
177
|
-
When: Saving a test case, ticket, or acceptance criteria as a repeatable regression test. Requires stable evidence and two unchanged full passes. iOS, Android, Chromium, and Vega (D-pad navigation records as `tool: tv-remote` steps); not Apple TV or Android TV.
|
|
178
|
-
Prompt keywords: QA test, regression test, test case, automate an e2e test, write an e2e test, generate a test
|
|
179
|
-
Routing: one-off check → `argent-test-ui-flow`; saved path → `argent-create-e2e`; saved acceptance test → `argent-qa-e2e`.
|
|
180
|
-
|
|
181
|
-
PROPOSING DESIGN VARIANTS FOR HUMAN SELECTION
|
|
182
|
-
Use skill: `argent-lens`
|
|
183
|
-
When: The user asks for design alternatives / options / A-B choices for a screen or component, or you have produced more than one candidate look for an element and want a human to pick before committing. Covers the build → navigate → screenshot → propose_variant loop and the single blocking await_user_selection call. (Gated behind the `argent-lens` flag, off by default; run `argent enable argent-lens` first.)
|
|
184
|
-
Prompt keywords: variant, design option, alternative, A/B, "let me pick", "show me options"
|
|
185
|
-
</skill_routing>
|
|
186
33
|
|
|
187
|
-
|
|
188
|
-
ENVIRONMENT INSPECTION AT SESSION START
|
|
189
|
-
Use subagent: `argent-environment-inspector`
|
|
190
|
-
When:
|
|
191
|
-
- Environment context of the project is not yet known
|
|
192
|
-
- No "Project Environment" section exists in project memory / `MEMORY.md` or you lack information about basic setup workflows
|
|
193
|
-
- Need to determine build commands, startup scripts, metro port, platform support, or QA tooling
|
|
194
|
-
If the subagent already ran this session (result in memory), use that context directly; do NOT re-run.
|
|
195
|
-
Rules:
|
|
196
|
-
- Run the `argent-environment-inspector` subagent if possible. Never call `gather-workspace-data` yourself - do only if subagent is not available.
|
|
197
|
-
- The main agent is responsible for persisting the subagent's JSON result to project memory
|
|
198
|
-
</subagents>
|
|
34
|
+
</availability_check>
|
|
@@ -5,26 +5,18 @@ description: Set up and connect to an Android emulator using argent MCP tools. U
|
|
|
5
5
|
|
|
6
6
|
## 1. Prerequisites
|
|
7
7
|
|
|
8
|
-
-
|
|
9
|
-
- **Android Emulator** on PATH: needed to boot AVDs. If you will only use an already-running emulator or a physical device, adb alone is sufficient.
|
|
10
|
-
- An AVD created via Android Studio or `avdmanager create avd`.
|
|
11
|
-
|
|
12
|
-
Verify with `adb version` and `emulator -list-avds`.
|
|
8
|
+
The Android SDK (platform tools and emulator) and an AVD, created in Android Studio or with `avdmanager create avd`. If `list-devices` returns no Android devices and no `avds`, either no AVD exists or Argent can't find the SDK. Then run `argent config set android.sdkRoot <sdk-path>` and call `list-devices` again after a minute: a failed SDK lookup is cached that long. Exporting `ANDROID_HOME` in your shell doesn't reach the tool-server that is already running.
|
|
13
9
|
|
|
14
10
|
## 2. Setup
|
|
15
11
|
|
|
16
|
-
1. **Find a ready device**: call `list-devices`. Filter for entries with `platform: "android"`. Ready devices (`state: "device"`) come first.
|
|
17
|
-
2. **Boot if needed**: if
|
|
18
|
-
3. **Metro (for React Native)**: once a device is up, run `adb -s <serial> reverse tcp:8081 tcp:8081` so the device can reach Metro on your host. Repeat if the device restarts.
|
|
12
|
+
1. **Find a ready device**: call `list-devices`. Filter for entries with `platform: "android"`. Ready devices (`state: "device"`) come first. If the user named a device, use it. Otherwise pick the first `kind: "emulator"` that fits the task. Take a physical phone (`kind: "device"`) only when the user asks for one. If the result has a `hint` about the adb server, prefix every `adb` command that you run yourself, as the hint shows.
|
|
13
|
+
2. **Boot if needed**: if no such emulator is ready, call `boot-device` with `avdName: <name>` from the same call's `avds` list. `avds` doesn't mark TV images: for a TV task, pick the AVD by its name.
|
|
19
14
|
|
|
20
15
|
## 3. Using the device
|
|
21
16
|
|
|
22
|
-
Pass the Android serial as `udid` to the
|
|
17
|
+
Pass the Android serial as `udid` to the same interaction tools as on iOS. See `argent-device-interact` for interaction tooling and the Android notes at the bottom of that skill. If a React Native app can't reach Metro, see `argent-metro-debugger` §1.
|
|
23
18
|
|
|
24
19
|
## 4. Notes
|
|
25
20
|
|
|
26
|
-
- **Android TV / leanback AVDs** boot through this exact flow
|
|
27
|
-
- Serials are the adb device id. iOS UDIDs and Android serials are not interchangeable, but you do NOT need to tell the tools which platform: dispatch is automatic.
|
|
28
|
-
- `describe` on Android returns a shallower tree than iOS (no accessibility-service equivalent), but covers most tap-target discovery.
|
|
29
|
-
- `reinstall-app` on Android always installs with `-g` so first-launch runtime permissions are pre-granted.
|
|
21
|
+
- **Android TV / leanback AVDs** boot through this exact flow, but `list-devices` tags them `runtimeKind: "tv"` and they are focus-driven: use the `argent-tv-interact` skill, not the gesture tools.
|
|
30
22
|
- To stop the emulator, run `adb -s <serial> emu kill` from a shell (clean shutdown). Never `pkill -9`/`kill -9` qemu: a hard kill leaves the userdata image dirty, after which cold boots can hang for many minutes doing recovery (runaway writes, `boot_completed` never flips). If an image gets into that state, boot once with `-wipe-data` to reset it.
|
|
@@ -13,7 +13,7 @@ For a saved QA test case, ticket, or acceptance criterion, load `argent-qa-e2e`
|
|
|
13
13
|
|
|
14
14
|
- Before creating or changing an e2e test, read [Live authoring](references/live-authoring.md) completely.
|
|
15
15
|
- When polishing, composing, or manually reviewing YAML, read [E2E YAML](references/e2e-yaml.md). For Vega, read its platform limits before recording remote or keyboard tools.
|
|
16
|
-
- E2E tests run on physical iPhones (an iOS `list-devices` entry with kind `"device"`), but replay never auto-binds one, even when no simulator is booted: pass the phone's udid as `device` (CLI `--device`), and only a `connected` phone can run. `pinch`/`rotate` steps
|
|
16
|
+
- E2E tests run on physical iPhones (an iOS `list-devices` entry with kind `"device"`), but replay never auto-binds one, even when no simulator is booted: pass the phone's udid as `device` (CLI `--device`), and only a `connected` phone can run. `pinch`/`rotate` steps need the app drawn in portrait. On hardware the runner tree is the `describe` tree: same ids and roles, no UIView hierarchy. See `argent-ios-device-interact` for the hardware contract.
|
|
17
17
|
- On capture warnings, raw coordinates, unavailable trees, mistimed transitions, overlays, or replay failures, read [Reliability and recovery](references/reliability-and-recovery.md).
|
|
18
18
|
|
|
19
19
|
## Non-negotiable rules
|
|
@@ -67,22 +67,22 @@ YAML selectors and live discovery use different screen projections:
|
|
|
67
67
|
|
|
68
68
|
| Platform | Runner tree | `describe` / `await-ui-element` | Important difference |
|
|
69
69
|
| -------- | --------------------------------------------------------- | ------------------------------- | ------------------------------------------------------ |
|
|
70
|
-
| iOS
|
|
70
|
+
| iOS sim | projected UIView hierarchy | accessibility tree | `native-full-hierarchy` is raw; nodes and roles differ |
|
|
71
71
|
| Android | full accessibility hierarchy | trimmed interactables | Discovery can omit testID containers or merge nodes |
|
|
72
72
|
| Chromium | filtered DOM nodes with id, label, value, click, or focus | shorter DOM walk | Projections and node limits differ (12,000 vs. 5,000) |
|
|
73
73
|
| Vega | toolkit page source | same source | Same elements, different shape |
|
|
74
74
|
|
|
75
|
-
On iOS, Android, and Chromium, an id absent from `describe` can still resolve in an e2e test. Verify it in a scratch fragment. Chromium exposes password fields to the runner as `[password]`; select them by id or role.
|
|
75
|
+
On an iOS simulator, Android, and Chromium, an id absent from `describe` can still resolve in an e2e test. Verify it in a scratch fragment. Chromium exposes password fields to the runner as `[password]`; select them by id or role.
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
For the recorder's cross-tree warning on a recorded wait, see [Live waits and checks](live-authoring.md#live-waits-and-checks). On Vega both read the same source, so a mismatch usually means the screen changed or a `text` check selected a different element.
|
|
78
78
|
|
|
79
|
-
**On iOS, a `launch:` step also decides which app the runner reads.** A successful `launch:` pins later runner-tree reads to that app, so a read probes only that app instead of fanning out over every connected one to find the frontmost. A pinned read still refuses, naming the reason, when the app has no foreground presence left, when it stops answering after an earlier read got through, when its devtools connection dropped, or when the pinned id is a `com.apple.*` system app.
|
|
79
|
+
**On an iOS simulator, a `launch:` step also decides which app the runner reads.** A successful `launch:` pins later runner-tree reads to that app, so a read probes only that app instead of fanning out over every connected one to find the frontmost. A pinned read still refuses, naming the reason, when the app has no foreground presence left, when it stops answering after an earlier read got through, when its devtools connection dropped, or when the pinned id is a `com.apple.*` system app.
|
|
80
80
|
|
|
81
81
|
Any raw `tool:` step ends the pin, because its effect on the screen is opaque to the runner, and reads auto-detect the frontmost app again until the next `launch:` re-pins. A tool that cannot change the foreground app leaves the launched id as an unpinned fallback, which takes the read only when auto-detection times out and the launched app vouches for itself with a probe of its own. `launch-app`, `restart-app`, `reinstall-app`, `open-url`, and `button` drop even that; `launch-app` and `restart-app` replace it with the app they just started, still unpinned. Nested `run:` fragments inherit both the pin and its clearing.
|
|
82
82
|
|
|
83
|
-
So on iOS recording and replay can read different apps, not only different projections: recording has no run state and always auto-detects the frontmost connected app, while a replay read between a `launch:` and the next raw `tool:` step reads the launched app.
|
|
83
|
+
So on an iOS simulator, recording and replay can read different apps, not only different projections: recording has no run state and always auto-detects the frontmost connected app, while a replay read between a `launch:` and the next raw `tool:` step reads the launched app.
|
|
84
84
|
|
|
85
|
-
**On iOS, never copy a `role` from `describe` into a YAML selector.** The runner derives iOS roles from the UIView class name and `describe` from accessibility traits, so a React Native `Pressable` (class `RCTView`) is `AXGroup` to the runner and `AXButton` to `describe`. Select on `id`/`text`, or confirm the role against the runner's own tree.
|
|
85
|
+
**On an iOS simulator, never copy a `role` from `describe` into a YAML selector.** The runner derives iOS roles from the UIView class name and `describe` from accessibility traits, so a React Native `Pressable` (class `RCTView`) is `AXGroup` to the runner and `AXButton` to `describe`. Select on `id`/`text`, or confirm the role against the runner's own tree.
|
|
86
86
|
|
|
87
87
|
When several nodes match, the directive decides:
|
|
88
88
|
|
|
@@ -118,7 +118,7 @@ Directives stop the test on failure and skip later steps. The available directiv
|
|
|
118
118
|
- iOS: unfolded, the UI is landscape. `swipe` and `scroll-to` directions and the reading order stay as the user sees the UI. Coordinates stay in the space of the `describe` frames.
|
|
119
119
|
- iOS: a fold between two angles that are not `closed` or `open` can keep the current panel. The step passes, and the report names the panel. To change panels, fold to `closed` or `open`.
|
|
120
120
|
|
|
121
|
-
Use the launch map for cross-platform tests. A bare launch applies everywhere and becomes an app path on Chromium. The map takes `native:`, `ios:`, `android:`, `vega:`, and `chromium:`. `native:` is one id shared by iOS, Android, and Vega, and a per-platform key overrides it for that platform. `chromium:` accepts a relative or absolute app path. `ios:` also accepts `{ app, args }`;
|
|
121
|
+
Use the launch map for cross-platform tests. A bare launch applies everywhere and becomes an app path on Chromium. The map takes `native:`, `ios:`, `android:`, `vega:`, and `chromium:`. `native:` is one id shared by iOS, Android, and Vega, and a per-platform key overrides it for that platform. `chromium:` accepts a relative or absolute app path. `ios:` also accepts `{ app, args }`; Argent passes `args` to the app at launch. A launch that declares no id for the run's platform is an error, not a cue to switch platforms. A run on a remote simulator uses the `ios:` id, or the `native:` id when the map has no `ios:` key, so no test needs a key for a remote run. On an iOS simulator, a successful launch also pins later tree reads to that app until the next raw `tool:` step, so read [The runner tree is not the discovery tree](#the-runner-tree-is-not-the-discovery-tree) when a read describes the wrong screen.
|
|
122
122
|
|
|
123
123
|
```yaml
|
|
124
124
|
- launch: { native: com.acme.app, chromium: ../../app }
|
|
@@ -156,9 +156,9 @@ Only the direction presets carry OS-edge margins. A resolved `from` point is use
|
|
|
156
156
|
|
|
157
157
|
On Chromium a swipe is a mouse drag (`gesture-drag`), so a `from` on an `<img>`, an `<a href>` or a `draggable="true"` node starts the browser's native drag-and-drop: the page gets `pointerdown` then `pointercancel` and sees no travel. On Vega, `swipe` fails upfront like the other touch directives.
|
|
158
158
|
|
|
159
|
-
`type` presses Enter in a second `keyboard` call unless `submit: false`. A polished focus tap plus one text-only `keyboard` call usually needs `submit: false`. Store external values as `{{secret:NAME}}
|
|
159
|
+
`type` presses Enter in a second `keyboard` call unless `submit: false`. A polished focus tap plus one text-only `keyboard` call usually needs `submit: false`. Store external values as `{{secret:NAME}}`; the runner resolves them from the same sources as the `keyboard` tool. The runner redacts every resolved value, so do not use a placeholder for content a report must show.
|
|
160
160
|
|
|
161
|
-
A **selector-less gesture** (a coordinate `tap`/`long-press`/`swipe`, or a `pinch`/`rotate` with no `on:`) resolves no frame, so a tree source it cannot read does not fail it. It settles best effort, dispatches anyway, and the step **passes carrying a warning** that quotes the source's own error. That green says the gesture was sent, not that it landed: one aimed at a moving element can miss it entirely. Restore the tree source, usually by relaunching the app so the instrumentation loads. Accept the warning only where the app serves no tree at all, and put an explicit `wait:` before a gesture that follows a transition
|
|
161
|
+
A **selector-less gesture** (a coordinate `tap`/`long-press`/`swipe`, or a `pinch`/`rotate` with no `on:`) resolves no frame, so a tree source it cannot read does not fail it. It settles best effort, dispatches anyway, and the step **passes carrying a warning** that quotes the source's own error. That green says the gesture was sent, not that it landed: one aimed at a moving element can miss it entirely. Restore the tree source, usually by relaunching the app so the instrumentation loads. Accept the warning only where the app serves no tree at all, and put an explicit `wait:` before a gesture that follows a transition: after the first such gesture, later ones skip the settle window until a tree read succeeds again or the app relaunches.
|
|
162
162
|
|
|
163
163
|
## Verification conditions
|
|
164
164
|
|
|
@@ -209,7 +209,7 @@ It **never fails a run.** Every outcome short of a clean settle passes with a wa
|
|
|
209
209
|
- **a small part of it was still changing**: a spinner, caret, or progress dot moved through the hold. Too small to count as the screen moving, so the settle completed anyway.
|
|
210
210
|
- **the screen was still for the last Nms**: the wait ran out mid-hold, so no settle was confirmed. It names the term that was short: a second agreeing interval, or the rest of `stableFor`. Raise this step's `timeout:`, because the wait was too short rather than the screen too busy.
|
|
211
211
|
- **the tree stayed empty**: the screen rendered no accessible content: a canvas or video surface, or a screen that never arrived.
|
|
212
|
-
- **settled on the UI tree alone**: no screenshot pair could be read, so presentation-layer animation was never waited out.
|
|
212
|
+
- **settled on the UI tree alone**: no screenshot pair could be read, so presentation-layer animation was never waited out. Inspect the capture path rather than the app's rendering.
|
|
213
213
|
- **too few reads**: a settle needs three reads across two intervals and this step got fewer, so it ended with no evidence either way.
|
|
214
214
|
|
|
215
215
|
Only a tree source this step could not read stops the run, as an errored step: one still failing when the wait ends, one that wedges after answering, one that answers with an empty tree it flags as degraded (an unattached Vega toolkit, an AX service asking to be relaunched), or one that never answers (raise `timeout` before suspecting the app). The run is then not ok and every later step is skipped. A single failed read is not that: the hold restarts from the next good read. The same outage stops no [selector-less gesture](#directives), which needs no frame and passes with its own warning instead.
|
|
@@ -241,8 +241,6 @@ A `run:` target is a YAML path resolved against the directory of the test file c
|
|
|
241
241
|
|
|
242
242
|
## Local scripts
|
|
243
243
|
|
|
244
|
-
Use a local `.mjs` script only when the user requests one. Record it with `e2e-add-script` at the point where it must run.
|
|
245
|
-
|
|
246
244
|
```yaml
|
|
247
245
|
- script: { path: ../../scripts/seed-order.mjs }
|
|
248
246
|
- script: { path: ../../scripts/seed-order.mjs, timeout: 60000 }
|
|
@@ -250,13 +248,10 @@ Use a local `.mjs` script only when the user requests one. Record it with `e2e-a
|
|
|
250
248
|
|
|
251
249
|
Use the map form shown above. A bare `script: scripts/seed.mjs` is invalid.
|
|
252
250
|
|
|
253
|
-
|
|
254
|
-
- **`timeout`** is optional and uses milliseconds. The default is 30000. The minimum is 100.
|
|
251
|
+
`path` is relative to the test file that contains the step. Include `.mjs` and match the file name's letter case. `timeout` is in milliseconds, as in `e2e-add-script`.
|
|
255
252
|
|
|
256
253
|
Over a link (`argent link` or `ARGENT_TOOLS_URL`, also to 127.0.0.1), `e2e-add-script` refuses the call, and a replay rejects a test with a `script:` step. Record and replay a test with a script without a link.
|
|
257
254
|
|
|
258
|
-
If a script fails, check its changes before you retry.
|
|
259
|
-
|
|
260
255
|
## Snapshots and CLI runs
|
|
261
256
|
|
|
262
257
|
`argent e2e run <name> [--device <id>] [--platform ios|android|chromium|vega|ios-remote] [--update-baselines] [--output <dir>] [--json]` runs without an LLM and exits non-zero on failure.
|
|
@@ -267,7 +262,7 @@ Do not use a snapshot as the only proof of navigation, persistence, data, access
|
|
|
267
262
|
|
|
268
263
|
Baselines live beside the test, under `.argent/e2e/__baselines__/<name>/` and are keyed by platform and full-capture geometry; `cropOn` also contributes its selector. A run on a remote simulator uses `ios` in the key, so it uses the same baseline as a local iOS run with the same capture geometry. Seed from a known-good state with `--update-baselines`. A test that a `tool: e2e-execute` step runs keeps its own baselines, and `--update-baselines` updates them too unless the step sets `updateBaselines` itself. A run on a remote simulator with `--update-baselines` rewrites the same baseline file that a local run uses, and its step reason says that a remote simulator wrote it. Inspect every baseline and require user review. Do not commit it yourself. Baseline creation or update is not a test pass. Never update a baseline only to make a diff pass. The default `maxMismatch` is 0.5 percent.
|
|
269
264
|
|
|
270
|
-
Pin `--platform` and `--device` for iOS, Android, or Vega. For Chromium the device class is the window's own pixel size, which the app sets and no launch argument changes: pass `--platform chromium` and omit `--device` so the runner boots the declared app path instead of attaching to a running window of another size. A window sized from host or session state produces a key CI cannot reproduce, and the step fails for a missing baseline. The runner pins mobile status bars during visual runs. `--output <dir>` writes failed
|
|
265
|
+
Pin `--platform` and `--device` for iOS, Android, or Vega. For Chromium the device class is the window's own pixel size, which the app sets and no launch argument changes: pass `--platform chromium` and omit `--device` so the runner boots the declared app path instead of attaching to a running window of another size. A window sized from host or session state produces a key CI cannot reproduce, and the step fails for a missing baseline. The runner pins mobile status bars during visual runs. `--output <dir>` writes failed snapshots' images and failed steps' screenshots under `<dir>/<name>/` for CI artifact upload.
|
|
271
266
|
|
|
272
267
|
## YAML safety
|
|
273
268
|
|
|
@@ -23,28 +23,17 @@ Read this file before creating or changing an e2e test. Exercise the saved path
|
|
|
23
23
|
|
|
24
24
|
## Recorder contract
|
|
25
25
|
|
|
26
|
-
`e2e-add-step.command` is an MCP tool name. `args` is a JSON string, not an object. Omit `args` for a no-argument tool.
|
|
27
|
-
|
|
28
|
-
```text
|
|
29
|
-
command: "gesture-tap"
|
|
30
|
-
args: "{\"udid\":\"DEVICE\",\"x\":0.5,\"y\":0.35}"
|
|
31
|
-
```
|
|
32
|
-
|
|
33
26
|
A recorded `e2e-execute` has two names. The top-level `name` identifies the recording. `args.name` identifies the sibling test captured as `run:`.
|
|
34
27
|
|
|
35
|
-
When the user requests a script, call `e2e-add-script` at the point where it must run. Read [E2E YAML: Local scripts](e2e-yaml.md#local-scripts) first. If the call fails, check its changes before you retry.
|
|
36
|
-
|
|
37
28
|
Over a link, `e2e-add-step` refuses a call whose step a replay over the same link rejects, and runs nothing. It also refuses an `e2e-execute` call whose test does not pass. That test can have changed the device before it stopped. In both cases the recorder records no step. See [Replay](#replay) for the steps that a replay over a link rejects.
|
|
38
29
|
|
|
39
30
|
Obey these lifecycle rules:
|
|
40
31
|
|
|
41
|
-
1.
|
|
42
|
-
2.
|
|
43
|
-
3.
|
|
44
|
-
4.
|
|
45
|
-
5.
|
|
46
|
-
6. Inspect `toolResult`, `message`, and `recorded` after each call. A call that errors records nothing, but a call that returns normally while reporting an unmet condition **does** append the step, and `message` says the step was added either way. A failed `e2e-add-script` call appends nothing. `await-ui-element` is the case that turns up in practice (see [Live waits and checks](#live-waits-and-checks)). Only `e2e-start-recording` and `e2e-finish-recording` return the whole YAML as `e2eTestFile`. A step call returns `recorded` (one summary line for the step it appended) plus a running `stepCount`. Read `recorded`: the recorder does not always store the tool call you made, and that line is where a rewrite shows up. To see the whole file mid-recording, read it at `savedTo`. A `savedTo` that comes back `null` means the write failed on your side. The step is still in the recording, so continue: the next step rewrites the whole file, and `e2e-finish-recording` returns `e2eTestFile` regardless.
|
|
47
|
-
7. Edit or reorder the YAML only after `e2e-finish-recording`. A recording over a link, also to 127.0.0.1, overwrites edits made during the recording.
|
|
32
|
+
1. Choose a name unique to the task: another caller can take over the same `name` + `project_root` pair without an ownership check. The pair is keyed by the file the filesystem resolves to, not the spelling you passed, so a differently-cased name or a symlinked `.argent/e2e` collides too. That collision is reported: the second start says `restarted`, and the first recording's next call fails naming both spellings.
|
|
33
|
+
2. Treat `e2e-start-recording` as destructive. It truncates the named YAML even when it holds a finished or committed test. `restarted` reports only a displaced live take.
|
|
34
|
+
3. If a call says the recording is inactive, do not restart under that name. The completed take can still be on disk. Copy it aside or record under a fresh name.
|
|
35
|
+
4. Read `recorded` after each call. The recorder does not always store the tool call you made, and that line is where a rewrite shows up. A call that returns normally while reporting an unmet condition **does** append the step; `await-ui-element` is the case that turns up in practice (see [Live waits and checks](#live-waits-and-checks)). To see the whole file mid-recording, read it at `savedTo`. A `null` `savedTo` means only the write on your side failed: the step is still in the recording, the next step rewrites the whole file, and `e2e-finish-recording` returns `e2eTestFile` regardless.
|
|
36
|
+
5. Edit or reorder the YAML only after `e2e-finish-recording`.
|
|
48
37
|
|
|
49
38
|
## Start in the correct order
|
|
50
39
|
|
|
@@ -64,7 +53,7 @@ On iOS, only `restart-app` guarantees an instrumented launch. `launch-app` can f
|
|
|
64
53
|
|
|
65
54
|
**The app sets the window size; no boot argument overrides it.** Electron ignores `--window-size`: the size comes from the app's own `BrowserWindow` options, and Argent never resizes the window. Boot a fresh target with `boot-device` and `electronAppPath`, then take one `screenshot` and record its pixel dimensions: that capture size is the snapshot device class ([E2E YAML: Snapshots](e2e-yaml.md#snapshots-and-cli-runs)) and must match when CI replays. If the app sizes its window from host or session state, say so in the report.
|
|
66
55
|
|
|
67
|
-
After boot, start the recorder before the first in-app action. Record the first-screen wait. `restart-app` has no Chromium support, so
|
|
56
|
+
After boot, start the recorder before the first in-app action. Record the first-screen wait. `restart-app` has no Chromium support, so a recorded Chromium test is a fragment until polish writes its launch in (and removes any `executionPrerequisite` the recording declared). During polish, add the matching launch:
|
|
68
57
|
|
|
69
58
|
```yaml
|
|
70
59
|
steps:
|
|
@@ -74,7 +63,7 @@ steps:
|
|
|
74
63
|
args: ["--enable-feature-flag"]
|
|
75
64
|
```
|
|
76
65
|
|
|
77
|
-
|
|
66
|
+
A relative path resolves from the folder of the test being run. Copy the live boot arguments verbatim, and omit `args` when the boot passed none. This packaging exception represents the boot already exercised live. It does not permit a rehearsed UI path.
|
|
78
67
|
|
|
79
68
|
### Fragments
|
|
80
69
|
|
|
@@ -88,8 +77,8 @@ Reach each screen through the app's UI. Do not replace tested navigation with `o
|
|
|
88
77
|
|
|
89
78
|
For every action:
|
|
90
79
|
|
|
91
|
-
1. **Discover without mutation.** Use `describe`, iOS native discovery,
|
|
92
|
-
2. **Choose a durable target.** Prefer a stable id, then stable text or an accessibility label. On iOS, use native discovery for ids that trimmed accessibility output omits
|
|
80
|
+
1. **Discover without mutation.** Use `describe`, iOS native discovery, or `screenshot`. Do not record discovery or `debugger-*` calls: `port` is not a device-bind key, so a recorded one replays against whatever Metro owns that port.
|
|
81
|
+
2. **Choose a durable target.** Prefer a stable id, then stable text or an accessibility label. On iOS, use native discovery for ids that trimmed accessibility output omits; on Android React Native, `debugger-component-tree`.
|
|
93
82
|
3. **Add an echo.** Name the current state, action, and expected outcome before the action can fail.
|
|
94
83
|
4. **Execute through `e2e-add-step`.** Inspect the result and the `recorded` line immediately.
|
|
95
84
|
5. **Verify immediately.** Record outcome checks when their states first appear. After navigation, prove identity then readiness: record the identity check live, and add the readiness gate during polish.
|
|
@@ -114,10 +103,10 @@ Without step 1, `hidden` also passes for a typo or an element that never existed
|
|
|
114
103
|
|
|
115
104
|
### Taps
|
|
116
105
|
|
|
117
|
-
`e2e-add-step` cannot receive a YAML selector directly. Discover the element first, then record `gesture-tap` at its frame center; the live coordinates are transport for the gesture, not a final locator. The recorder reads the pre-tap tree and derives the selector in a fixed order (`id`, then `text`, then `role`), giving three outcomes. Read the `recorded` line after every tap
|
|
106
|
+
`e2e-add-step` cannot receive a YAML selector directly. Discover the element first, then record `gesture-tap` at its frame center; the live coordinates are transport for the gesture, not a final locator. The recorder reads the pre-tap tree and derives the selector in a fixed order (`id`, then `text`, then `role`), giving three outcomes. Read the `recorded` line after every tap. It names the derived form (a selector map, or the kept point):
|
|
118
107
|
|
|
119
108
|
1. **`tap: { id: ... }` or `tap: { text: ... }`**: the good case.
|
|
120
|
-
2. **`tap: { role: ... }`,
|
|
109
|
+
2. **`tap: { role: ... }`, with a warning.** An icon-only button with neither id nor visible label lands here. `role` matches as a case-insensitive substring, so a replay screen holding a second control of that role can win the [ranking](e2e-yaml.md#the-runner-tree-is-not-the-discovery-tree) and the tap reports a pass on the wrong control.
|
|
121
110
|
3. **A kept raw point**, with a warning naming the reason and the retarget.
|
|
122
111
|
|
|
123
112
|
Treat outcomes 2 and 3 alike. Restore the source screen with direct MCP calls, record a corrected tap, then remove the weak step after finishing. Keep a point or a bare role only through the [coordinate fallback gate](reliability-and-recovery.md#coordinate-fallback-gate).
|
|
@@ -126,11 +115,11 @@ Never tap the on-screen keyboard through the recorder. Some platforms expose it
|
|
|
126
115
|
|
|
127
116
|
### Typing
|
|
128
117
|
|
|
129
|
-
Record the focus tap, then record `keyboard` with `text`.
|
|
118
|
+
Record the focus tap, then record `keyboard` with `text`. To submit, record a second `keyboard` step with `key: "enter"`. Verify the complete value with `describe` or an app validation marker.
|
|
130
119
|
|
|
131
120
|
**Never `describe` or `screenshot` a non-secure field you just filled from `{{secret:…}}`.** Only a password field is redacted; a plain text input hands the resolved value back into your context, and an API key or token typed into one is the ordinary case. Submit or navigate away first, then verify the resulting screen.
|
|
132
121
|
|
|
133
|
-
**`describe`
|
|
122
|
+
**`describe` marks the field being typed into as `focused` on Chromium and the iOS simulator.** There, read it before recording `keyboard`. Elsewhere, the value check afterwards is what proves the keys landed.
|
|
134
123
|
|
|
135
124
|
If characters are lost, restore the field with direct calls. Do not record a duplicate typing step. Polish the valid pair into `type:`. Its replay focus wait reads the runner's own tree, which does report focus on iOS, Android, and Chromium, but an unconfirmed poll falls through to typing rather than failing, so retain the committed-value check. Store credentials as `{{secret:NAME}}`. Never record a literal credential.
|
|
136
125
|
|
|
@@ -146,27 +135,13 @@ For every retained raw gesture, add an echo and a recorded result check.
|
|
|
146
135
|
|
|
147
136
|
### Live waits and checks
|
|
148
137
|
|
|
149
|
-
Record `await-ui-element` through `e2e-add-step`. The recorder writes the step even when `toolResult.success` is false
|
|
150
|
-
|
|
151
|
-
- `unmet`: The tree was readable, but the condition was false. Restore the expected state or correct the selector or timeout. Record the check again, then delete the failed step after `e2e-finish-recording`.
|
|
152
|
-
- `unreadable`: The wait ended without a trustworthy read. Restore the tree source and record the check again. Keep the failed step: the condition is unknown, not false.
|
|
153
|
-
- `cancelled`: The caller stopped the wait. Record the check again. Keep the failed step: the condition is unknown, not false.
|
|
154
|
-
|
|
155
|
-
Only `unmet` disproves the condition. Never delete a step during the recording.
|
|
156
|
-
|
|
157
|
-
A stale `hidden` whose selector matches nothing replays as a silent pass: the unfalsifiable gate that [Record absence in three steps](#record-absence-in-three-steps) exists to prevent. Never proceed as though the gate passed. See the `await-ui-element` section of `argent-device-interact` for the full live condition and selector reference.
|
|
138
|
+
Record `await-ui-element` through `e2e-add-step`. The recorder writes the step even when `toolResult.success` is false, and its warning names the cause and what to do. Delete a failed wait only when the cause is `unmet`, after `e2e-finish-recording`; never during the recording.
|
|
158
139
|
|
|
159
|
-
A
|
|
140
|
+
A stale `hidden` whose selector matches nothing replays as a silent pass: the unfalsifiable gate that [Record absence in three steps](#record-absence-in-three-steps) exists to prevent. Never proceed as though the gate passed.
|
|
160
141
|
|
|
161
|
-
The live tool and e2e runner use [different trees](e2e-yaml.md#the-runner-tree-is-not-the-discovery-tree). After a successful wait, the recorder checks the same condition on the runner tree:
|
|
142
|
+
The live tool and e2e runner use [different trees](e2e-yaml.md#the-runner-tree-is-not-the-discovery-tree). After a successful wait, the recorder checks the same condition on the runner tree and warns when it does not hold there or could not be checked; the warning says what to rule out. If the trees really differ, keep the raw `await-ui-element` step: it replays on the tree it passed on.
|
|
162
143
|
|
|
163
|
-
-
|
|
164
|
-
- Mismatch: For `text`, first rule out a selector that matches more than one element. Then rule out a changed screen. If the trees really differ, keep the raw `await-ui-element` step: it replays on the tree it passed on.
|
|
165
|
-
- Unreadable, slow, or cancelled check: The conversion is unknown. Restore the source or re-record before conversion.
|
|
166
|
-
|
|
167
|
-
A warning does not reject the step. `e2e-finish-recording` repeats each warning below its step and reports dropped warnings.
|
|
168
|
-
|
|
169
|
-
Do not edit YAML before finishing because edits can drop recorded verdicts. If the finish reports drops, record the waits again. Replay every conversion. Keep a raw tool only for `pollIntervalMs`, `bundleId`, or a cross-tree mismatch.
|
|
144
|
+
A warning does not reject the step. If `e2e-finish-recording` reports dropped warnings, record those waits again. Replay every conversion. Keep a raw tool only for `pollIntervalMs`, `bundleId`, or a cross-tree mismatch.
|
|
170
145
|
|
|
171
146
|
### Wrong turns
|
|
172
147
|
|
|
@@ -253,7 +228,7 @@ The condition grep matches a condition key with a scalar after it (`visible: Sav
|
|
|
253
228
|
Resolve every hit and confirm:
|
|
254
229
|
|
|
255
230
|
- Every element action uses a stable selector unless the fallback gate cleared and documented it.
|
|
256
|
-
- **No `role:` stands as the only key under a `tap:`/`long-press:`.**
|
|
231
|
+
- **No `role:` stands as the only key under a `tap:`/`long-press:`.** It comes from the recorder's last-resort fallback or a hand edit. Replace it, or clear it through the fallback gate. A `role:` beside another field or a scope (`within`, `after`, `next`) is deliberate and needs no defence.
|
|
257
232
|
- Every element-seeking gesture became `scroll-to`.
|
|
258
233
|
- No device id or literal credential remains.
|
|
259
234
|
- Every selector-bearing condition uses an explicit selector map without positional or data-derived values.
|
|
@@ -268,30 +243,15 @@ Resolve every hit and confirm:
|
|
|
268
243
|
|
|
269
244
|
Run `e2e-execute` on the complete YAML with the absolute project root. For a fragment, verify its prerequisite before setting `prerequisiteAcknowledged: true`.
|
|
270
245
|
|
|
271
|
-
`e2e-execute`
|
|
272
|
-
|
|
273
|
-
Over `argent link` or `ARGENT_TOOLS_URL`, the client sends the test file, its `run:` fragments, the tests that its `tool: e2e-execute` steps name, the snapshot baselines of each run and the file arguments of its `tool:` steps with the call. These steps work over a link:
|
|
274
|
-
|
|
275
|
-
- `run:` fragments and the tests that `tool: e2e-execute` steps name, when they are under `project_root`, under its `.argent/e2e/` or `.argent/flows/`, or beside the test file. Keep them there.
|
|
276
|
-
- `snapshot:` steps in the test and in its fragments. The baselines stay in the project. With `updateBaselines: true`, the client writes each new baseline when the run ends. A `baseline not written` line in the report means that the client did not save that baseline: fix the reason in the line and run again.
|
|
277
|
-
- A `tool:` step whose file argument is an absolute path to a `.png` or `.yaml` file, such as `baselinePath` of `screenshot-diff`. Keep the real file under the project root or beside the test file, not behind a symlink to another place. Otherwise the step reports `error` when it runs, after the earlier steps acted.
|
|
278
|
-
- A `tool: e2e-execute` step that names its test with `name` and an absolute `project_root` without a `..` segment. Keep the test that the step names under the project on the client, and spell `name` in the letter case of its file. That test uses its own baselines. A replay with `updateBaselines` also updates them, unless the step sets `updateBaselines` itself.
|
|
246
|
+
Over `argent link` or `ARGENT_TOOLS_URL`, the client uploads the test and the files its steps need. `e2e-execute`'s description lists what travels and which steps a linked run rejects (`script:`, recording tools, directory, app or output-directory arguments such as `reinstall-app`'s, relative or non-`.png`/`.yaml` file arguments, file paths built from several arguments). Beyond that list:
|
|
279
247
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
- `
|
|
283
|
-
-
|
|
284
|
-
- a `tool:` step with a relative file path, or a file other than `.png` or `.yaml`
|
|
285
|
-
- a `tool:` step whose tool builds the file path from several arguments, such as `e2e-read-prerequisite` with `name`
|
|
286
|
-
- a `tool: e2e-execute` step with `e2e_test_path`, or with `name` and a relative `project_root` or one with a `..` segment
|
|
287
|
-
- a `tool:` step that records an e2e test
|
|
288
|
-
|
|
289
|
-
The tool-server checks the test, its fragments and the tests that it runs before the first step. The error lists each step that does not work over a link, and each `run:` or `tool: e2e-execute` step whose test the client could not send, with the reason. A fragment or a test that does not exist fails its step when the step runs. Run a test that needs these steps with no link and no `ARGENT_TOOLS_URL`, on the computer that runs the tool-server.
|
|
248
|
+
- Keep every file a step needs (`run:` fragments, tests named by `tool: e2e-execute`, `.png`/`.yaml` arguments such as `screenshot-diff`'s `baselinePath`) as a real file under `project_root`, its `.argent/e2e/` or `.argent/flows/`, or beside the test file, not behind a symlink to another place. Otherwise the step reports `error` when it runs, after the earlier steps acted.
|
|
249
|
+
- A `tool: e2e-execute` step works over a link only with `name` and an absolute `project_root` without a `..` segment. Spell `name` in the letter case of its file.
|
|
250
|
+
- A `baseline not written` line in the report means that the client did not save that baseline: fix the reason in the line and run again.
|
|
251
|
+
- The tool-server rejects unsupported steps before the first step, listing each with the reason; a fragment or test that does not exist fails only when its step runs. Run a test that needs a rejected step with no link and no `ARGENT_TOOLS_URL`, on the computer that runs the tool-server.
|
|
290
252
|
|
|
291
253
|
Manual rescue invalidates the pass. An `errored` step was never evaluated: an `idle` wait whose tree source could not be read, a step that threw, an unresolvable `run:` target, or a `launch:` that did not start the app. Read the reason: most name the environment, but a failed `launch:` is a verdict about the app. Unconfirmed focus is not in this class at all: the replay focus poll has no failure return, so a `type:` step whose focus was never confirmed is scored a **pass**, and only the value check after typing catches it.
|
|
292
254
|
|
|
293
|
-
**A passing step that carries a `warning` is a finding, not noise.** `await: { idle: true }` raises [six different warnings](e2e-yaml.md#idle-readiness) and they do not share one meaning
|
|
294
|
-
|
|
295
|
-
A [selector-less gesture](e2e-yaml.md#directives) raises a warning of a different shape, not one of those six: a tree-source outage left it unsettled, so it dispatched blind and the green says only that the gesture was sent. Restore the source, usually by relaunching the app so the instrumentation loads. Accept it only where the app serves no tree at all, such as the [injection-free iOS form](reliability-and-recovery.md#terminally-non-injectable-ios-apps).
|
|
255
|
+
**A passing step that carries a `warning` is a finding, not noise.** `await: { idle: true }` raises [six different warnings](e2e-yaml.md#idle-readiness) and they do not share one meaning or one repair. No report separates intended motion from a load that never finished. Read which one it is, look at that screen, disclose what you found, and confirm the following step targets a stable element rather than stillness.
|
|
296
256
|
|
|
297
|
-
|
|
257
|
+
A [selector-less gesture](e2e-yaml.md#directives) warns in a different shape: it dispatched blind during a tree-source outage, so the green says only that the gesture was sent. Restore the source, usually by relaunching the app. Accept it only where the app serves no tree at all, such as the [injection-free iOS form](reliability-and-recovery.md#terminally-non-injectable-ios-apps).
|