zeno-mobile-runner 0.1.2
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/CHANGELOG.md +497 -0
- package/CONTRIBUTING.md +42 -0
- package/FEATURES.md +111 -0
- package/LICENSE +21 -0
- package/README.md +176 -0
- package/SECURITY.md +34 -0
- package/build.zig +38 -0
- package/build.zig.zon +7 -0
- package/clients/README.md +149 -0
- package/clients/go/README.md +24 -0
- package/clients/go/examples/fake-session/main.go +93 -0
- package/clients/go/go.mod +3 -0
- package/clients/go/zmr/client.go +432 -0
- package/clients/kotlin/README.md +35 -0
- package/clients/kotlin/build.gradle.kts +35 -0
- package/clients/kotlin/settings.gradle.kts +15 -0
- package/clients/kotlin/src/main/kotlin/dev/zmr/FakeSession.kt +86 -0
- package/clients/kotlin/src/main/kotlin/dev/zmr/ZmrClient.kt +67 -0
- package/clients/python/README.md +29 -0
- package/clients/python/examples/fake_session.py +48 -0
- package/clients/python/pyproject.toml +13 -0
- package/clients/python/zmr_client.py +202 -0
- package/clients/rust/Cargo.lock +107 -0
- package/clients/rust/Cargo.toml +10 -0
- package/clients/rust/README.md +19 -0
- package/clients/rust/examples/fake_session.rs +70 -0
- package/clients/rust/src/lib.rs +461 -0
- package/clients/swift/Package.swift +16 -0
- package/clients/swift/README.md +36 -0
- package/clients/swift/Sources/ZMRClient/ZMRClient.swift +114 -0
- package/clients/swift/Sources/ZMRFakeSession/main.swift +86 -0
- package/clients/typescript/README.md +34 -0
- package/clients/typescript/examples/fake-session.mjs +36 -0
- package/clients/typescript/index.d.ts +144 -0
- package/clients/typescript/index.mjs +192 -0
- package/clients/typescript/package.json +8 -0
- package/docs/adr/0001-agent-native-runner-boundary.md +31 -0
- package/docs/adr/0002-app-local-zmr-contract.md +39 -0
- package/docs/adr/0003-ios-simulator-xctest-shim.md +41 -0
- package/docs/adr/0004-benchmark-claims-and-baseline-collection.md +37 -0
- package/docs/adr/README.md +12 -0
- package/docs/ai-agents.md +154 -0
- package/docs/app-integration.md +330 -0
- package/docs/benchmarking.md +273 -0
- package/docs/client-installation.md +133 -0
- package/docs/clients.md +98 -0
- package/docs/config.md +175 -0
- package/docs/demo.md +259 -0
- package/docs/frameworks.md +72 -0
- package/docs/install.md +95 -0
- package/docs/npm.md +356 -0
- package/docs/protocol-fixtures/README.md +8 -0
- package/docs/protocol-fixtures/core-session.requests.jsonl +8 -0
- package/docs/protocol-fixtures/core-session.responses.jsonl +8 -0
- package/docs/protocol-versioning.md +65 -0
- package/docs/protocol.md +560 -0
- package/docs/scenario-authoring.md +88 -0
- package/docs/trace-privacy.md +88 -0
- package/docs/troubleshooting.md +256 -0
- package/examples/android-app-auth-probe.json +89 -0
- package/examples/android-app-error-state.json +13 -0
- package/examples/android-app-login-smoke.json +192 -0
- package/examples/android-app-onboarding.json +12 -0
- package/examples/android-app-referral-deep-link.json +12 -0
- package/examples/android-shim-smoke.json +19 -0
- package/examples/demo-failure.json +12 -0
- package/examples/demo-fake.json +14 -0
- package/examples/ios-dev-client-open-link.json +26 -0
- package/examples/ios-dev-client-route-snapshot.json +24 -0
- package/examples/ios-shim-smoke.json +23 -0
- package/examples/ios-smoke.json +9 -0
- package/go.work +3 -0
- package/npm/agents.mjs +183 -0
- package/npm/app-config.mjs +95 -0
- package/npm/build-zmr.mjs +21 -0
- package/npm/commands.mjs +104 -0
- package/npm/generated-files.mjs +50 -0
- package/npm/index.mjs +75 -0
- package/npm/init-app.mjs +80 -0
- package/npm/package-scripts.mjs +72 -0
- package/npm/postinstall.mjs +21 -0
- package/npm/scaffold.mjs +179 -0
- package/npm/scenarios.mjs +93 -0
- package/npm/setup.mjs +69 -0
- package/npm/wizard.mjs +117 -0
- package/npm/zmr.mjs +23 -0
- package/package.json +118 -0
- package/schemas/README.md +26 -0
- package/schemas/action-result.schema.json +27 -0
- package/schemas/capabilities-output.schema.json +98 -0
- package/schemas/devices-output.schema.json +25 -0
- package/schemas/doctor-output.schema.json +51 -0
- package/schemas/explain-output.schema.json +51 -0
- package/schemas/import-output.schema.json +23 -0
- package/schemas/init-output.schema.json +71 -0
- package/schemas/json-rpc.schema.json +55 -0
- package/schemas/release-manifest.schema.json +43 -0
- package/schemas/release-readiness-output.schema.json +127 -0
- package/schemas/run-output.schema.json +43 -0
- package/schemas/scenario.schema.json +128 -0
- package/schemas/schemas-output.schema.json +26 -0
- package/schemas/semantic-snapshot.schema.json +116 -0
- package/schemas/snapshot.schema.json +60 -0
- package/schemas/trace-event.schema.json +14 -0
- package/schemas/trace-manifest.schema.json +59 -0
- package/schemas/validate-output.schema.json +42 -0
- package/schemas/version-output.schema.json +23 -0
- package/schemas/zmr-config.schema.json +75 -0
- package/scripts/android-emulator.sh +126 -0
- package/scripts/assert-ios-physical-ready.sh +213 -0
- package/scripts/benchmark-command.sh +307 -0
- package/scripts/benchmark.sh +359 -0
- package/scripts/benchmark_gate.py +117 -0
- package/scripts/benchmark_result_row.py +88 -0
- package/scripts/compare-benchmarks.py +288 -0
- package/scripts/create-android-demo-app.sh +342 -0
- package/scripts/create-ios-demo-app.sh +261 -0
- package/scripts/demo-android-real.sh +232 -0
- package/scripts/demo-ios-real.sh +270 -0
- package/scripts/demo.sh +464 -0
- package/scripts/device-matrix.sh +338 -0
- package/scripts/ensure-ios-shim-target.rb +237 -0
- package/scripts/install-android-shim.sh +281 -0
- package/scripts/install-ios-shim.sh +589 -0
- package/scripts/pilot-gate.sh +560 -0
- package/scripts/release-readiness.py +838 -0
- package/scripts/release-readiness.sh +91 -0
- package/scripts/run-android-pilot.sh +561 -0
- package/scripts/run-ios-pilot.sh +509 -0
- package/shims/android/README.md +21 -0
- package/shims/android/ZMRShimInstrumentedTest.java +152 -0
- package/shims/android/protocol.md +18 -0
- package/shims/ios/README.md +50 -0
- package/shims/ios/ZMRShim.swift +110 -0
- package/shims/ios/ZMRShimUITestCase.swift +518 -0
- package/shims/ios/protocol.md +74 -0
- package/skills/zmr-mobile-testing/SKILL.md +127 -0
- package/src/android.zig +344 -0
- package/src/android_device_info.zig +99 -0
- package/src/android_emulator.zig +154 -0
- package/src/android_screen_recording.zig +112 -0
- package/src/android_shell.zig +112 -0
- package/src/bundle.zig +124 -0
- package/src/bundle_redaction.zig +272 -0
- package/src/bundle_tar.zig +123 -0
- package/src/cli_devices.zig +97 -0
- package/src/cli_doctor.zig +114 -0
- package/src/cli_import.zig +70 -0
- package/src/cli_info.zig +39 -0
- package/src/cli_init.zig +72 -0
- package/src/cli_output.zig +467 -0
- package/src/cli_run.zig +259 -0
- package/src/cli_serve.zig +287 -0
- package/src/cli_trace.zig +111 -0
- package/src/cli_validate.zig +41 -0
- package/src/command.zig +211 -0
- package/src/config.zig +305 -0
- package/src/config_diagnostics.zig +212 -0
- package/src/config_paths.zig +49 -0
- package/src/device_registry.zig +37 -0
- package/src/doctor.zig +412 -0
- package/src/doctor_hints.zig +52 -0
- package/src/errors.zig +55 -0
- package/src/fake_device.zig +163 -0
- package/src/health.zig +28 -0
- package/src/importer.zig +343 -0
- package/src/importer_json.zig +100 -0
- package/src/importer_model.zig +103 -0
- package/src/ios.zig +399 -0
- package/src/ios_devices.zig +219 -0
- package/src/ios_lifecycle.zig +72 -0
- package/src/ios_shim.zig +242 -0
- package/src/ios_snapshot.zig +20 -0
- package/src/json_fields.zig +80 -0
- package/src/json_rpc.zig +150 -0
- package/src/json_rpc_methods.zig +318 -0
- package/src/json_rpc_observation.zig +31 -0
- package/src/json_rpc_params.zig +52 -0
- package/src/json_rpc_protocol.zig +110 -0
- package/src/json_rpc_trace.zig +73 -0
- package/src/main.zig +131 -0
- package/src/mcp.zig +234 -0
- package/src/mcp_protocol.zig +64 -0
- package/src/mcp_trace.zig +83 -0
- package/src/report.zig +346 -0
- package/src/report_html.zig +63 -0
- package/src/report_values.zig +27 -0
- package/src/run_options.zig +152 -0
- package/src/runner.zig +280 -0
- package/src/runner_actions.zig +109 -0
- package/src/runner_config.zig +6 -0
- package/src/runner_diagnostics.zig +268 -0
- package/src/runner_events.zig +170 -0
- package/src/runner_native.zig +88 -0
- package/src/runner_waits.zig +300 -0
- package/src/scaffold.zig +472 -0
- package/src/scenario.zig +346 -0
- package/src/scenario_fields.zig +50 -0
- package/src/schema_registry.zig +53 -0
- package/src/selector.zig +84 -0
- package/src/semantic.zig +171 -0
- package/src/trace.zig +315 -0
- package/src/trace_json.zig +340 -0
- package/src/trace_summary.zig +218 -0
- package/src/trace_summary_diagnostic.zig +202 -0
- package/src/types.zig +120 -0
- package/src/uiautomator.zig +164 -0
- package/src/validation.zig +187 -0
- package/src/version.zig +22 -0
- package/viewer/app.js +373 -0
- package/viewer/index.html +126 -0
- package/viewer/parser.js +233 -0
- package/viewer/styles.css +585 -0
package/docs/demo.md
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Demo
|
|
2
|
+
|
|
3
|
+
Run the local demo with no emulator, simulator, app, or credentials:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
./scripts/demo.sh
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The script builds `zig-out/bin/zmr`, then runs:
|
|
10
|
+
|
|
11
|
+
- `zmr version`
|
|
12
|
+
- `zmr version --json`
|
|
13
|
+
- `zmr schemas --json`
|
|
14
|
+
- `zmr validate examples/demo-fake.json`
|
|
15
|
+
- `zmr validate examples/demo-failure.json`
|
|
16
|
+
- `zmr validate examples/android-app-onboarding.json`
|
|
17
|
+
- `zmr validate examples/android-app-referral-deep-link.json`
|
|
18
|
+
- `zmr validate examples/android-app-error-state.json`
|
|
19
|
+
- `zmr validate examples/android-shim-smoke.json`
|
|
20
|
+
- `zmr validate examples/ios-smoke.json`
|
|
21
|
+
- `zmr validate examples/ios-dev-client-open-link.json`
|
|
22
|
+
- `zmr validate examples/ios-dev-client-route-snapshot.json`
|
|
23
|
+
- `zmr validate examples/ios-shim-smoke.json`
|
|
24
|
+
- expected-failing `zmr validate --json` output that shows `fieldPath`, `line`,
|
|
25
|
+
and `column` for invalid scenarios covered by `schemas/validate-output.schema.json`
|
|
26
|
+
- `zmr doctor --adb ./tests/fake-adb.sh --xcrun ./tests/fake-xcrun.sh --ios-shim ./tests/fake-ios-shim.sh`
|
|
27
|
+
- `zmr doctor --json` output for a missing Android shim that includes a
|
|
28
|
+
remediation `hint`
|
|
29
|
+
- `zmr doctor --json` output that warns with stable setup `errorCode` values
|
|
30
|
+
when no Android devices, booted iOS simulators, or paired physical iOS
|
|
31
|
+
devices are ready
|
|
32
|
+
- expected-failing `zmr doctor --strict --json` output for the same no-device
|
|
33
|
+
setup, showing how CI can fail without parsing the diagnostics itself
|
|
34
|
+
- `zmr doctor --json --config traces/demo-doctor-config.json` output that
|
|
35
|
+
validates configured smoke scenario files, including an `ios-smoke-scenario` remediation
|
|
36
|
+
for a bad `ios.smokeScenario` and a `zmr validate on the configured Android
|
|
37
|
+
smoke scenario` hint for malformed scenario JSON
|
|
38
|
+
- `zmr doctor --json --config traces/demo-bad-config.json` output that reports
|
|
39
|
+
stable `errorCode` plus `fieldPath` for an invalid app-local config value
|
|
40
|
+
before device setup starts
|
|
41
|
+
- `zmr devices --adb ./tests/fake-adb.sh`
|
|
42
|
+
- `zmr devices --json --adb ./tests/fake-adb.sh`
|
|
43
|
+
- `zmr devices --platform ios --xcrun ./tests/fake-xcrun.sh`
|
|
44
|
+
- `zmr devices --json --platform ios --xcrun ./tests/fake-xcrun.sh`
|
|
45
|
+
- `zmr init --app --json --dir traces/demo-init-app --app-id com.example.demoapp`
|
|
46
|
+
followed by validation and strict config-driven doctor checks from that
|
|
47
|
+
generated app-local workspace
|
|
48
|
+
- `zmr import flow-yaml traces/demo-flow-yaml-flow.yaml --out traces/demo-imported-flow.json --json`
|
|
49
|
+
followed by validation of the generated native ZMR scenario
|
|
50
|
+
- `zmr run examples/demo-fake.json --trace-dir traces/demo-fake-android --json`
|
|
51
|
+
- `scripts/device-matrix.sh --matrix traces/demo-device-matrix.json --trace-root traces/demo-device-matrix`
|
|
52
|
+
- `zmr run examples/demo-failure.json --trace-dir traces/demo-failure --json`
|
|
53
|
+
- `zmr explain traces/demo-failure`
|
|
54
|
+
- `zmr explain traces/demo-failure --json`
|
|
55
|
+
- `zmr serve --transport stdio --trace-dir traces/demo-rpc-session`
|
|
56
|
+
- `node clients/typescript/examples/fake-session.mjs`
|
|
57
|
+
- `python3 clients/python/examples/fake_session.py`
|
|
58
|
+
- `swift run ZMRFakeSession` from `clients/swift`
|
|
59
|
+
- `gradle -p clients/kotlin runFakeSession`
|
|
60
|
+
- `go run ./clients/go/examples/fake-session --zmr ./zig-out/bin/zmr --adb ./tests/fake-adb.sh --trace-dir traces/demo-go-client`
|
|
61
|
+
- `cargo run --manifest-path clients/rust/Cargo.toml --example fake_session -- --zmr ./zig-out/bin/zmr --adb ./tests/fake-adb.sh --trace-dir traces/demo-rust-client`
|
|
62
|
+
- `zmr run examples/ios-smoke.json --platform ios --trace-dir traces/demo-fake-ios`
|
|
63
|
+
|
|
64
|
+
The fake Android flow exercises selector matching and wait/assert trace output.
|
|
65
|
+
The fake device-matrix flow exercises Android, iOS simulator, and physical iOS
|
|
66
|
+
matrix rows without requiring local hardware, producing `matrix.jsonl` and
|
|
67
|
+
`summary.json`.
|
|
68
|
+
The fake failure flow exercises failed trace diagnostics and the terminal
|
|
69
|
+
`zmr explain` summary.
|
|
70
|
+
The fake JSON-RPC flow exercises the agent protocol over stdio, live RPC trace
|
|
71
|
+
recording, `observe.snapshot`, and redacted `trace.export`.
|
|
72
|
+
Doctor output is intentionally structured for setup automation; `--json`
|
|
73
|
+
includes remediation `hint` values for missing or warning checks, and
|
|
74
|
+
`--config` validates app-local smoke scenario files. Add `--strict` when a
|
|
75
|
+
non-`ok` diagnostic should also make the command fail.
|
|
76
|
+
The TypeScript reference client flow exercises the same protocol through the
|
|
77
|
+
client API external agents would use.
|
|
78
|
+
The Python reference client flow verifies the same agent integration path with
|
|
79
|
+
only the Python standard library.
|
|
80
|
+
The Swift and Kotlin reference client flows verify host-side native-language
|
|
81
|
+
agent/test-harness integration for iOS and Android teams.
|
|
82
|
+
The fake Android shim flow exercises shim-backed hierarchy, wait, tap, type,
|
|
83
|
+
hide-keyboard, and snapshot handling.
|
|
84
|
+
The fake iOS flow exercises simulator lifecycle, deep-link opening, screenshot
|
|
85
|
+
artifact capture, log capture, and snapshot trace writing. The fake iOS shim
|
|
86
|
+
flow exercises shim-backed hierarchy, wait, tap, type, hide-keyboard, and
|
|
87
|
+
snapshot handling.
|
|
88
|
+
|
|
89
|
+
Load any generated `.zmrtrace` in `viewer/index.html` to inspect the replay
|
|
90
|
+
timeline, payloads, screenshot, UI tree, selected node details, and raw
|
|
91
|
+
artifacts side-by-side.
|
|
92
|
+
|
|
93
|
+
## Real Android Pilot Demo
|
|
94
|
+
|
|
95
|
+
Run the Android pilot against a sample app test build:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
./scripts/run-android-pilot.sh \
|
|
99
|
+
--app-root /path/to/mobile-app \
|
|
100
|
+
--device emulator-5554
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
To force a known emulator state, direct `zmr run` supports `--android-avd`,
|
|
104
|
+
`--create-avd-if-missing`, `--avd-system-image`, `--avd-device`,
|
|
105
|
+
`--restore-snapshot`, `--reset-emulator`, and `--wait-emulator`. The pilot
|
|
106
|
+
wrapper accepts the same state controls while also building/installing the app.
|
|
107
|
+
Add `--screen-record` to keep a pilot-level MP4 under the trace root:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
./scripts/run-android-pilot.sh \
|
|
111
|
+
--app-root /path/to/mobile-app \
|
|
112
|
+
--device emulator-5554 \
|
|
113
|
+
--avd Small_Phone \
|
|
114
|
+
--reset-emulator \
|
|
115
|
+
--restore-snapshot zmr-clean \
|
|
116
|
+
--screen-record
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The script builds `zmr` when needed, validates both sample scenarios, installs the debug test APK, starts the app's test Metro server, and runs:
|
|
120
|
+
|
|
121
|
+
- `examples/android-app-auth-probe.json`
|
|
122
|
+
- `examples/android-app-login-smoke.json`
|
|
123
|
+
|
|
124
|
+
For each single run it writes:
|
|
125
|
+
|
|
126
|
+
- `auth/report.html`
|
|
127
|
+
- `login-smoke/report.html`
|
|
128
|
+
- `auth.zmrtrace`
|
|
129
|
+
- `auth-redacted.zmrtrace`
|
|
130
|
+
- `login-smoke.zmrtrace`
|
|
131
|
+
- `login-smoke-redacted.zmrtrace`
|
|
132
|
+
- `screenrecord.mp4` when pilot `--screen-record`, `zmr run --screen-record`, or `.zmr/config.json` `artifacts.screenRecording` is enabled
|
|
133
|
+
|
|
134
|
+
Use the redacted bundles for demos outside a trusted local machine:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
open viewer/index.html
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Then load `auth-redacted.zmrtrace` or `login-smoke-redacted.zmrtrace`.
|
|
141
|
+
|
|
142
|
+
Inspect the command plan without touching the emulator:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
./scripts/run-android-pilot.sh --dry-run --skip-emulator --skip-metro --app-root <android-app-root>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Run repeated benchmark passes:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
./scripts/run-android-pilot.sh \
|
|
152
|
+
--app-root <android-app-root> \
|
|
153
|
+
--device emulator-5554 \
|
|
154
|
+
--runs 20 \
|
|
155
|
+
--min-pass-rate 100 \
|
|
156
|
+
--max-failures 0
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`<trace-root>/metro.log` may contain sensitive app output from the sample app test environment. Do not publish raw Metro logs.
|
|
160
|
+
|
|
161
|
+
## Real Android Demo APK
|
|
162
|
+
|
|
163
|
+
To generate a small public native Android app and matching smoke scenario:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npx zmr-demo-android --out /tmp/zmr-android-demo --device emulator-5554 --avd <avd-name>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The wrapper builds a signed debug APK with Android SDK command-line tools
|
|
170
|
+
only, boots the named AVD when the requested device is not ready, installs the
|
|
171
|
+
app, and runs the generated smoke scenario. To inspect or customize the
|
|
172
|
+
generated app before running manually:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npx zmr-create-android-demo-app --out /tmp/zmr-android-demo
|
|
176
|
+
adb install -r /tmp/zmr-android-demo/build/app-debug.apk
|
|
177
|
+
zmr run /tmp/zmr-android-demo/.zmr/android-smoke.json \
|
|
178
|
+
--device emulator-5554 \
|
|
179
|
+
--app-id com.example.mobiletest \
|
|
180
|
+
--trace-dir /tmp/zmr-android-demo/traces/android-demo
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The scenario launches the app, waits for visible text, taps a button, types
|
|
184
|
+
text into a field, and captures a trace-backed snapshot.
|
|
185
|
+
|
|
186
|
+
## Real iOS Simulator Demo
|
|
187
|
+
|
|
188
|
+
To generate a small public demo app with the ZMR XCTest shim already installed:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
npx zmr-demo-ios --out /tmp/zmr-ios-demo --device booted --cleanup-build-products
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
That command creates the demo app, builds it, installs it on the requested
|
|
195
|
+
simulator, runs the plain iOS smoke and selector-grade shim smoke, then writes
|
|
196
|
+
reports and redacted `.zmrtrace` bundles. `--cleanup-build-products` removes
|
|
197
|
+
generated Xcode `DerivedData` after the pilot so repeated demo runs keep their
|
|
198
|
+
footprint small. When `--device booted` is used and no
|
|
199
|
+
simulator is running, the command boots an available iOS simulator first. If
|
|
200
|
+
the first available simulator fails to boot because CoreSimulator cannot start
|
|
201
|
+
`launchd_sim`, the script tries the next available iOS simulator before failing.
|
|
202
|
+
|
|
203
|
+
To inspect or customize the generated app before running the pilot manually:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npx zmr-create-ios-demo-app --out /tmp/zmr-ios-demo
|
|
207
|
+
cd /tmp/zmr-ios-demo
|
|
208
|
+
xcodebuild -project ios/ZMRDemo.xcodeproj -scheme ZMRDemo -destination 'generic/platform=iOS Simulator' -derivedDataPath DerivedData build
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Then boot a simulator and run from the ZMR repo:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
scripts/run-ios-pilot.sh \
|
|
215
|
+
--app-root /tmp/zmr-ios-demo \
|
|
216
|
+
--app-path /tmp/zmr-ios-demo/DerivedData/Build/Products/Debug-iphonesimulator/ZMRDemo.app \
|
|
217
|
+
--app-id com.example.mobiletest \
|
|
218
|
+
--device booted \
|
|
219
|
+
--ios-shim /tmp/zmr-ios-demo/.zmr/ios-shim
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Build the app for an iOS simulator, boot a simulator, then run:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
./scripts/run-ios-pilot.sh \
|
|
226
|
+
--app-root /path/to/mobile-app \
|
|
227
|
+
--app-path /path/to/mobile-app/build/Debug-iphonesimulator/Sample.app \
|
|
228
|
+
--app-id com.example.mobiletest \
|
|
229
|
+
--device booted \
|
|
230
|
+
--ios-shim /path/to/mobile-app/.zmr/ios-shim
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
For each run it writes:
|
|
234
|
+
|
|
235
|
+
- `ios-smoke/report.html`
|
|
236
|
+
- `ios-smoke.zmrtrace`
|
|
237
|
+
- `ios-smoke-redacted.zmrtrace`
|
|
238
|
+
- `ios-shim-smoke/report.html` when `--ios-shim` is set
|
|
239
|
+
- `ios-shim-smoke.zmrtrace` when `--ios-shim` is set
|
|
240
|
+
- `ios-shim-smoke-redacted.zmrtrace` when `--ios-shim` is set
|
|
241
|
+
|
|
242
|
+
The iOS demo covers simulator install, launch/open-link, screenshot capture,
|
|
243
|
+
log capture, trace export, and viewer inspection. With `--ios-shim`, it also
|
|
244
|
+
runs `examples/ios-shim-smoke.json`, which exercises launch, waitVisible, tap,
|
|
245
|
+
selector-scoped typeText, hideKeyboard, and snapshot through the generated
|
|
246
|
+
XCTest/XCUIAutomation shim command.
|
|
247
|
+
|
|
248
|
+
When an iOS shim is configured, the pilot wrapper prewarms it before scenario
|
|
249
|
+
timing by sending `{"cmd":"appState"}`. That catches Xcode target wiring issues
|
|
250
|
+
early and keeps cold `build-for-testing` cost out of benchmark durations.
|
|
251
|
+
The same app-state check is used as an idempotent launch confirmation when the
|
|
252
|
+
app is already running but `simctl launch` reports a non-zero exit.
|
|
253
|
+
|
|
254
|
+
Simulator demos require a simulator-built `iphonesimulator` `.app`. A signed
|
|
255
|
+
device `.ipa` is for `--ios-device-type physical` only and is rejected early for
|
|
256
|
+
simulator pilots.
|
|
257
|
+
|
|
258
|
+
`clearState` on iOS is best-effort app uninstall by bundle id. Repeating it is
|
|
259
|
+
safe: a simulator where the app is already absent is treated as clean.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Framework Guide
|
|
2
|
+
|
|
3
|
+
ZMR drives the installed mobile app through Android and iOS automation surfaces.
|
|
4
|
+
It does not require a React Native, Expo, Flutter, Swift, Kotlin, or Java test
|
|
5
|
+
SDK inside the app. The app only needs stable selectors and a predictable way to
|
|
6
|
+
reach the screens you want to test.
|
|
7
|
+
|
|
8
|
+
## React Native
|
|
9
|
+
|
|
10
|
+
Use app-owned selectors for controls that agents need to find:
|
|
11
|
+
|
|
12
|
+
- `testID` for Android resource ids and iOS accessibility identifiers.
|
|
13
|
+
- `accessibilityLabel` for user-facing controls that should be visible to assistive technology.
|
|
14
|
+
- Stable visible text for headings, tabs, and actions that are not localized or data-driven.
|
|
15
|
+
- Deep links for jumping directly to logged-in, onboarding, or error states.
|
|
16
|
+
|
|
17
|
+
Keep generated ZMR files under `.zmr/` and run the wizard from the app repo:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx zmr-wizard --app-id com.example.mobiletest --package-json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Expo
|
|
24
|
+
|
|
25
|
+
Expo development builds work like React Native apps once they are installed on a
|
|
26
|
+
simulator, emulator, or device. For dev-client flows, give ZMR the scheme that
|
|
27
|
+
opens your development build:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx zmr-wizard \
|
|
31
|
+
--app-id com.example.mobiletest \
|
|
32
|
+
--expo-dev-client-scheme mobiletest \
|
|
33
|
+
--package-json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The wizard adds Android and iOS dev-client scenarios that open Metro before
|
|
37
|
+
selector assertions run.
|
|
38
|
+
|
|
39
|
+
## Flutter
|
|
40
|
+
|
|
41
|
+
ZMR supports Flutter apps at the platform level. It can launch the Android or
|
|
42
|
+
iOS app, open deep links, wait for accessibility semantics, tap visible
|
|
43
|
+
controls, type text, take screenshots, collect traces, and export redacted
|
|
44
|
+
artifacts.
|
|
45
|
+
|
|
46
|
+
ZMR does not inspect Flutter widget trees, read Dart state, or replace Flutter's
|
|
47
|
+
own widget/integration test APIs. For reliable ZMR scenarios, expose stable
|
|
48
|
+
selectors through Flutter semantics:
|
|
49
|
+
|
|
50
|
+
```dart
|
|
51
|
+
Semantics(
|
|
52
|
+
label: 'email',
|
|
53
|
+
textField: true,
|
|
54
|
+
child: TextField(...),
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Prefer app-owned semantics labels for form fields, primary buttons, tabs, and
|
|
59
|
+
important states. Deep links are the cleanest way to skip setup screens and reach
|
|
60
|
+
the state an agent needs to inspect.
|
|
61
|
+
|
|
62
|
+
## Native Android And iOS
|
|
63
|
+
|
|
64
|
+
Native apps should expose:
|
|
65
|
+
|
|
66
|
+
- Android `resourceId` values or content descriptions for important controls.
|
|
67
|
+
- iOS accessibility identifiers or labels for important controls.
|
|
68
|
+
- Deep links for direct navigation into test states.
|
|
69
|
+
- Optional Android and iOS shims when native selector actions and bounded
|
|
70
|
+
hierarchy snapshots are needed.
|
|
71
|
+
|
|
72
|
+
See [app-integration.md](app-integration.md) for the shim setup commands.
|
package/docs/install.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Install
|
|
2
|
+
|
|
3
|
+
Most mobile app teams should install ZMR from npm inside the app repository.
|
|
4
|
+
That keeps `.zmr/` config, scenarios, generated package scripts, and traces with
|
|
5
|
+
the app they belong to.
|
|
6
|
+
|
|
7
|
+
## npm Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install --save-dev zeno-mobile-runner
|
|
11
|
+
npx zmr-wizard --app-id com.example.mobiletest --package-json
|
|
12
|
+
npx zmr doctor --strict --json --config .zmr/config.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The wizard creates `.zmr/config.json`, Android and iOS smoke scenarios,
|
|
16
|
+
`.zmr/device-matrix.json`, and `.zmr/AGENTS.md`. Run the generated validation
|
|
17
|
+
before touching a device:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run zmr:validate
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Common app-local commands:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx zmr-wizard --app-id com.example.mobiletest --android --ios --package-json
|
|
27
|
+
npx zmr-install-android-shim --app-root . --test-package com.example.mobiletest.test
|
|
28
|
+
npx zmr-install-ios-shim --app-root . --scheme SampleUITests --bundle-id com.example.mobiletest
|
|
29
|
+
npx zmr-device-matrix --matrix .zmr/device-matrix.json --trace-root traces/zmr-matrix
|
|
30
|
+
npm run zmr:serve
|
|
31
|
+
npm run zmr:mcp
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
See [docs/npm.md](npm.md) for the full npm binary list, binary resolution, and
|
|
35
|
+
app-local `.zmr/` setup.
|
|
36
|
+
|
|
37
|
+
## Homebrew Or Existing Binary
|
|
38
|
+
|
|
39
|
+
Teams that do not use JavaScript can install or build the `zmr` executable once
|
|
40
|
+
and point any language client or script at it:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
brew install --build-from-source ./dist/homebrew/zmr.rb
|
|
44
|
+
zmr version
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Build From Source
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git clone https://github.com/johnmikel/zeno-mobile-runner.git
|
|
51
|
+
cd zeno-mobile-runner
|
|
52
|
+
zig test src/test_harness.zig -target aarch64-macos.15.0
|
|
53
|
+
zig build-exe src/main.zig -target aarch64-macos.15.0 -O ReleaseSafe -femit-bin=zig-out/bin/zmr
|
|
54
|
+
./zig-out/bin/zmr version
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
On macOS hosts where Zig can infer the target, `zig build test` and `zig build`
|
|
58
|
+
are also valid.
|
|
59
|
+
|
|
60
|
+
## First Run Without A Device
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
zmr version --json
|
|
64
|
+
zmr schemas --json
|
|
65
|
+
zmr init zmr-scenario.json --app-id com.example.mobiletest
|
|
66
|
+
zmr init --app --json --dir . --app-id com.example.mobiletest
|
|
67
|
+
zmr validate examples/demo-fake.json
|
|
68
|
+
./scripts/demo.sh
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## App Codebase Integration
|
|
72
|
+
|
|
73
|
+
ZMR runs outside the app process and points at app build artifacts. For real app
|
|
74
|
+
pilots, pass the app root, app id, target device, and optional shim paths:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npx zmr-pilot-gate \
|
|
78
|
+
--android \
|
|
79
|
+
--ios \
|
|
80
|
+
--android-app-root . \
|
|
81
|
+
--android-app-id com.example.mobiletest \
|
|
82
|
+
--android-device emulator-5554 \
|
|
83
|
+
--ios-app-root . \
|
|
84
|
+
--ios-app-path ./build/Debug-iphonesimulator/Sample.app \
|
|
85
|
+
--ios-app-id com.example.mobiletest \
|
|
86
|
+
--ios-device booted \
|
|
87
|
+
--runs 20 \
|
|
88
|
+
--min-pass-rate 100 \
|
|
89
|
+
--max-failures 0 \
|
|
90
|
+
--evidence-out traces/zmr-pilots/evidence.jsonl
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
See [app-integration.md](app-integration.md), [frameworks.md](frameworks.md),
|
|
94
|
+
and [config.md](config.md) for framework guidance, shim setup, `.zmr/config.json`
|
|
95
|
+
defaults, and CLI override precedence.
|