peachsim 0.1.527

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.
Files changed (324) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +640 -0
  3. package/cli/app-config.ts +82 -0
  4. package/cli/app-fonts.ts +388 -0
  5. package/cli/app-project.ts +59 -0
  6. package/cli/app-splash.ts +171 -0
  7. package/cli/app-state-reset.ts +26 -0
  8. package/cli/auth.ts +184 -0
  9. package/cli/bin.ts +59 -0
  10. package/cli/bridge-diagnostics.ts +226 -0
  11. package/cli/bridge-flow-runner.ts +2806 -0
  12. package/cli/browser-backend.ts +44 -0
  13. package/cli/browser-evals.ts +96 -0
  14. package/cli/cli-update.ts +261 -0
  15. package/cli/cloud-client.ts +1530 -0
  16. package/cli/cloud-dispatch.ts +206 -0
  17. package/cli/cloud-session.ts +227 -0
  18. package/cli/command-contract.ts +221 -0
  19. package/cli/command-registry.ts +304 -0
  20. package/cli/commands/agent-wrapper.ts +1048 -0
  21. package/cli/commands/agent.ts +439 -0
  22. package/cli/commands/app-fonts.ts +99 -0
  23. package/cli/commands/assert.ts +542 -0
  24. package/cli/commands/auth.ts +71 -0
  25. package/cli/commands/box/bundle-plane.ts +71 -0
  26. package/cli/commands/box/checkout-plane.ts +256 -0
  27. package/cli/commands/box/plane-share.ts +208 -0
  28. package/cli/commands/box/rnx-command.ts +60 -0
  29. package/cli/commands/box/search-command.ts +157 -0
  30. package/cli/commands/box.ts +925 -0
  31. package/cli/commands/camera.ts +266 -0
  32. package/cli/commands/cleanup.ts +169 -0
  33. package/cli/commands/compat.ts +176 -0
  34. package/cli/commands/config.ts +34 -0
  35. package/cli/commands/control.ts +2154 -0
  36. package/cli/commands/cpu-profile.ts +941 -0
  37. package/cli/commands/daemon-mac-app.ts +165 -0
  38. package/cli/commands/daemon.ts +800 -0
  39. package/cli/commands/debug.ts +751 -0
  40. package/cli/commands/desktop.ts +39 -0
  41. package/cli/commands/detect.ts +201 -0
  42. package/cli/commands/detox.ts +481 -0
  43. package/cli/commands/device.ts +134 -0
  44. package/cli/commands/diagnose.ts +589 -0
  45. package/cli/commands/do-chain.ts +408 -0
  46. package/cli/commands/electron.ts +94 -0
  47. package/cli/commands/film.ts +379 -0
  48. package/cli/commands/flow.ts +1240 -0
  49. package/cli/commands/inspect/actions.ts +516 -0
  50. package/cli/commands/inspect/core.ts +2086 -0
  51. package/cli/commands/inspect/count.ts +17 -0
  52. package/cli/commands/inspect/describe.ts +119 -0
  53. package/cli/commands/inspect/env.ts +25 -0
  54. package/cli/commands/inspect/find.ts +169 -0
  55. package/cli/commands/inspect/get-layout.ts +53 -0
  56. package/cli/commands/inspect/keyboard.ts +54 -0
  57. package/cli/commands/inspect/list.ts +175 -0
  58. package/cli/commands/inspect/memory.ts +215 -0
  59. package/cli/commands/inspect/redaction.ts +39 -0
  60. package/cli/commands/inspect/resolve-target.ts +77 -0
  61. package/cli/commands/inspect/screens.ts +78 -0
  62. package/cli/commands/inspect/settle.ts +32 -0
  63. package/cli/commands/inspect/settling.ts +197 -0
  64. package/cli/commands/inspect/shared.ts +259 -0
  65. package/cli/commands/inspect/sleep.ts +15 -0
  66. package/cli/commands/inspect/tree.ts +23 -0
  67. package/cli/commands/inspect/url.ts +17 -0
  68. package/cli/commands/inspect/wait-event.ts +211 -0
  69. package/cli/commands/inspect/wait-idle.ts +25 -0
  70. package/cli/commands/inspect/wait-ready.ts +87 -0
  71. package/cli/commands/inspect/wait-selector.ts +59 -0
  72. package/cli/commands/inspect/wait.ts +32 -0
  73. package/cli/commands/inspect.ts +4738 -0
  74. package/cli/commands/install-cli.ts +275 -0
  75. package/cli/commands/install-desktop.ts +385 -0
  76. package/cli/commands/login.ts +357 -0
  77. package/cli/commands/logout.ts +24 -0
  78. package/cli/commands/maestro-generate.ts +375 -0
  79. package/cli/commands/maestro.ts +536 -0
  80. package/cli/commands/mode.ts +58 -0
  81. package/cli/commands/no-bridge-hint.ts +80 -0
  82. package/cli/commands/perf.ts +67 -0
  83. package/cli/commands/permissions.ts +203 -0
  84. package/cli/commands/platform.ts +410 -0
  85. package/cli/commands/preview.ts +103 -0
  86. package/cli/commands/profile.ts +106 -0
  87. package/cli/commands/react.ts +353 -0
  88. package/cli/commands/record.ts +1435 -0
  89. package/cli/commands/report-issue.ts +305 -0
  90. package/cli/commands/reset.ts +89 -0
  91. package/cli/commands/runtime.ts +348 -0
  92. package/cli/commands/screenshot-command.ts +106 -0
  93. package/cli/commands/screenshot-layers.ts +144 -0
  94. package/cli/commands/screenshot-mode.ts +38 -0
  95. package/cli/commands/screenshot.ts +492 -0
  96. package/cli/commands/screenshots-capture.ts +608 -0
  97. package/cli/commands/screenshots.ts +127 -0
  98. package/cli/commands/serve.ts +139 -0
  99. package/cli/commands/setup.ts +416 -0
  100. package/cli/commands/shell-boolean-mode.ts +82 -0
  101. package/cli/commands/skills.ts +468 -0
  102. package/cli/commands/slides.ts +357 -0
  103. package/cli/commands/state.ts +94 -0
  104. package/cli/commands/storage.ts +58 -0
  105. package/cli/commands/telemetry.ts +55 -0
  106. package/cli/commands/test.ts +535 -0
  107. package/cli/commands/three-mode.ts +771 -0
  108. package/cli/commands/timeline.ts +121 -0
  109. package/cli/commands/upgrade.ts +167 -0
  110. package/cli/commands/upload.ts +1203 -0
  111. package/cli/commands/version.ts +63 -0
  112. package/cli/commands/welcome.ts +17 -0
  113. package/cli/commands/what-happened.ts +328 -0
  114. package/cli/current-sim.ts +217 -0
  115. package/cli/desktop-companion.ts +315 -0
  116. package/cli/drivers/electron.ts +70 -0
  117. package/cli/drivers/index.ts +20 -0
  118. package/cli/drivers/playwright-provisioning.ts +184 -0
  119. package/cli/drivers/playwright-sim-host.ts +537 -0
  120. package/cli/drivers/playwright.ts +209 -0
  121. package/cli/drivers/registry.ts +65 -0
  122. package/cli/drivers/types.ts +102 -0
  123. package/cli/flow-export.ts +55 -0
  124. package/cli/flow-file.ts +142 -0
  125. package/cli/flow-live-status.ts +126 -0
  126. package/cli/flow-session.ts +140 -0
  127. package/cli/help-core.ts +143 -0
  128. package/cli/help.ts +44 -0
  129. package/cli/hidden-runtime-alias.ts +19 -0
  130. package/cli/hints.ts +214 -0
  131. package/cli/inspect-notice-state.ts +114 -0
  132. package/cli/internal-child.ts +176 -0
  133. package/cli/maestro-js.ts +323 -0
  134. package/cli/main.ts +704 -0
  135. package/cli/open-url.ts +8 -0
  136. package/cli/outbound-endpoints.ts +830 -0
  137. package/cli/parent-pid.ts +204 -0
  138. package/cli/parse-args.ts +189 -0
  139. package/cli/privacy.ts +53 -0
  140. package/cli/prompt.ts +56 -0
  141. package/cli/recording-access.ts +108 -0
  142. package/cli/registry.ts +2 -0
  143. package/cli/resolve-assets.ts +63 -0
  144. package/cli/rnx-in-process.ts +98 -0
  145. package/cli/run-registry.ts +226 -0
  146. package/cli/run-rnx-core.ts +148 -0
  147. package/cli/run-rnx.ts +137 -0
  148. package/cli/runtime-notes.ts +66 -0
  149. package/cli/runtime-summary.ts +25 -0
  150. package/cli/secure-file.ts +31 -0
  151. package/cli/self-invocation.ts +58 -0
  152. package/cli/send-to-box.ts +109 -0
  153. package/cli/setup-repository.ts +191 -0
  154. package/cli/shell-init.ts +98 -0
  155. package/cli/standalone.ts +4 -0
  156. package/cli/telemetry.ts +84 -0
  157. package/cli/ui.ts +68 -0
  158. package/cli/ws-bridge.ts +1020 -0
  159. package/detox/attempt-events.cjs +23 -0
  160. package/detox/colors.ts +54 -0
  161. package/detox/config-loader.ts +135 -0
  162. package/detox/element-types.ts +48 -0
  163. package/detox/expectations.ts +534 -0
  164. package/detox/gestures.ts +501 -0
  165. package/detox/index.ts +2694 -0
  166. package/detox/jest-preset.cjs +29 -0
  167. package/detox/jest-setup-after-env.cjs +22 -0
  168. package/detox/matchers.ts +30 -0
  169. package/detox/motion-change.cjs +109 -0
  170. package/detox/motion-change.d.cts +35 -0
  171. package/detox/navigation-lifecycle.ts +290 -0
  172. package/detox/navigation.ts +43 -0
  173. package/detox/proof-frame.cjs +114 -0
  174. package/detox/record-block-execution.cjs +78 -0
  175. package/detox/screenshots/animated-color-test-rest-norngh.png +0 -0
  176. package/detox/screenshots/color-test-after-drag-norngh.png +0 -0
  177. package/detox/screenshots/color-test-rest-norngh.png +0 -0
  178. package/detox/screenshots/theme-blue-toggle.png +0 -0
  179. package/detox/screenshots/theme-blue.png +0 -0
  180. package/detox/screenshots/theme-red-toggle.png +0 -0
  181. package/detox/screenshots/theme-red.png +0 -0
  182. package/dist-lib/agent-daemon-client.cjs +502 -0
  183. package/dist-lib/agent-events.cjs +48 -0
  184. package/dist-lib/agent-identity.cjs +53 -0
  185. package/dist-lib/agent-sessions.cjs +759 -0
  186. package/dist-lib/attached-projects.cjs +526 -0
  187. package/dist-lib/auth/shared-session.cjs +208 -0
  188. package/dist-lib/backend-origin.cjs +88 -0
  189. package/dist-lib/beta.cjs +41 -0
  190. package/dist-lib/beta.mjs +13 -0
  191. package/dist-lib/bridge-constants.cjs +161 -0
  192. package/dist-lib/bridge-contract-input.cjs +451 -0
  193. package/dist-lib/bridge-contract-input.mjs +414 -0
  194. package/dist-lib/bridge-contract.cjs +130 -0
  195. package/dist-lib/bridge-contract.mjs +94 -0
  196. package/dist-lib/capture-contract.cjs +220 -0
  197. package/dist-lib/capture-contract.mjs +190 -0
  198. package/dist-lib/cli-constants.cjs +32 -0
  199. package/dist-lib/cloud-contract.cjs +194 -0
  200. package/dist-lib/cloud-contract.mjs +145 -0
  201. package/dist-lib/cloud.cjs +670 -0
  202. package/dist-lib/cloud.mjs +639 -0
  203. package/dist-lib/config.cjs +96 -0
  204. package/dist-lib/detox/index.cjs +3789 -0
  205. package/dist-lib/detox/jest-preset.cjs +29 -0
  206. package/dist-lib/dev-bundle-resolution.cjs +290 -0
  207. package/dist-lib/home-paths.cjs +638 -0
  208. package/dist-lib/host/bridge-host.cjs +10903 -0
  209. package/dist-lib/host/fetch-proxy-handler.cjs +421 -0
  210. package/dist-lib/host/fetch-proxy-overrides.cjs +63 -0
  211. package/dist-lib/host/fetch-proxy-overrides.mjs +37 -0
  212. package/dist-lib/host/replacement-module-handler.cjs +469 -0
  213. package/dist-lib/host/websocket-proxy.cjs +298 -0
  214. package/dist-lib/index.cjs +4268 -0
  215. package/dist-lib/jump-to-source-babel.cjs +93 -0
  216. package/dist-lib/jump-to-source-native.cjs +112 -0
  217. package/dist-lib/menu.cjs +646 -0
  218. package/dist-lib/menu.mjs +604 -0
  219. package/dist-lib/metro-fingerprint-registry.cjs +186 -0
  220. package/dist-lib/metro-fingerprint-registry.mjs +156 -0
  221. package/dist-lib/metro-production-bundle.cjs +329 -0
  222. package/dist-lib/metro-production-bundle.mjs +295 -0
  223. package/dist-lib/metro.cjs +904 -0
  224. package/dist-lib/profiles.cjs +246 -0
  225. package/dist-lib/public-brand.cjs +39 -0
  226. package/dist-lib/react-native-host-modules.cjs +51 -0
  227. package/dist-lib/react-native-host-modules.mjs +25 -0
  228. package/dist-lib/render-mode.cjs +54 -0
  229. package/dist-lib/scripts/dev-server-scanner.cjs +1232 -0
  230. package/dist-lib/sdk.cjs +2433 -0
  231. package/dist-lib/sdk.mjs +2336 -0
  232. package/dist-lib/skills.cjs +39132 -0
  233. package/dist-lib/swift-submit.cjs +92 -0
  234. package/dist-lib/swift-submit.mjs +65 -0
  235. package/dist-lib/swift.cjs +1646 -0
  236. package/dist-lib/vite.cjs +1591 -0
  237. package/package.json +290 -0
  238. package/scripts/dev-server-scanner.ts +1291 -0
  239. package/scripts/optional-demo-registry.ts +113 -0
  240. package/skills/contrast/SKILL.md +165 -0
  241. package/skills/rnx-debug/SKILL.md +433 -0
  242. package/skills/rnx-perf/SKILL.md +399 -0
  243. package/skills/rnx-setup/SKILL.md +172 -0
  244. package/skills/rnx-test/SKILL.md +321 -0
  245. package/skills/rnx-visual/SKILL.md +126 -0
  246. package/src/agent-daemon-client.ts +410 -0
  247. package/src/agent-events.ts +71 -0
  248. package/src/agent-identity.ts +23 -0
  249. package/src/agent-prompt.ts +71 -0
  250. package/src/agent-sessions.ts +580 -0
  251. package/src/app-url.ts +39 -0
  252. package/src/attached-projects.ts +539 -0
  253. package/src/auth/shared-session.ts +235 -0
  254. package/src/backend-origin.ts +70 -0
  255. package/src/beta.ts +19 -0
  256. package/src/bridge-constants.ts +175 -0
  257. package/src/bridge-contract-input.ts +502 -0
  258. package/src/bridge-contract.ts +558 -0
  259. package/src/browser-cache.ts +16 -0
  260. package/src/capture-contract.ts +587 -0
  261. package/src/cli-constants.ts +1 -0
  262. package/src/cli-version.ts +40 -0
  263. package/src/cloud-contract.ts +274 -0
  264. package/src/cloud.ts +762 -0
  265. package/src/codex-client.ts +234 -0
  266. package/src/config.ts +132 -0
  267. package/src/connect.ts +101 -0
  268. package/src/dev-bundle-resolution.ts +346 -0
  269. package/src/dev-server-open.ts +198 -0
  270. package/src/disk-cleanup.ts +540 -0
  271. package/src/flow-timeout-scale.ts +15 -0
  272. package/src/home-paths.ts +806 -0
  273. package/src/host/agent-host.ts +666 -0
  274. package/src/host/bridge-host.ts +2788 -0
  275. package/src/host/fetch-proxy-handler.ts +449 -0
  276. package/src/host/fetch-proxy-overrides.ts +51 -0
  277. package/src/host/open-url.ts +89 -0
  278. package/src/host/plane-host.ts +203 -0
  279. package/src/host/replacement-module-handler.ts +158 -0
  280. package/src/host/websocket-proxy.ts +315 -0
  281. package/src/index.ts +71 -0
  282. package/src/jump-to-source-babel.ts +135 -0
  283. package/src/jump-to-source-native.ts +102 -0
  284. package/src/menu.ts +777 -0
  285. package/src/metro-fingerprint-registry.ts +302 -0
  286. package/src/metro-plugin.ts +341 -0
  287. package/src/metro-production-bundle.ts +471 -0
  288. package/src/native-dev-bundle-url.ts +118 -0
  289. package/src/native-seam-manifest.ts +341 -0
  290. package/src/playwright-host-log.ts +16 -0
  291. package/src/plist.ts +27 -0
  292. package/src/poll-until.ts +123 -0
  293. package/src/profiles.ts +179 -0
  294. package/src/public-brand.ts +9 -0
  295. package/src/react-native-host-modules.ts +26 -0
  296. package/src/render-mode.ts +27 -0
  297. package/src/rolldown-plugin-swift.ts +240 -0
  298. package/src/runtime-assets.ts +233 -0
  299. package/src/runtime-delivery.ts +54 -0
  300. package/src/screenshots/compose.ts +422 -0
  301. package/src/screenshots/frame-compose.ts +514 -0
  302. package/src/screenshots/orchestrate.ts +256 -0
  303. package/src/screenshots/org-deck.ts +91 -0
  304. package/src/screenshots/registry.ts +58 -0
  305. package/src/screenshots/schema.ts +364 -0
  306. package/src/sdk.ts +15 -0
  307. package/src/settings-bundle.ts +418 -0
  308. package/src/shell-bridge-identity.ts +15 -0
  309. package/src/sim-client.ts +697 -0
  310. package/src/skills/builtin/a11y-review.ts +132 -0
  311. package/src/skills/builtin/compat-check.ts +71 -0
  312. package/src/skills/builtin/maestro-test.ts +121 -0
  313. package/src/skills/builtin/perf-profile.ts +90 -0
  314. package/src/skills/builtin/screenshot-all.ts +52 -0
  315. package/src/skills/builtin/visual-diff.ts +100 -0
  316. package/src/skills/registry.ts +107 -0
  317. package/src/skills/types.ts +41 -0
  318. package/src/swift-submit.ts +185 -0
  319. package/src/swift.ts +7 -0
  320. package/src/team-machine-prompt.ts +73 -0
  321. package/src/vite-plugin-one.ts +264 -0
  322. package/src/vite-plugin-swift.ts +620 -0
  323. package/src/vite-plugin.ts +1946 -0
  324. package/src/worklets-babel.ts +250 -0
