rnxsim 0.1.335 → 0.1.337
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/README.md +104 -76
- package/cli/auth.ts +2 -2
- package/cli/bin.ts +7 -3
- package/cli/bridge-flow-runner.ts +2 -2
- package/cli/commands/agent-wrapper.ts +1 -1
- package/cli/commands/agent.ts +12 -12
- package/cli/commands/app-fonts.ts +1 -1
- package/cli/commands/assert.ts +7 -7
- package/cli/commands/auth.ts +4 -4
- package/cli/commands/camera.ts +13 -13
- package/cli/commands/cleanup.ts +6 -6
- package/cli/commands/compat.ts +4 -4
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +37 -43
- package/cli/commands/cpu-profile.ts +2 -2
- package/cli/commands/daemon-mac-app.ts +2 -2
- package/cli/commands/daemon.ts +12 -12
- package/cli/commands/debug.ts +22 -22
- package/cli/commands/desktop.ts +3 -3
- package/cli/commands/detox.ts +17 -17
- package/cli/commands/device.ts +9 -9
- package/cli/commands/diagnose.ts +11 -11
- package/cli/commands/electron.ts +7 -7
- package/cli/commands/film.ts +6 -6
- package/cli/commands/inspect/core.ts +6 -7
- package/cli/commands/inspect/find.ts +2 -2
- package/cli/commands/inspect.ts +36 -36
- package/cli/commands/install-desktop.ts +8 -8
- package/cli/commands/login.ts +6 -6
- package/cli/commands/maestro-generate.ts +2 -2
- package/cli/commands/maestro.ts +23 -23
- package/cli/commands/mode.ts +4 -4
- package/cli/commands/no-bridge-hint.ts +9 -9
- package/cli/commands/perf.ts +11 -11
- package/cli/commands/permissions.ts +5 -5
- package/cli/commands/profile.ts +11 -11
- package/cli/commands/react.ts +15 -15
- package/cli/commands/record.ts +15 -15
- package/cli/commands/report-issue.ts +2 -2
- package/cli/commands/reset.ts +2 -2
- package/cli/commands/runtime.ts +18 -18
- package/cli/commands/screenshot-mode.ts +5 -5
- package/cli/commands/screenshot.ts +12 -12
- package/cli/commands/screenshots-capture.ts +7 -7
- package/cli/commands/screenshots.ts +6 -6
- package/cli/commands/serve.ts +6 -6
- package/cli/commands/setup.ts +13 -15
- package/cli/commands/skills.ts +14 -14
- package/cli/commands/slides.ts +19 -23
- package/cli/commands/state.ts +2 -2
- package/cli/commands/storage.ts +3 -3
- package/cli/commands/telemetry.ts +1 -1
- package/cli/commands/three-mode.ts +16 -16
- package/cli/commands/timeline.ts +4 -4
- package/cli/commands/upgrade.ts +1 -1
- package/cli/commands/upload.ts +11 -11
- package/cli/commands/version.ts +3 -5
- package/cli/commands/what-happened.ts +11 -11
- package/cli/drivers/electron.ts +3 -3
- package/cli/hints.ts +8 -8
- package/cli/recording-access.ts +1 -1
- package/cli/ws-bridge.ts +5 -5
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-XSJMAFVA.js → agent-QQ3RJNRY.js} +14 -14
- package/dist-cli/chunks/{agent-wrapper-NFLJ5K64.js → agent-wrapper-M6SQSMRY.js} +3 -3
- package/dist-cli/chunks/app-fonts-F6NDV3XC.js +4 -0
- package/dist-cli/chunks/{assert-ILAXIYB5.js → assert-5VB3KQNK.js} +12 -12
- package/dist-cli/chunks/auth-PFXODKFN.js +12 -0
- package/dist-cli/chunks/{beta-TDR6UKJU.js → beta-WUWYHT4F.js} +2 -2
- package/dist-cli/chunks/camera-V3MMTKP7.js +33 -0
- package/dist-cli/chunks/{chunk-INBPUR4T.js → chunk-2ANFH72P.js} +11 -11
- package/dist-cli/chunks/chunk-2GIA5T6B.js +74 -0
- package/dist-cli/chunks/{chunk-GP6QEBZA.js → chunk-4FRSEZ7Z.js} +1 -1
- package/dist-cli/chunks/{chunk-USGOQ3YJ.js → chunk-4GXBZHNA.js} +2 -2
- package/dist-cli/chunks/{chunk-R3CMECGC.js → chunk-4HESY5E7.js} +4 -4
- package/dist-cli/chunks/{chunk-WKT7YM5Q.js → chunk-4VJEXQGD.js} +1 -1
- package/dist-cli/chunks/{chunk-FE6ZHPKD.js → chunk-5LJNNHZH.js} +1 -1
- package/dist-cli/chunks/{chunk-I2HQB5NN.js → chunk-5QXGSTYI.js} +2 -2
- package/dist-cli/chunks/{chunk-FJSHIWAM.js → chunk-5SHAOQHJ.js} +2 -2
- package/dist-cli/chunks/{chunk-CGZWLSYD.js → chunk-5UPRBMIG.js} +1 -1
- package/dist-cli/chunks/{chunk-ZTM2MKNI.js → chunk-5ZEFRPCC.js} +1 -1
- package/dist-cli/chunks/{chunk-RTD3CPDQ.js → chunk-6ART4XVJ.js} +23 -23
- package/dist-cli/chunks/{chunk-MTD6IAEA.js → chunk-6CAUT2LH.js} +1 -1
- package/dist-cli/chunks/{chunk-ZYHCWCMM.js → chunk-7ATIH7OU.js} +1 -1
- package/dist-cli/chunks/{chunk-RVUGKXJD.js → chunk-7Q4QKHMA.js} +1 -1
- package/dist-cli/chunks/{chunk-MTNIDSOA.js → chunk-ABK2V2PR.js} +1 -1
- package/dist-cli/chunks/{chunk-TL4DNDDY.js → chunk-B53ILAHI.js} +2 -2
- package/dist-cli/chunks/{chunk-POC3QTA6.js → chunk-BSSVLFZR.js} +2 -2
- package/dist-cli/chunks/chunk-BVOBXTPN.js +30 -0
- package/dist-cli/chunks/{chunk-4KC35DMK.js → chunk-CPDEUWL5.js} +2 -2
- package/dist-cli/chunks/{chunk-HNQLZZJA.js → chunk-DINU267S.js} +2 -2
- package/dist-cli/chunks/{chunk-DCDKJ4NC.js → chunk-DQQ4CZVC.js} +2 -2
- package/dist-cli/chunks/{chunk-JWAY6DIH.js → chunk-EDWN2HOO.js} +18 -18
- package/dist-cli/chunks/{chunk-3CS4EUMG.js → chunk-EWVG4A3B.js} +2 -2
- package/dist-cli/chunks/{chunk-RTEJXUXN.js → chunk-F3NKCQHM.js} +6 -6
- package/dist-cli/chunks/{chunk-M7CBQ5I4.js → chunk-GEAGFYKP.js} +1 -1
- package/dist-cli/chunks/chunk-GGNH44PZ.js +5 -0
- package/dist-cli/chunks/{chunk-YSUIYK6B.js → chunk-HAHJJJUC.js} +2 -2
- package/dist-cli/chunks/chunk-HPJ5EKIZ.js +4 -0
- package/dist-cli/chunks/{chunk-IN2PZBQD.js → chunk-IBTHGFKE.js} +2 -2
- package/dist-cli/chunks/{chunk-ZZWO6Y7X.js → chunk-J6BYRRZQ.js} +2 -2
- package/dist-cli/chunks/{chunk-6Y3PVPTF.js → chunk-JK4OZ2TQ.js} +5 -5
- package/dist-cli/chunks/{chunk-PO3TOAED.js → chunk-KGQAO25M.js} +2 -2
- package/dist-cli/chunks/{chunk-J7XFINJG.js → chunk-L6UUIQE7.js} +2 -2
- package/dist-cli/chunks/{chunk-35XNGT5C.js → chunk-LXYLCETR.js} +1 -1
- package/dist-cli/chunks/{chunk-JWK5WD44.js → chunk-LZAL3DMP.js} +2 -2
- package/dist-cli/chunks/{chunk-3ZDOPKHE.js → chunk-M43UU7UG.js} +4 -4
- package/dist-cli/chunks/{chunk-ROPHZJ6P.js → chunk-M4LGUVBM.js} +2 -2
- package/dist-cli/chunks/{chunk-RELRA5VW.js → chunk-NCG6C5AH.js} +2 -2
- package/dist-cli/chunks/{chunk-42KDXJUD.js → chunk-NR5TSR2Y.js} +2 -2
- package/dist-cli/chunks/{chunk-R2UL5VFY.js → chunk-OCPWXT73.js} +3 -3
- package/dist-cli/chunks/{chunk-VV4MXLFR.js → chunk-ODKS6JUJ.js} +1 -1
- package/dist-cli/chunks/{chunk-F33DUJGG.js → chunk-R2WBREGQ.js} +1 -1
- package/dist-cli/chunks/chunk-RKY3ZNTA.js +5 -0
- package/dist-cli/chunks/{chunk-MGGRL2Z2.js → chunk-SW7BHOMO.js} +9 -9
- package/dist-cli/chunks/{chunk-GVKISFQ3.js → chunk-TJTLXG3R.js} +1 -1
- package/dist-cli/chunks/chunk-TNI4PW75.js +124 -0
- package/dist-cli/chunks/{chunk-CL3PREIE.js → chunk-UWEDNDND.js} +2 -2
- package/dist-cli/chunks/{chunk-IV36DY6M.js → chunk-WRID5SBV.js} +1 -1
- package/dist-cli/chunks/{chunk-42ALI64M.js → chunk-WUYI3XJ5.js} +2 -2
- package/dist-cli/chunks/{chunk-6VN5ULGQ.js → chunk-X7MHCEGG.js} +2 -2
- package/dist-cli/chunks/chunk-XIQFYLWD.js +15 -0
- package/dist-cli/chunks/{chunk-LCVUJCRJ.js → chunk-ZUK5ZQU7.js} +1 -1
- package/dist-cli/chunks/{cleanup-X6ZRPFDV.js → cleanup-6WBS3MUO.js} +10 -10
- package/dist-cli/chunks/cli-version-HUQCDGMA.js +4 -0
- package/dist-cli/chunks/{compat-VRXJ5J56.js → compat-2WOPKJYK.js} +9 -9
- package/dist-cli/chunks/{config-LHPPE4EP.js → config-FPD7WUYB.js} +5 -5
- package/dist-cli/chunks/{control-TVTNGSSF.js → control-B3XNER7I.js} +2 -2
- package/dist-cli/chunks/daemon-T4D4X2P5.js +4 -0
- package/dist-cli/chunks/{debug-EUHBBPGM.js → debug-LKV5CEAV.js} +17 -17
- package/dist-cli/chunks/desktop-EMDPOYQT.js +31 -0
- package/dist-cli/chunks/detox-4J4UTZE7.js +52 -0
- package/dist-cli/chunks/{device-PONITUZJ.js → device-PMZ7RPXQ.js} +11 -11
- package/dist-cli/chunks/{diagnose-2PN4K4L2.js → diagnose-MLEP727D.js} +12 -12
- package/dist-cli/chunks/{disk-cleanup-U2PQLOEW.js → disk-cleanup-CVEDIPEE.js} +2 -2
- package/dist-cli/chunks/drivers-NTUKJEL6.js +4 -0
- package/dist-cli/chunks/{film-XGZCFTQL.js → film-4RNECABF.js} +9 -9
- package/dist-cli/chunks/flow-5IOCAHVO.js +4 -0
- package/dist-cli/chunks/help-NUJUYEWP.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-I4MYF5CO.js → hidden-runtime-alias-YIF25W4F.js} +2 -2
- package/dist-cli/chunks/{home-paths-YRAPZ5LE.js → home-paths-WNJCCCCZ.js} +2 -2
- package/dist-cli/chunks/inspect-MFEIYUCN.js +4 -0
- package/dist-cli/chunks/install-desktop-NB65KI4D.js +4 -0
- package/dist-cli/chunks/{login-ZMAIAQ6F.js → login-VEHHGN42.js} +6 -6
- package/dist-cli/chunks/{logout-UQZ5JBJU.js → logout-VE7PNXL2.js} +2 -2
- package/dist-cli/chunks/{maestro-BQYKDUC4.js → maestro-ZXHTDEOI.js} +25 -25
- package/dist-cli/chunks/{maestro-generate-VQYMMQJ5.js → maestro-generate-TK33E2Z6.js} +3 -3
- package/dist-cli/chunks/mode-ZDKJ56NT.js +26 -0
- package/dist-cli/chunks/{optional-demo-registry-DUWHCLGD.js → optional-demo-registry-GBZ3WVDW.js} +2 -2
- package/dist-cli/chunks/{perf-7RAU7WRZ.js → perf-JXNZOUKW.js} +28 -28
- package/dist-cli/chunks/permissions-WQ62PW7Y.js +13 -0
- package/dist-cli/chunks/record-4S3ZMDIO.js +72 -0
- package/dist-cli/chunks/{report-issue-P376KFFU.js → report-issue-KKBADTWO.js} +4 -4
- package/dist-cli/chunks/reset-H5XIISJE.js +4 -0
- package/dist-cli/chunks/runtime-FK7EEMWA.js +4 -0
- package/dist-cli/chunks/{screenshot-command-NE7BKTQ2.js → screenshot-command-42U5MVQL.js} +34 -34
- package/dist-cli/chunks/{screenshot-layers-UE4R64PZ.js → screenshot-layers-4G42AHOX.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-ULXPLXMC.js → screenshots-capture-HMQ2OO3I.js} +11 -11
- package/dist-cli/chunks/{serve-P7BT4XHR.js → serve-S4V5EDW2.js} +16 -16
- package/dist-cli/chunks/setup-T43V7GA6.js +32 -0
- package/dist-cli/chunks/{skills-NTRYKJSF.js → skills-O426K26J.js} +16 -16
- package/dist-cli/chunks/{state-4D5YAM47.js → state-ZEEPDKJG.js} +5 -5
- package/dist-cli/chunks/storage-4GQLOFGG.js +37 -0
- package/dist-cli/chunks/store-RFMSNWLJ.js +4 -0
- package/dist-cli/chunks/telemetry-NFAAPSMN.js +4 -0
- package/dist-cli/chunks/{timeline-GZNFGD3Q.js → timeline-ONCYX7KW.js} +6 -6
- package/dist-cli/chunks/{upgrade-A46D6PEY.js → upgrade-A36T52AM.js} +2 -2
- package/dist-cli/chunks/upload-36O32DII.js +4 -0
- package/dist-cli/chunks/version-67HA253N.js +6 -0
- package/dist-cli/chunks/{web-H2IXO5SC.js → web-PWXQHQIE.js} +2 -2
- package/dist-cli/chunks/{what-happened-Z7UII5GH.js → what-happened-WNXE622R.js} +16 -16
- package/dist-lib/agent-daemon-client.cjs +5 -5
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +4 -4
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +7 -7
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +248 -98
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +2 -2
- package/dist-lib/menu.mjs +2 -2
- package/dist-lib/metro-host-modules/react-dom.js +6 -0
- package/dist-lib/metro-host-modules/react-native-web.js +6 -0
- package/dist-lib/metro-host-modules/react-native.js +6 -0
- package/dist-lib/metro-host-modules/react.js +6 -0
- package/dist-lib/metro-host-modules/react__jsx-dev-runtime.js +6 -0
- package/dist-lib/metro-host-modules/react__jsx-runtime.js +6 -0
- package/dist-lib/metro-production-bundle.cjs +72 -0
- package/dist-lib/metro-production-bundle.mjs +44 -0
- package/dist-lib/metro.cjs +152 -8
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +2 -2
- package/dist-lib/react-native-host-modules.cjs +50 -0
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +6 -7
- package/dist-lib/sdk.mjs +6 -7
- package/dist-lib/skills.cjs +71 -77
- package/dist-lib/vite.cjs +104 -85
- package/package.json +15 -2
- package/scripts/preuninstall.cjs +1 -1
- package/skills/contrast/SKILL.md +67 -75
- package/skills/rnx-debug/SKILL.md +84 -84
- package/skills/rnx-perf/SKILL.md +8 -8
- package/skills/rnx-setup/SKILL.md +54 -54
- package/skills/rnx-test/SKILL.md +35 -35
- package/skills/rnx-visual/SKILL.md +18 -18
- package/src/agent-daemon-client.ts +2 -2
- package/src/agent-sessions.ts +2 -2
- package/src/connect.ts +6 -6
- package/src/disk-cleanup.ts +1 -1
- package/src/home-paths.ts +1 -1
- package/src/host/bridge-host.ts +6 -6
- package/src/index.ts +1 -1
- package/src/metro-host-modules/react-dom.js +6 -0
- package/src/metro-host-modules/react-native-web.js +6 -0
- package/src/metro-host-modules/react-native.js +6 -0
- package/src/metro-host-modules/react.js +6 -0
- package/src/metro-host-modules/react__jsx-dev-runtime.js +6 -0
- package/src/metro-host-modules/react__jsx-runtime.js +6 -0
- package/src/metro-plugin.ts +249 -10
- package/src/metro-production-bundle.ts +51 -0
- package/src/public-brand.ts +1 -1
- package/src/react-native-host-modules.ts +25 -0
- package/src/runtime-assets.ts +1 -1
- package/src/sim-client.ts +1 -1
- package/src/vite-plugin-one.ts +171 -145
- package/dist-cli/chunks/app-fonts-L3UXFYVE.js +0 -4
- package/dist-cli/chunks/auth-ISX2EUQL.js +0 -12
- package/dist-cli/chunks/camera-4SWTNJUA.js +0 -33
- package/dist-cli/chunks/chunk-BRHZEZKN.js +0 -124
- package/dist-cli/chunks/chunk-EJPYPJWP.js +0 -5
- package/dist-cli/chunks/chunk-KWCD5MOK.js +0 -15
- package/dist-cli/chunks/chunk-MJ7QGY7Z.js +0 -4
- package/dist-cli/chunks/chunk-RSA4XWHN.js +0 -5
- package/dist-cli/chunks/chunk-S3EIOAWZ.js +0 -74
- package/dist-cli/chunks/chunk-TYANJQLO.js +0 -30
- package/dist-cli/chunks/cli-version-NZUSWKZR.js +0 -4
- package/dist-cli/chunks/daemon-XUEC47EC.js +0 -4
- package/dist-cli/chunks/desktop-LLHMP4A3.js +0 -31
- package/dist-cli/chunks/detox-QLNWLXA4.js +0 -52
- package/dist-cli/chunks/drivers-7IU37M2E.js +0 -4
- package/dist-cli/chunks/flow-NZZLR4BN.js +0 -4
- package/dist-cli/chunks/help-D7URIJRD.js +0 -4
- package/dist-cli/chunks/inspect-TJYWKY56.js +0 -4
- package/dist-cli/chunks/install-desktop-LD3W5RS7.js +0 -4
- package/dist-cli/chunks/mode-ZQ6H7KWM.js +0 -26
- package/dist-cli/chunks/permissions-DRZ3HCFL.js +0 -13
- package/dist-cli/chunks/record-J5JAYW4Y.js +0 -72
- package/dist-cli/chunks/reset-KXYRDEFU.js +0 -4
- package/dist-cli/chunks/runtime-66CEPOG6.js +0 -4
- package/dist-cli/chunks/setup-QO5KZAX3.js +0 -32
- package/dist-cli/chunks/storage-X2K2MDPX.js +0 -37
- package/dist-cli/chunks/store-TUJPIRTT.js +0 -4
- package/dist-cli/chunks/telemetry-CF5DVEKI.js +0 -4
- package/dist-cli/chunks/upload-UIQJIBEZ.js +0 -4
- package/dist-cli/chunks/version-CMBB3FXL.js +0 -6
package/skills/rnx-test/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ rnx has two test runners. Maestro owns every YAML test, whether it was
|
|
|
9
9
|
hand-authored, generated from a goal, or recorded from live CLI actions.
|
|
10
10
|
Detox runs existing imperative Jest suites through the rnx driver.
|
|
11
11
|
|
|
12
|
-
> needs a connected, pinned sim. if `
|
|
12
|
+
> needs a connected, pinned sim. if `rnx describe` errors, load
|
|
13
13
|
> `/rnx-setup` first.
|
|
14
14
|
|
|
15
15
|
## route in (decision tree)
|
|
@@ -32,7 +32,7 @@ Do not invent a third runner for how a Maestro flow was authored.
|
|
|
32
32
|
implementation and author flows against it.
|
|
33
33
|
- **pin a sim before running a suite.** parallel CI jobs colliding
|
|
34
34
|
on the default bridge port is the #1 flake source. pass `--port` in
|
|
35
|
-
CI and `
|
|
35
|
+
CI and `rnx use <id>` locally.
|
|
36
36
|
- **every flow ends with an assert, not a screenshot.** a screenshot
|
|
37
37
|
passes as long as the flow didn't throw. `assertVisible` (or
|
|
38
38
|
`expect(...).toBeVisible()`) actually verifies the happy path.
|
|
@@ -54,23 +54,23 @@ Write declarative Maestro YAML. The same command runs existing suites,
|
|
|
54
54
|
generates tests, records live drafts, profiles, and uploads replayable results.
|
|
55
55
|
|
|
56
56
|
```sh
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
rnx maestro test .maestro/login.yaml # run one flow
|
|
58
|
+
rnx maestro test .maestro/login.yaml --record # record video
|
|
59
|
+
rnx maestro test .maestro/login.yaml --profile # include perf stats
|
|
60
|
+
rnx maestro test .maestro/ # run the suite
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
Author from a live interaction:
|
|
64
64
|
|
|
65
65
|
```sh
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
rnx maestro start # begin a draft
|
|
67
|
+
rnx do tap-id loginButton # drive the app via the CLI
|
|
68
|
+
rnx maestro keep # save the step
|
|
69
|
+
rnx do type "user@example.com"
|
|
70
|
+
rnx maestro keep
|
|
71
|
+
rnx do tap-id submit
|
|
72
|
+
rnx maestro keep
|
|
73
|
+
rnx maestro end --output .maestro/login.yaml --validate
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
the recorder emits minimal YAML — no coordinate dumps, no `sleep` noise —
|
|
@@ -104,7 +104,7 @@ exemplar flow:
|
|
|
104
104
|
run with env interpolation:
|
|
105
105
|
|
|
106
106
|
```sh
|
|
107
|
-
|
|
107
|
+
rnx maestro --env USERNAME=alice --env PASSWORD=hunter2 \
|
|
108
108
|
test .maestro/login.yaml \
|
|
109
109
|
--record --profile
|
|
110
110
|
```
|
|
@@ -119,7 +119,7 @@ CLI's `wait idle` with a generous budget. use it before any
|
|
|
119
119
|
Generate and immediately run a Maestro flow from a plain-language goal:
|
|
120
120
|
|
|
121
121
|
```sh
|
|
122
|
-
|
|
122
|
+
rnx maestro generate "log in with the demo account and verify the dashboard"
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
Generation writes the same deterministic Maestro artifact, uploads its replay,
|
|
@@ -136,19 +136,19 @@ command change:
|
|
|
136
136
|
maestro test .maestro/login.yaml
|
|
137
137
|
|
|
138
138
|
# after
|
|
139
|
-
|
|
139
|
+
rnx maestro test .maestro/login.yaml
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
no test rewrites, no detox config, no simulator. the runtime auto-launches
|
|
143
143
|
an rnx shell if one isn't running.
|
|
144
144
|
|
|
145
145
|
```sh
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
146
|
+
rnx maestro # auto-discover .maestro/ or maestro/
|
|
147
|
+
rnx maestro test .maestro/login.yaml
|
|
148
|
+
rnx maestro test .maestro/ # every flow in a directory
|
|
149
|
+
rnx maestro init # scaffold a starter flow
|
|
150
|
+
rnx maestro --list-compat # supported / partial / unsupported
|
|
151
|
+
rnx maestro --env USERNAME=alice test .maestro/login.yaml
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
### supported verbs
|
|
@@ -182,7 +182,7 @@ these throw `unsupported maestro verb: X`:
|
|
|
182
182
|
### troubleshooting
|
|
183
183
|
|
|
184
184
|
- **"no maestro flows found"** — pass an explicit path
|
|
185
|
-
(`
|
|
185
|
+
(`rnx maestro test path/to/flow.yaml`) or run `rnx maestro
|
|
186
186
|
init` to scaffold one.
|
|
187
187
|
- **"missing environment variable for flow placeholder: FOO"** — pass
|
|
188
188
|
`--env FOO=bar` or export it. pick one mechanism per repo and document
|
|
@@ -230,14 +230,14 @@ works until your first hung shell.
|
|
|
230
230
|
### commands
|
|
231
231
|
|
|
232
232
|
```sh
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
233
|
+
rnx detox # run e2e/, test/e2e/, or detox/
|
|
234
|
+
rnx detox --config my.cjs # use a specific jest config
|
|
235
|
+
rnx detox --watch # jest watch mode
|
|
236
|
+
rnx detox -t "login" # --testNamePattern
|
|
237
|
+
rnx detox --headed # keep the shell window visible
|
|
238
|
+
rnx detox --no-launch # don't auto-launch a shell
|
|
239
|
+
rnx detox --port 5173 # explicit bridge port for CI
|
|
240
|
+
rnx detox init # scaffold config + e2e/example.test.ts
|
|
241
241
|
```
|
|
242
242
|
|
|
243
243
|
### compat surface
|
|
@@ -263,12 +263,12 @@ rnxsim detox init # scaffold config + e2e/example.test.ts
|
|
|
263
263
|
### troubleshooting
|
|
264
264
|
|
|
265
265
|
- **"no rnx shell reachable"** — start one yourself
|
|
266
|
-
(`
|
|
266
|
+
(`rnx open <port>`) or pass `--port <n>`.
|
|
267
267
|
- **"jest cannot find module 'detox'"** — the preset isn't wired. confirm
|
|
268
268
|
`preset: 'rnxsim/detox/jest-preset'` is in the jest config jest
|
|
269
269
|
actually loaded (`--config` overrides package.json).
|
|
270
270
|
- **matchers fail on elements that exist** — canvas has no DOM. use
|
|
271
|
-
`by.id` (testID); `
|
|
271
|
+
`by.id` (testID); `rnx describe` shows what the shell sees.
|
|
272
272
|
- **passes locally, flakes in CI** — the shell boots asynchronously.
|
|
273
273
|
bump jest `testTimeout` to 10–15 s and add a `waitFor(element(...))
|
|
274
274
|
.toBeVisible().withTimeout(10000)` before the first assertion.
|
|
@@ -287,6 +287,6 @@ rnxsim detox init # scaffold config + e2e/example.test.ts
|
|
|
287
287
|
failing Maestro runs land a recording next to the output.
|
|
288
288
|
- **a flake reproduces but resists fixing** — don't paper over with
|
|
289
289
|
`sleep`. open `/rnx-debug` against the same sim, capture
|
|
290
|
-
the timeline (`
|
|
290
|
+
the timeline (`rnx timeline start` → reproduce → `rnx
|
|
291
291
|
what-happened`), and look for the missing animation-completion or
|
|
292
292
|
the unresolved fetch that's racing the assertion.
|
|
@@ -7,13 +7,13 @@ description: Pixel-level rendering comparison between rnx and native iOS — fon
|
|
|
7
7
|
|
|
8
8
|
pixel-level rendering fidelity: does the rnx canvas match native iOS
|
|
9
9
|
for text, gradients, shadows, blur, and image rendering? the `rnx`
|
|
10
|
-
CLI gives you two primitives — **canvas capture** (`
|
|
11
|
-
and **structural diff** (`
|
|
10
|
+
CLI gives you two primitives — **canvas capture** (`rnx screenshot`)
|
|
11
|
+
and **structural diff** (`rnx debug snapshot`/`diff`). pixel
|
|
12
12
|
comparison itself is "capture both sides, diff the PNGs with a standard
|
|
13
13
|
image tool" — there is no single oracle-diff command, and that's fine:
|
|
14
14
|
the capture step is the hard part and it's fully reproducible.
|
|
15
15
|
|
|
16
|
-
> needs a connected, pinned sim. if `
|
|
16
|
+
> needs a connected, pinned sim. if `rnx describe` errors,
|
|
17
17
|
> load `/rnx-setup` first.
|
|
18
18
|
|
|
19
19
|
## route in
|
|
@@ -28,12 +28,12 @@ the capture step is the hard part and it's fully reproducible.
|
|
|
28
28
|
|
|
29
29
|
## anti-patterns (read first)
|
|
30
30
|
|
|
31
|
-
- **run structural diff before pixel work.** `
|
|
31
|
+
- **run structural diff before pixel work.** `rnx debug snapshot` /
|
|
32
32
|
`debug diff` (in `/rnx-debug`) is cheaper, deterministic, and
|
|
33
33
|
points at the responsible nodes. only when it's empty (or the change is
|
|
34
34
|
pure rendering) does a pixel comparison add information.
|
|
35
35
|
- **don't single-screenshot animated surfaces.** a gradient
|
|
36
|
-
mid-animation never matches. gate the capture behind `
|
|
36
|
+
mid-animation never matches. gate the capture behind `rnx wait
|
|
37
37
|
idle` first.
|
|
38
38
|
- **a > 5% pixel threshold hides regressions.** ~1% is the right
|
|
39
39
|
ballpark for catching real font / shadow / gradient drift without
|
|
@@ -44,18 +44,18 @@ the capture step is the hard part and it's fully reproducible.
|
|
|
44
44
|
- **commit baselines alongside the code change that produced them.**
|
|
45
45
|
baseline churn without code churn means someone captured noise.
|
|
46
46
|
|
|
47
|
-
## capturing — `
|
|
47
|
+
## capturing — `rnx screenshot`
|
|
48
48
|
|
|
49
49
|
fast, no extra setup, works on any loaded app:
|
|
50
50
|
|
|
51
51
|
```sh
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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 --gallery --themes # crawl screens → HTML gallery, light+dark
|
|
57
|
+
rnx screenshot --no-shell -o tenant.png # tenant surface only, no iOS chrome
|
|
58
|
+
rnx screenshot --shell-only # only the simulated iOS chrome
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
`--gallery` crawls reachable screens and writes a browsable HTML gallery
|
|
@@ -68,9 +68,9 @@ capture both sides to PNGs, then diff with any standard image tool.
|
|
|
68
68
|
**rnx vs rnx (regression across your own commits):**
|
|
69
69
|
|
|
70
70
|
```sh
|
|
71
|
-
|
|
71
|
+
rnx screenshot -o before.png # baseline, before your change
|
|
72
72
|
# … make the rendering change, let the sim hot-reload …
|
|
73
|
-
|
|
73
|
+
rnx screenshot -o after.png # after your change
|
|
74
74
|
npx pixelmatch before.png after.png diff.png 0.1 # writes diff.png
|
|
75
75
|
# or: magick compare before.png after.png diff.png
|
|
76
76
|
```
|
|
@@ -81,7 +81,7 @@ npx pixelmatch before.png after.png diff.png 0.1 # writes diff.png
|
|
|
81
81
|
# native side — capture from your booted iOS simulator
|
|
82
82
|
xcrun simctl io booted screenshot native.png
|
|
83
83
|
# rnx side — same screen, same appearance
|
|
84
|
-
|
|
84
|
+
rnx screenshot -o rnx.png
|
|
85
85
|
npx pixelmatch native.png rnx.png diff.png 0.1
|
|
86
86
|
```
|
|
87
87
|
|
|
@@ -92,7 +92,7 @@ under unrelated chrome.
|
|
|
92
92
|
## typical workflow
|
|
93
93
|
|
|
94
94
|
1. structural diff first — confirm the change is genuinely visual.
|
|
95
|
-
2. capture the affected screen with `
|
|
95
|
+
2. capture the affected screen with `rnx screenshot` (crop to the
|
|
96
96
|
element if you can).
|
|
97
97
|
3. diff against the baseline (previous commit, or a native capture).
|
|
98
98
|
4. iterate the rendering until the diff is under threshold.
|
|
@@ -110,7 +110,7 @@ under unrelated chrome.
|
|
|
110
110
|
## recovery — common failure modes
|
|
111
111
|
|
|
112
112
|
- **a single icon/glyph diffs** — font-load race or image not yet
|
|
113
|
-
cached. recapture after `
|
|
113
|
+
cached. recapture after `rnx wait idle`, or navigate away and back
|
|
114
114
|
to seed the cache.
|
|
115
115
|
- **everything diffs by a constant offset** — you captured the two sides
|
|
116
116
|
on different devices or appearances. pin both, recapture.
|
|
@@ -361,7 +361,7 @@ export async function ensureDaemonRunning(
|
|
|
361
361
|
}
|
|
362
362
|
if (shouldSkipPersistentDaemon()) {
|
|
363
363
|
throw new AgentDaemonError(
|
|
364
|
-
`no rnx bridge on port ${port}. run \`
|
|
364
|
+
`no rnx bridge on port ${port}. run \`rnx setup\` to install the background daemon, or \`rnx serve\` in another shell.`,
|
|
365
365
|
'DEV_HOST_REFUSED',
|
|
366
366
|
)
|
|
367
367
|
}
|
|
@@ -386,7 +386,7 @@ export async function ensureDaemonRunning(
|
|
|
386
386
|
}
|
|
387
387
|
throw new AgentDaemonError(
|
|
388
388
|
`spawned rnx daemon on port ${port} but it did not come up in time. ` +
|
|
389
|
-
`run \`
|
|
389
|
+
`run \`rnx serve\` manually to diagnose.`,
|
|
390
390
|
'SPAWN_TIMEOUT',
|
|
391
391
|
)
|
|
392
392
|
}
|
package/src/agent-sessions.ts
CHANGED
|
@@ -117,7 +117,7 @@ export function resolveSootsimInvocation(): { cmd: string; prefixArgs: string[]
|
|
|
117
117
|
// bin-shim case falls through to the error below instead of silently
|
|
118
118
|
// running `node` without args.
|
|
119
119
|
throw new Error(
|
|
120
|
-
'
|
|
120
|
+
'rnx CLI not found. set SOOTSIM_BIN to the path of the rnx binary, ' +
|
|
121
121
|
'or build the workspace CLI via `bun run --cwd packages/sootsim build:cli`.',
|
|
122
122
|
)
|
|
123
123
|
}
|
|
@@ -335,7 +335,7 @@ export async function startSession(opts: StartSessionOpts): Promise<StartSession
|
|
|
335
335
|
'ALREADY_RUNNING',
|
|
336
336
|
`session already running for project=${project.id} provider=${provider} ` +
|
|
337
337
|
`(session ${existingLive.id}, pid ${existingLive.wrapperPid}). ` +
|
|
338
|
-
'end it first with `
|
|
338
|
+
'end it first with `rnx agent end <sessionId>`.',
|
|
339
339
|
)
|
|
340
340
|
}
|
|
341
341
|
|
package/src/connect.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { SimClient, SimConnectError } from './sim-client'
|
|
|
11
11
|
export interface ConnectOptions {
|
|
12
12
|
/** ws bridge port. default: the resolved bridge world (lockfiles). */
|
|
13
13
|
port?: number
|
|
14
|
-
/** sim id to attach to (as shown by `
|
|
14
|
+
/** sim id to attach to (as shown by `rnx list`). default: the primary sim. */
|
|
15
15
|
sim?: string
|
|
16
16
|
/** per-command bridge timeout in ms. default 15000. */
|
|
17
17
|
timeoutMs?: number
|
|
@@ -30,13 +30,13 @@ function pickSim(
|
|
|
30
30
|
`no sim connected with id ${wanted} on bridge :${port}` +
|
|
31
31
|
(open.length
|
|
32
32
|
? ` — connected: ${open.map((sim) => sim.id).join(', ')}`
|
|
33
|
-
: ' — no sims connected; open one with `
|
|
33
|
+
: ' — no sims connected; open one with `rnx open <port>`'),
|
|
34
34
|
)
|
|
35
35
|
}
|
|
36
36
|
return match
|
|
37
37
|
}
|
|
38
|
-
// same session affinity as the CLI: a sim pinned by `
|
|
39
|
-
// `
|
|
38
|
+
// same session affinity as the CLI: a sim pinned by `rnx open` /
|
|
39
|
+
// `rnx use` in this terminal wins over the primary election, so a script
|
|
40
40
|
// run next to CLI commands drives the sim the terminal is working with. a
|
|
41
41
|
// stale pin (sim gone) falls through to the primary.
|
|
42
42
|
const pinned = readCurrentSimId()
|
|
@@ -47,7 +47,7 @@ function pickSim(
|
|
|
47
47
|
const primary = open.find((sim) => sim.isPrimary) ?? open[0]
|
|
48
48
|
if (!primary) {
|
|
49
49
|
throw new SimConnectError(
|
|
50
|
-
`no sims connected on bridge :${port} — open one with \`
|
|
50
|
+
`no sims connected on bridge :${port} — open one with \`rnx open <port>\``,
|
|
51
51
|
)
|
|
52
52
|
}
|
|
53
53
|
return primary
|
|
@@ -67,7 +67,7 @@ export async function connect(options: ConnectOptions = {}): Promise<SimClient>
|
|
|
67
67
|
discovery.close()
|
|
68
68
|
if (error instanceof SimConnectError) throw error
|
|
69
69
|
const message = error instanceof Error ? error.message : String(error)
|
|
70
|
-
throw new SimConnectError(`${message} — is the
|
|
70
|
+
throw new SimConnectError(`${message} — is the rnx daemon or dev shell running?`)
|
|
71
71
|
}
|
|
72
72
|
discovery.close()
|
|
73
73
|
|
package/src/disk-cleanup.ts
CHANGED
|
@@ -178,7 +178,7 @@ function collectRecordingEntries(
|
|
|
178
178
|
})
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
// videos staged by `
|
|
181
|
+
// videos staged by `rnx camera play`. a fixture is only a copy of a file
|
|
182
182
|
// the user still has, so it is cheap to reclaim, but the automatic sweep must
|
|
183
183
|
// not pull one out from under a sim that is playing it right now. aggressive
|
|
184
184
|
// only, matching recordings.
|
package/src/home-paths.ts
CHANGED
|
@@ -128,7 +128,7 @@ export function profilesDir(): string {
|
|
|
128
128
|
return path.join(sootsimHomeDir(), 'profiles')
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
// video fixtures staged for `
|
|
131
|
+
// video fixtures staged for `rnx camera play`. the CLI copies the user's
|
|
132
132
|
// file in here and the daemon serves it by basename from this one directory,
|
|
133
133
|
// so the route can never be talked into reading anywhere else on disk.
|
|
134
134
|
export function cameraFixturesDir(): string {
|
package/src/host/bridge-host.ts
CHANGED
|
@@ -306,7 +306,7 @@ const HTTP_MIME_TYPES: Record<string, string> = {
|
|
|
306
306
|
'.mov': 'video/quicktime',
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
// `
|
|
309
|
+
// `rnx camera play` stages a video under ~/.sootsim/camera-fixtures and the
|
|
310
310
|
// simulator plays it as the camera feed. the route below serves that one
|
|
311
311
|
// directory, addressed by basename only.
|
|
312
312
|
const CAMERA_FIXTURE_ROUTE = '/__camera-fixtures/'
|
|
@@ -1010,7 +1010,7 @@ export class SootSimBridgeHost {
|
|
|
1010
1010
|
ws.send(
|
|
1011
1011
|
JSON.stringify({
|
|
1012
1012
|
id: msg.id,
|
|
1013
|
-
error: `sim ${targetSim.id} is locked by another cli — use \`
|
|
1013
|
+
error: `sim ${targetSim.id} is locked by another cli — use \`rnx claim ${targetSim.id} --force\` or \`rnx open --new\``,
|
|
1014
1014
|
_locked: outcome.lock,
|
|
1015
1015
|
}),
|
|
1016
1016
|
)
|
|
@@ -1634,7 +1634,7 @@ export class SootSimBridgeHost {
|
|
|
1634
1634
|
return
|
|
1635
1635
|
}
|
|
1636
1636
|
|
|
1637
|
-
// /__camera-fixtures/<name> — the staged video behind `
|
|
1637
|
+
// /__camera-fixtures/<name> — the staged video behind `rnx camera play`.
|
|
1638
1638
|
// the shell page is a different origin from this daemon (vite dev on 5173,
|
|
1639
1639
|
// daemon on 7668+), and the camera pipeline draws the <video> to a canvas
|
|
1640
1640
|
// and reads it back, so this needs real CORS or the canvas taints and
|
|
@@ -1766,8 +1766,8 @@ export class SootSimBridgeHost {
|
|
|
1766
1766
|
res.writeHead(503, { 'Content-Type': 'text/plain; charset=utf-8' })
|
|
1767
1767
|
res.end(
|
|
1768
1768
|
versionedRuntimeRequest
|
|
1769
|
-
? `rnx: runtime ${requestedRuntime ?? '(invalid version origin)'} is not installed. run \`
|
|
1770
|
-
: 'rnx: no active runtime installed. run `
|
|
1769
|
+
? `rnx: runtime ${requestedRuntime ?? '(invalid version origin)'} is not installed. run \`rnx open\` from that app again.`
|
|
1770
|
+
: 'rnx: no active runtime installed. run `rnx runtime install` to fetch one.',
|
|
1771
1771
|
)
|
|
1772
1772
|
return
|
|
1773
1773
|
}
|
|
@@ -2472,7 +2472,7 @@ export class SootSimBridgeHost {
|
|
|
2472
2472
|
if (candidates.length > 1) {
|
|
2473
2473
|
throw new Error(
|
|
2474
2474
|
`multiple sims are connected: ${candidates.map((sim) => sim.id).join(', ')}; ` +
|
|
2475
|
-
'run `
|
|
2475
|
+
'run `rnx use <sim>` or pass `--sim <sim>`',
|
|
2476
2476
|
)
|
|
2477
2477
|
}
|
|
2478
2478
|
const candidate = candidates[0]
|
package/src/index.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type {
|
|
|
29
29
|
SimStateResult,
|
|
30
30
|
} from './bridge-contract'
|
|
31
31
|
|
|
32
|
-
export {
|
|
32
|
+
export { rnxPlugin } from './vite-plugin-one'
|
|
33
33
|
export { default as metroPlugin } from './metro-plugin'
|
|
34
34
|
export { default as jumpToSourceBabelPlugin } from './jump-to-source-babel'
|
|
35
35
|
export {
|