@@ -0,0 +1,321 @@
1
+ ---
2
+ name: rnx-test
3
+ description: Run automated tests against your React Native app under rnx with Maestro YAML or Detox/Jest
4
+ ---
5
+
6
+ # rnx tests
7
+
8
+ rnx has two test runners. Maestro owns every YAML test, whether it was
9
+ hand-authored, generated from a goal, or recorded from live CLI actions.
10
+ Detox runs existing imperative Jest suites through the rnx driver.
11
+
12
+ > needs a connected, pinned sim. if `rnx describe` errors, load
13
+ > `/rnx-setup` first.
14
+
15
+ Set `RNX_NO_OPEN=1` before starting an app dev server for a Detox,
16
+ Maestro, or iOS-only pass. Apps can opt into a named Electron window through
17
+ the official Vite or Metro plugin, and test-only work must not open that window.
18
+
19
+ ## route in (decision tree)
20
+
21
+ - have an existing `.maestro/` directory? → [Maestro](#branch--maestro)
22
+ - have existing Detox specs? → [detox drop-in](#branch--detox-drop-in)
23
+ - writing tests fresh, want plain-language generation, or want live authoring? → [Maestro](#branch--maestro)
24
+ - need one short, timing-sensitive sequence from the shell? → [inline chains](#one-off-inline-chains)
25
+
26
+ Do not invent a third runner for how a Maestro flow was authored.
27
+
28
+ ## anti-patterns (apply to both runners)
29
+
30
+ - **`sleep` is almost always a bug.** the underlying CLI auto-settles
31
+ before reads and polls layout hash after writes. if a flow fails
32
+ without a `sleep`, the fix is `waitFor`, `waitForAnimationToEnd`, or
33
+ `wait idle` — not a blind timer. the one legitimate case: a
34
+ user-controlled debounce ("press and hold for 2s").
35
+ - **prefer testID (`tapOn: { id: ... }`, `by.id(testID)`) over text.** text breaks
36
+ under i18n, copy churn, and duplicate strings. add `testID` during
37
+ implementation and author flows against it.
38
+ - **pin a sim before running a suite.** parallel CI jobs colliding
39
+ on the default bridge port is the #1 flake source. pass `--port` in
40
+ CI and `rnx use <id>` locally.
41
+ - **every flow ends with an assert, not a screenshot.** a screenshot
42
+ passes as long as the flow didn't throw. `assertVisible` (or
43
+ `expect(...).toBeVisible()`) actually verifies the happy path.
44
+ - **don't run a 40-step "smoke everything" flow.** when it fails, you
45
+ can't tell what regressed. split into `login.yaml`, `compose.yaml`,
46
+ `settings.yaml`, chain with `runFlow`.
47
+ - **inside an `rnx do` chain, use `sleep` only for gesture timing.** after the
48
+ chain, use `rnx wait` for app state so automation advances on a real condition.
49
+
50
+ ## you're done when
51
+
52
+ - the suite passes locally and in CI
53
+ - every flake is either fixed or marked `xfail` with a written reason
54
+ and a removal date
55
+ - the green run took noticeably less wall-clock than the previous
56
+ baseline (a suite that grows slower without growing wider is a smell)
57
+
58
+ ## one-off inline chains
59
+
60
+ repeat `--then` before each additional `do` action to run one ordered engine
61
+ batch. use a chain for a short repro, form fill, or timing-sensitive gesture
62
+ that does not belong in a saved test:
63
+
64
+ ```sh
65
+ rnx do tap email --then type user@example.com --then tap submit
66
+ rnx wait selector dashboard
67
+ ```
68
+
69
+ the batch stops on the first failure. add `--json` for per-action results.
70
+ `tap <id>` and `tap-id <id>` are exact; use `tap-text <text>` for visible text.
71
+ punctuation in action data remains data. the exact `--then` token is reserved
72
+ as the action boundary. use Maestro when the sequence should be reviewed,
73
+ reused, or run in CI; an inline chain is not a third test runner and does not
74
+ read flow files.
75
+
76
+ ## branch — Maestro
77
+
78
+ Write declarative Maestro YAML. The same command runs existing suites,
79
+ generates tests, records live drafts, profiles, and uploads replayable results.
80
+
81
+ ```sh
82
+ rnx maestro test .maestro/login.yaml # run one flow
83
+ rnx maestro test .maestro/login.yaml --record # record video
84
+ rnx maestro test .maestro/login.yaml --profile # include perf stats
85
+ rnx maestro test .maestro/ # run the suite
86
+ ```
87
+
88
+ Author from a live interaction:
89
+
90
+ ```sh
91
+ rnx maestro start # begin a draft
92
+ rnx do tap-id loginButton # drive the app via the CLI
93
+ rnx maestro keep # save the step
94
+ rnx do type "user@example.com"
95
+ rnx maestro keep
96
+ rnx do tap-id submit
97
+ rnx maestro keep
98
+ rnx maestro end --output .maestro/login.yaml --validate
99
+ ```
100
+
101
+ the recorder emits minimal YAML — no coordinate dumps, no `sleep` noise —
102
+ because the underlying CLI already settled between every action.
103
+
104
+ exemplar flow:
105
+
106
+ ```yaml
107
+ # .maestro/login.yaml
108
+ - launchApp: {}
109
+
110
+ - waitFor:
111
+ text: 'Sign in'
112
+ timeout: 10000
113
+
114
+ - tapOn:
115
+ id: emailInput
116
+ - inputText: '${USERNAME}'
117
+
118
+ - tapOn:
119
+ id: passwordInput
120
+ - inputText: '${PASSWORD}'
121
+
122
+ - tapOn:
123
+ id: signInButton
124
+ - waitForAnimationToEnd: true
125
+
126
+ - assertVisible: 'Welcome back'
127
+ ```
128
+
129
+ run with env interpolation:
130
+
131
+ ```sh
132
+ rnx maestro --env USERNAME=alice --env PASSWORD=hunter2 \
133
+ test .maestro/login.yaml \
134
+ --record --profile
135
+ ```
136
+
137
+ automatic settling inside flows: every tap, type, scroll, swipe, and
138
+ drag is backed by the same primitives that auto-wait for transitions on
139
+ the way in and layout stability on the way out. you rarely need
140
+ explicit waits; when you do, `waitForAnimationToEnd: true` maps to the
141
+ CLI's `wait idle` with a generous budget. use it before any
142
+ `assertVisible` that depends on a transition longer than ~400 ms.
143
+
144
+ Generate and immediately run a Maestro flow from a plain-language goal:
145
+
146
+ ```sh
147
+ rnx maestro generate "log in with the demo account and verify the dashboard"
148
+ ```
149
+
150
+ Generation writes the same deterministic Maestro artifact, uploads its replay,
151
+ and registers it as a Maestro run. The dashboard does not distinguish how it
152
+ was authored.
153
+
154
+ ### existing Maestro suites
155
+
156
+ if you already have a `.maestro/` directory, the migration is one
157
+ command change:
158
+
159
+ ```sh
160
+ # before
161
+ maestro test .maestro/login.yaml
162
+
163
+ # after
164
+ rnx maestro test .maestro/login.yaml
165
+ ```
166
+
167
+ no test rewrites, no detox config, no simulator. the runtime auto-launches
168
+ an rnx shell if one isn't running.
169
+
170
+ ```sh
171
+ rnx maestro # auto-discover .maestro/ or maestro/
172
+ rnx maestro test .maestro/login.yaml
173
+ rnx maestro test .maestro/ # every flow in a directory
174
+ rnx maestro init # scaffold a starter flow
175
+ rnx maestro --list-compat # supported / partial / unsupported
176
+ rnx maestro --env USERNAME=alice test .maestro/login.yaml
177
+ ```
178
+
179
+ ### supported verbs
180
+
181
+ `launchApp` (including JSON `arguments`), `stopApp`, `clearState`, `tapOn`, `tapAtCoords`, `longPressOn`, `inputText`,
182
+ `pressKey`, `dispatchKey`, `hideKeyboard`, `eraseText`, `assertVisible`,
183
+ `assertNotVisible`, `assertTreeContains`, `waitFor`, `extendedWaitUntil`,
184
+ `waitForAnimationToEnd`, `scroll`, `scrollUntilVisible`, `scrollTo`,
185
+ `swipe`, `pinch`, `takeScreenshot`, `dumpTree`, `back`, `repeat.times`,
186
+ `runFlow`, `when` (`visible` / `notVisible` / `platform` / `true`),
187
+ `optional: true`, `onFlowStart` / `onFlowComplete`, `copyTextFrom` +
188
+ `${maestroCopiedText}`, `evalScript`, `openLink`, env var `${NAME}`
189
+ interpolation.
190
+
191
+ ### partial
192
+
193
+ - `clearKeychain` — no keychain in rnx; logs a warning and continues.
194
+ if a test depends on keychain state being reset, add an explicit
195
+ in-app "sign out" step instead.
196
+ - `when.platform` — rnx emulates iOS; android branches are skipped.
197
+ - `openLink`: app routing works; there is no OS-level browser fallback.
198
+
199
+ `stopApp` keeps the guest runtime stopped. The next `launchApp` starts a fresh
200
+ guest with its replacement arguments. Every `openLink` replaces the guest and
201
+ delivers the URL through React Native Linking after the replacement starts.
202
+
203
+ ### not yet implemented
204
+
205
+ these throw `unsupported maestro verb: X`:
206
+
207
+ - `travel`, `setLocation`, `setAirplaneMode`, `killApp`
208
+ - `addMedia`
209
+ - `repeat.while` (use `repeat.times`)
210
+
211
+ ### troubleshooting
212
+
213
+ - **"no maestro flows found"** — pass an explicit path
214
+ (`rnx maestro test path/to/flow.yaml`) or run `rnx maestro
215
+ init` to scaffold one.
216
+ - **"missing environment variable for flow placeholder: FOO"** — pass
217
+ `--env FOO=bar` or export it. pick one mechanism per repo and document
218
+ it in the flow directory's README.
219
+ - **flow can't find an element** — rnx's matcher uses testID + visible
220
+ text. UIKit-only labels that real maestro scrapes from the host OS won't
221
+ resolve here; switch to testID.
222
+ - **flow runs but nothing renders** — confirm the bundler your flow
223
+ targets is reachable and pass `--url <port>` or add `app: <port>`
224
+ frontmatter at the top of the YAML.
225
+
226
+ ## branch — detox drop-in
227
+
228
+ an existing detox suite runs against rnx with **one line** of jest
229
+ config and zero test changes.
230
+
231
+ `import { by, device, element, expect, waitFor } from 'detox'` is
232
+ rewritten by jest to an rnx-backed driver that drives the real shell
233
+ over playwright. matchers, assertions, and the `waitFor` API match the
234
+ upstream detox surface.
235
+
236
+ ### one-line install
237
+
238
+ ```js
239
+ // rnx-detox.config.cjs
240
+ module.exports = {
241
+ preset: 'rnxsim/detox',
242
+ rootDir: __dirname,
243
+ testMatch: ['<rootDir>/e2e/**/*.test.ts'],
244
+ }
245
+ ```
246
+
247
+ or, if you already have a jest config, pull in just the module mapper:
248
+
249
+ ```js
250
+ moduleNameMapper: {
251
+ '^detox$': require.resolve('rnxsim/detox'),
252
+ }
253
+ ```
254
+
255
+ keep the **preset**, not just the mapper — the preset wires up the
256
+ global setup/teardown that tears the shell down between suites. mapper-only
257
+ works until your first hung shell.
258
+
259
+ ### commands
260
+
261
+ ```sh
262
+ rnx detox # run e2e/, test/e2e/, or detox/
263
+ rnx detox --config my.cjs # use a specific jest config
264
+ rnx detox --watch # jest watch mode
265
+ rnx detox -t "login" # --testNamePattern
266
+ rnx detox --headed # keep the shell window visible
267
+ rnx detox --no-launch # don't auto-launch a shell
268
+ rnx detox --port 5173 # explicit bridge port for CI
269
+ rnx detox init # scaffold config + e2e/example.test.ts
270
+ ```
271
+
272
+ ### compat surface
273
+
274
+ | detox API | rnx |
275
+ | ---------------------------------- | ------- |
276
+ | `element(by.id(...))` | supported |
277
+ | `element(by.text(...))` | supported — but prefer `by.id` |
278
+ | `element(by.label(...))` | supported |
279
+ | `element(by.traits([...]))` | supported for the iOS trait set |
280
+ | `.toBeVisible()` / `.not.toBeVisible()` | supported |
281
+ | `.toHaveText(...)` / `.toHaveLabel(...)` | supported |
282
+ | `.tap()` / `.longPress()` | supported |
283
+ | `.typeText(...)` / `.replaceText(...)` | supported |
284
+ | `.scroll(...)` / `.scrollTo(...)` | supported |
285
+ | `.swipe(...)` | supported |
286
+ | `.setColumnToValue(...)` | supported for uniquely named picker rows |
287
+ | `waitFor(...).toBeVisible().withTimeout(...)` | supported |
288
+ | `device.launchApp(...)` / `device.reloadReactNative()` | supported |
289
+ | `device.shake()` | partial — emits the JS event, no haptic |
290
+ | `device.sendUserNotification(...)` | not yet |
291
+
292
+ ### troubleshooting
293
+
294
+ - **"no rnx shell reachable"** — start one yourself
295
+ (`rnx open <port>`) or pass `--port <n>`.
296
+ - **"jest cannot find module 'detox'"** — the preset isn't wired. confirm
297
+ `preset: 'rnxsim/detox'` is in the jest config jest
298
+ actually loaded (`--config` overrides package.json).
299
+ - **matchers fail on elements that exist** — canvas has no DOM. use
300
+ `by.id` (testID); `rnx describe` shows what the shell sees.
301
+ - **passes locally, flakes in CI** — the shell boots asynchronously.
302
+ bump jest `testTimeout` to 10–15 s and add a `waitFor(element(...))
303
+ .toBeVisible().withTimeout(10000)` before the first assertion.
304
+ - **port conflicts under parallel CI** — pass `--port` explicitly per
305
+ job so workers don't collide on the default bridge port.
306
+
307
+ ## recovery — common failure modes (both runners)
308
+
309
+ - **"no flows found"** — confirm the working directory or pass an explicit
310
+ `.maestro/` path.
311
+ - **"missing env variable"** — set with `--env` (or jest env config) and
312
+ document the variable list in the flow directory's README so new
313
+ contributors aren't guessing.
314
+ - **CI flakes but local passes** — bump test timeouts to 10–15 s before
315
+ the first assertion, pin the bridge port, and run with `--video` so
316
+ failing Maestro runs land a recording next to the output.
317
+ - **a flake reproduces but resists fixing** — don't paper over with
318
+ `sleep`. open `/rnx-debug` against the same sim, capture
319
+ the timeline (`rnx timeline start` → reproduce → `rnx
320
+ what-happened`), and look for the missing animation-completion or
321
+ the unresolved fetch that's racing the assertion.
@@ -0,0 +1,126 @@
1
+ ---
2
+ name: rnx-visual
3
+ description: Pixel-level rendering comparison between rnx and native iOS — fonts, gradients, shadows, image fidelity
4
+ ---
5
+
6
+ # rnx visual fidelity
7
+
8
+ pixel-level rendering fidelity: does the rnx canvas match native iOS
9
+ for text, gradients, shadows, blur, and image rendering? the `rnx`
10
+ CLI gives you two primitives — **canvas capture** (`rnx screenshot`)
11
+ and **structural diff** (`rnx debug snapshot`/`diff`). pixel
12
+ comparison itself is "capture both sides, diff the PNGs with a standard
13
+ image tool" — there is no single oracle-diff command, and that's fine:
14
+ the capture step is the hard part and it's fully reproducible.
15
+
16
+ > needs a connected, pinned sim. if `rnx describe` errors,
17
+ > load `/rnx-setup` first.
18
+
19
+ ## route in
20
+
21
+ - structural change ("which nodes / which props changed?") → load
22
+ `/rnx-debug`, debugging branch — `debug snapshot` + `debug
23
+ diff` is faster, deterministic, and tells you *why*.
24
+ - visual change (color, gradient, shadow, font metric, blur, image)? →
25
+ continue here.
26
+ - comparing rnx to your iOS simulator for fidelity? → continue.
27
+ - regressing your own app against itself across commits? → continue.
28
+
29
+ ## anti-patterns (read first)
30
+
31
+ - **run structural diff before pixel work.** `rnx debug snapshot` /
32
+ `debug diff` (in `/rnx-debug`) is cheaper, deterministic, and
33
+ points at the responsible nodes. only when it's empty (or the change is
34
+ pure rendering) does a pixel comparison add information.
35
+ - **don't single-screenshot animated surfaces.** a gradient
36
+ mid-animation never matches. gate the capture behind `rnx wait
37
+ idle` first.
38
+ - **a > 5% pixel threshold hides regressions.** ~1% is the right
39
+ ballpark for catching real font / shadow / gradient drift without
40
+ flagging anti-alias noise. go higher only with a written reason.
41
+ - **pin device and theme.** capture both sides on the same simulated
42
+ device and appearance. capture each appearance separately with
43
+ `rnx screenshot` after setting it on both simulators.
44
+ - **commit baselines alongside the code change that produced them.**
45
+ baseline churn without code churn means someone captured noise.
46
+
47
+ ## capturing — `rnx screenshot`
48
+
49
+ fast, no extra setup, works on any loaded app:
50
+
51
+ ```sh
52
+ rnx screenshot --output app.png # full canvas
53
+ rnx screenshot --area 0,200,393,400 # crop to a logical rect
54
+ rnx screenshot --id loginButton -o btn.png # crop to a node by testID
55
+ rnx screenshot --text "Sign in" # crop to a node by text
56
+ rnx screenshot --no-shell -o tenant.png # tenant surface only, no iOS chrome
57
+ rnx screenshot --shell-only # only the simulated iOS chrome
58
+ ```
59
+
60
+ `rnx screenshot` captures the current screen as a PNG. navigate to each
61
+ screen you want to inspect and capture it with a distinct output filename.
62
+
63
+ ## comparing pixels
64
+
65
+ capture both sides to PNGs, then diff with any standard image tool.
66
+
67
+ **rnx vs rnx (regression across your own commits):**
68
+
69
+ ```sh
70
+ rnx screenshot -o before.png # baseline, before your change
71
+ # … make the rendering change, let the sim hot-reload …
72
+ rnx screenshot -o after.png # after your change
73
+ npx pixelmatch before.png after.png diff.png 0.1 # writes diff.png
74
+ # or: magick compare before.png after.png diff.png
75
+ ```
76
+
77
+ **rnx vs native iOS (fidelity to the real thing):**
78
+
79
+ ```sh
80
+ # native side: lifecycle and UI use xcodebuildmcp with one claimed simulator
81
+ # lossless capture names that simulator explicitly; never use the booted alias
82
+ xcrun simctl io <udid> screenshot --type=png native.png
83
+ # rnx side: same screen, same appearance
84
+ rnx screenshot -o rnx.png
85
+ npx pixelmatch native.png rnx.png diff.png 0.1
86
+ ```
87
+
88
+ `xcodebuildmcp simulator screenshot` may return an optimized JPEG even when the
89
+ proof contract requires a lossless source. Use it only when JPEG is acceptable.
90
+ For parity proof, use the explicit-UDID PNG command above, then verify the
91
+ decoded dimensions and file type before admitting the capture.
92
+
93
+ crop both to the same region (`--area` / `--id`) when you only care
94
+ about one element — a full-screen diff buries a 3px font-baseline shift
95
+ under unrelated chrome.
96
+
97
+ ## typical workflow
98
+
99
+ 1. structural diff first — confirm the change is genuinely visual.
100
+ 2. capture the affected screen with `rnx screenshot` (crop to the
101
+ element if you can).
102
+ 3. diff against the baseline (previous commit, or a native capture).
103
+ 4. iterate the rendering until the diff is under threshold.
104
+ 5. navigate to each affected screen, capture it, and inspect the PNG
105
+ for unexpected rendering changes.
106
+
107
+ ## you're done when
108
+
109
+ - the diff is under threshold on every affected case, **or**
110
+ - the differences are explicitly accepted, baselines re-captured, and
111
+ both halves (code + baselines) committed together.
112
+ - the captures show no unexpected changes across all affected screens.
113
+
114
+ ## recovery — common failure modes
115
+
116
+ - **a single icon/glyph diffs** — font-load race or image not yet
117
+ cached. recapture after `rnx wait idle`, or navigate away and back
118
+ to seed the cache.
119
+ - **everything diffs by a constant offset** — you captured the two sides
120
+ on different devices or appearances. pin both, recapture.
121
+ - **baselines churn without a code change** — someone captured noise (a
122
+ lingering badge, half-open keyboard, a drifting clock). revert and
123
+ recapture from a clean, idle state.
124
+ - **persistent delta on the same font / shadow / gradient across
125
+ unrelated screens** — that's an engine-level rendering fidelity issue,
126
+ not your app. report it with the affected captures attached.