rnxsim 0.1.366 → 0.1.367
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 +14 -2
- package/cli/bin.ts +18 -0
- package/cli/bridge-flow-runner.ts +14 -151
- package/cli/commands/assert.ts +1 -1
- package/cli/commands/box/checkout-plane.ts +126 -0
- package/cli/commands/box/rnx-command.ts +68 -0
- package/cli/commands/box.ts +200 -0
- package/cli/commands/control.ts +12 -32
- package/cli/commands/do-chain.ts +412 -0
- package/cli/commands/flow.ts +0 -10
- package/cli/commands/inspect/core.ts +302 -725
- package/cli/commands/inspect/describe.ts +3 -76
- package/cli/commands/inspect/find.ts +3 -6
- package/cli/commands/inspect/get-layout.ts +14 -1
- package/cli/commands/inspect/resolve-target.ts +41 -47
- package/cli/commands/inspect/shared.ts +28 -123
- package/cli/commands/inspect/tree.ts +6 -15
- package/cli/commands/inspect/wait-ready.ts +2 -2
- package/cli/commands/inspect/wait-selector.ts +4 -8
- package/cli/commands/inspect.ts +23 -17
- package/cli/commands/install-desktop.ts +44 -7
- package/cli/commands/maestro-generate.ts +0 -2
- package/cli/commands/platform.ts +68 -0
- package/cli/commands/state.ts +5 -2
- package/cli/outbound-endpoints.ts +6 -1
- package/cli/parse-args.ts +13 -2
- package/cli/ws-bridge.ts +30 -2
- package/detox/index.ts +34 -17
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-SO6IOPRK.js → agent-EKKIAKP5.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-PMYCB2KO.js → agent-wrapper-MHLQUGA6.js} +2 -2
- package/dist-cli/chunks/{app-fonts-LULQGFY7.js → app-fonts-HN6ADRTQ.js} +2 -2
- package/dist-cli/chunks/{assert-WGNCD4ZU.js → assert-IMR6QCN6.js} +3 -3
- package/dist-cli/chunks/{auth-G7CCHH3M.js → auth-27LPMQNH.js} +2 -2
- package/dist-cli/chunks/{beta-N4LXL5TO.js → beta-6RXBB5AI.js} +2 -2
- package/dist-cli/chunks/box-DORLF3GP.js +1709 -0
- package/dist-cli/chunks/{camera-4JHCYBQS.js → camera-2G7JZ5DL.js} +2 -2
- package/dist-cli/chunks/{chunk-2UXU53MG.js → chunk-3QZJLNYY.js} +1 -1
- package/dist-cli/chunks/{chunk-YXXKSL6R.js → chunk-3VBVEDDA.js} +1 -1
- package/dist-cli/chunks/{chunk-ZJIS3CTW.js → chunk-4BWGLTKU.js} +2 -2
- package/dist-cli/chunks/chunk-4XSNO374.js +423 -0
- package/dist-cli/chunks/{chunk-RYIMSKDO.js → chunk-5DGMFUZG.js} +2 -2
- package/dist-cli/chunks/{chunk-M3BNCF7E.js → chunk-6DBS5EGX.js} +2 -2
- package/dist-cli/chunks/{chunk-ONORMKWX.js → chunk-6SO6I3D5.js} +2 -2
- package/dist-cli/chunks/chunk-75EFOPXE.js +32 -0
- package/dist-cli/chunks/{chunk-5NMCF5VF.js → chunk-A5AJFVOF.js} +1 -1
- package/dist-cli/chunks/{chunk-N3UC7HIX.js → chunk-AM2ODYAN.js} +1 -1
- package/dist-cli/chunks/{chunk-I6KIM6PN.js → chunk-AVOROGA3.js} +1 -1
- package/dist-cli/chunks/chunk-AXMMLO7D.js +130 -0
- package/dist-cli/chunks/{chunk-ORWP2E7R.js → chunk-BSEXEYNX.js} +2 -2
- package/dist-cli/chunks/{chunk-NQFJOCSF.js → chunk-CM6ZKZW7.js} +2 -2
- package/dist-cli/chunks/{chunk-ZMJ75EDG.js → chunk-DNVABCEC.js} +2 -2
- package/dist-cli/chunks/{chunk-2S7BKUP2.js → chunk-E33A4AIR.js} +2 -2
- package/dist-cli/chunks/{chunk-GXAB52K7.js → chunk-EFMOXYDD.js} +2 -2
- package/dist-cli/chunks/{chunk-TIAEYO6I.js → chunk-EV4P5UBP.js} +2 -2
- package/dist-cli/chunks/{chunk-JHXETDVC.js → chunk-G5IUIGGC.js} +1 -1
- package/dist-cli/chunks/chunk-GMLOCV3E.js +312 -0
- package/dist-cli/chunks/{chunk-ZLVRYXZ7.js → chunk-GRN2FHVW.js} +1 -1
- package/dist-cli/chunks/{chunk-A5FXX5PJ.js → chunk-HFFXPUEP.js} +1 -1
- package/dist-cli/chunks/chunk-HG6T4OOR.js +4 -0
- package/dist-cli/chunks/{chunk-OW5XHAA4.js → chunk-HNT2OXPZ.js} +1 -1
- package/dist-cli/chunks/chunk-IPEURNLI.js +24 -0
- package/dist-cli/chunks/chunk-IR44SFBA.js +5 -0
- package/dist-cli/chunks/chunk-JMSLXZFW.js +4 -0
- package/dist-cli/chunks/{chunk-EFR5DVNP.js → chunk-JPXQKLNH.js} +1 -1
- package/dist-cli/chunks/chunk-K3EC6JDE.js +4 -0
- package/dist-cli/chunks/{chunk-YGMEDJKJ.js → chunk-KHX65HAU.js} +2 -2
- package/dist-cli/chunks/{chunk-EQK5MJCU.js → chunk-LWOVKHRC.js} +2 -2
- package/dist-cli/chunks/{chunk-5OK3LCEJ.js → chunk-MQN5DWTI.js} +2 -2
- package/dist-cli/chunks/{chunk-TTASWLKM.js → chunk-N3BXQEUF.js} +1 -1
- package/dist-cli/chunks/{chunk-UCHW7ZHR.js → chunk-N5OSV26B.js} +2 -2
- package/dist-cli/chunks/chunk-PHNURIH3.js +4 -0
- package/dist-cli/chunks/{chunk-AFV32WZT.js → chunk-PP2KNVXP.js} +3 -3
- package/dist-cli/chunks/{chunk-XJU2QIRY.js → chunk-PROKNJVY.js} +2 -2
- package/dist-cli/chunks/chunk-QXLLY4IM.js +7 -0
- package/dist-cli/chunks/{chunk-HT6GFZOZ.js → chunk-RNQTOGM7.js} +1 -1
- package/dist-cli/chunks/{chunk-CN6XYYEA.js → chunk-RPNKKVBN.js} +27 -27
- package/dist-cli/chunks/{chunk-LN3RNW6X.js → chunk-RSNLI2NH.js} +2 -2
- package/dist-cli/chunks/{chunk-YCCCPFWT.js → chunk-RZGHV2WI.js} +2 -2
- package/dist-cli/chunks/chunk-SGGL3AFV.js +497 -0
- package/dist-cli/chunks/chunk-SH5ETJKG.js +4 -0
- package/dist-cli/chunks/{chunk-77ZHQJZR.js → chunk-T6J4YP56.js} +2 -2
- package/dist-cli/chunks/{chunk-MGDSJZ37.js → chunk-TWUE7WF5.js} +2 -2
- package/dist-cli/chunks/{chunk-SA6XVI55.js → chunk-U44VEQRN.js} +1 -1
- package/dist-cli/chunks/{chunk-IZKHOM37.js → chunk-URLVQHC3.js} +1 -1
- package/dist-cli/chunks/{chunk-GAJQSITE.js → chunk-VANZFTUE.js} +1 -1
- package/dist-cli/chunks/{chunk-EGAGZHO6.js → chunk-VB2YBH46.js} +1 -1
- package/dist-cli/chunks/{chunk-H23KWIKA.js → chunk-VFU2SJ7M.js} +2 -2
- package/dist-cli/chunks/{chunk-34IQM22N.js → chunk-VUBJ6FXU.js} +15 -15
- package/dist-cli/chunks/{chunk-NM2L2QV4.js → chunk-W5PATILQ.js} +2 -2
- package/dist-cli/chunks/chunk-WI5V4TYG.js +38 -0
- package/dist-cli/chunks/{chunk-6PL2CCGP.js → chunk-XTRHQAOV.js} +2 -2
- package/dist-cli/chunks/chunk-XWUTJLBM.js +27 -0
- package/dist-cli/chunks/{chunk-5DAIA77C.js → chunk-XYRUQQUR.js} +2 -2
- package/dist-cli/chunks/chunk-YBFB3RM7.js +4 -0
- package/dist-cli/chunks/chunk-YGQVQ2VG.js +4 -0
- package/dist-cli/chunks/{chunk-CTG7HBCA.js → chunk-YINACV32.js} +1 -1
- package/dist-cli/chunks/chunk-YV7ERO2V.js +5 -0
- package/dist-cli/chunks/{cleanup-KRIATKFH.js → cleanup-GVFHQ3KH.js} +2 -2
- package/dist-cli/chunks/cli-version-DPX5MA2M.js +4 -0
- package/dist-cli/chunks/{compat-6PTQ3QEA.js → compat-AYRTXYAM.js} +2 -2
- package/dist-cli/chunks/{config-ETGDUANO.js → config-K7LOOV62.js} +2 -2
- package/dist-cli/chunks/connect-H3CNY4IO.js +4 -0
- package/dist-cli/chunks/control-SMHZ2CF5.js +4 -0
- package/dist-cli/chunks/daemon-TEZUNI73.js +4 -0
- package/dist-cli/chunks/{debug-WIIB6ZKC.js → debug-ELGHG57T.js} +3 -3
- package/dist-cli/chunks/{desktop-TD7Q5LNB.js → desktop-4G7FK3MP.js} +3 -3
- package/dist-cli/chunks/{detox-7GNR33VM.js → detox-JKXGEJIZ.js} +2 -2
- package/dist-cli/chunks/{device-QOR3PGUF.js → device-IV3AR6KG.js} +2 -2
- package/dist-cli/chunks/{diagnose-RRCBLP6E.js → diagnose-3ERGF7EW.js} +2 -2
- package/dist-cli/chunks/{disk-cleanup-MJUGJPXT.js → disk-cleanup-ALFEVZ4B.js} +2 -2
- package/dist-cli/chunks/do-chain-K2B4OHM7.js +5 -0
- package/dist-cli/chunks/drivers-KJYXA3M3.js +4 -0
- package/dist-cli/chunks/env-2KF6IYZE.js +4 -0
- package/dist-cli/chunks/{film-D7Y64LID.js → film-UQXJFAD5.js} +3 -3
- package/dist-cli/chunks/flow-ASTUH56E.js +4 -0
- package/dist-cli/chunks/help-SNNYFELA.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-JGURVR2Z.js → hidden-runtime-alias-VJCWCFVO.js} +2 -2
- package/dist-cli/chunks/{home-paths-4ICFIGXO.js → home-paths-EGUZZ6J6.js} +2 -2
- package/dist-cli/chunks/inspect-XANAADQT.js +4 -0
- package/dist-cli/chunks/install-desktop-JKQA7UY6.js +4 -0
- package/dist-cli/chunks/{login-RU33QR2G.js → login-6KQGD7HK.js} +2 -2
- package/dist-cli/chunks/{logout-2IUG3Y5J.js → logout-2FCOVLBC.js} +2 -2
- package/dist-cli/chunks/{maestro-2MXTGG7I.js → maestro-HPSSEVJD.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-2PYIFGLR.js → maestro-generate-KQQ6JHMR.js} +5 -5
- package/dist-cli/chunks/{mode-3DAPG3HF.js → mode-SH7KRZET.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-BWSDJF2Z.js → optional-demo-registry-NAMCAVFX.js} +2 -2
- package/dist-cli/chunks/{perf-2TKPWB4N.js → perf-LWKAHXUL.js} +2 -2
- package/dist-cli/chunks/{permissions-5CSMHYNA.js → permissions-EZTKWTXV.js} +2 -2
- package/dist-cli/chunks/platform-KSOJIVN5.js +6 -0
- package/dist-cli/chunks/privacy-EJULWP7L.js +4 -0
- package/dist-cli/chunks/{record-I2HJCFP3.js → record-2IC7BAQN.js} +3 -3
- package/dist-cli/chunks/{report-issue-A4FZWBOC.js → report-issue-MMX6HOQO.js} +2 -2
- package/dist-cli/chunks/reset-PKFZA4NC.js +4 -0
- package/dist-cli/chunks/resolve-target-AFKU3BRE.js +4 -0
- package/dist-cli/chunks/runtime-XHWWPOIN.js +4 -0
- package/dist-cli/chunks/{screenshot-command-UFW5BFHP.js → screenshot-command-JYUXDVSA.js} +3 -3
- package/dist-cli/chunks/{screenshot-layers-5BIAL4YN.js → screenshot-layers-OGRY6AA3.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-EHYS3BV2.js → screenshots-capture-QHDN65XS.js} +2 -2
- package/dist-cli/chunks/{serve-O4FDM3AC.js → serve-W4BKAG4J.js} +3 -3
- package/dist-cli/chunks/setup-WJPMPSAC.js +4 -0
- package/dist-cli/chunks/sim-client-UOQGFBPO.js +4 -0
- package/dist-cli/chunks/{skills-ZK55SY32.js → skills-OPPXOD63.js} +2 -2
- package/dist-cli/chunks/state-TDAN7BOM.js +14 -0
- package/dist-cli/chunks/{storage-WP33ISEM.js → storage-CFB2YGLY.js} +2 -2
- package/dist-cli/chunks/store-4TEED4ZU.js +4 -0
- package/dist-cli/chunks/telemetry-S6N7CV6G.js +4 -0
- package/dist-cli/chunks/{timeline-DKGW5S4I.js → timeline-ASOOVP4C.js} +2 -2
- package/dist-cli/chunks/{upgrade-LL7G4B7G.js → upgrade-6MVJISHG.js} +2 -2
- package/dist-cli/chunks/upload-CBNIRFEW.js +4 -0
- package/dist-cli/chunks/{version-YLWR5G4F.js → version-5GS7CWRL.js} +2 -2
- package/dist-cli/chunks/{web-QELZ4CP6.js → web-QRRMYMV4.js} +2 -2
- package/dist-cli/chunks/welcome-33FXMAMB.js +5 -0
- package/dist-cli/chunks/{what-happened-MIOMZWM5.js → what-happened-GAZJGKXX.js} +2 -2
- package/dist-cli/chunks/ws-bridge-DIXUAPLQ.js +4 -0
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- 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-input.cjs +336 -0
- package/dist-lib/bridge-contract-input.mjs +303 -0
- package/dist-lib/bridge-contract.cjs +29 -1
- package/dist-lib/bridge-contract.mjs +19 -0
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +32 -18
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +5 -1
- 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/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +214 -594
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +273 -657
- package/dist-lib/sdk.mjs +271 -652
- package/dist-lib/skills.cjs +190 -287
- package/dist-lib/vite.cjs +1 -1
- package/package.json +9 -6
- package/skills/contrast/SKILL.md +3 -0
- package/skills/rnx-debug/SKILL.md +8 -0
- package/skills/rnx-test/SKILL.md +21 -0
- package/src/bridge-contract-input.ts +359 -0
- package/src/bridge-contract.ts +121 -1
- package/src/host/bridge-host.ts +7 -12
- package/src/index.ts +7 -0
- package/src/sim-client.ts +12 -3
- package/dist-cli/chunks/chunk-3X6IBUBX.js +0 -38
- package/dist-cli/chunks/chunk-7B37IZBN.js +0 -15
- package/dist-cli/chunks/chunk-DMPF2D24.js +0 -4
- package/dist-cli/chunks/chunk-DW37EVX5.js +0 -767
- package/dist-cli/chunks/chunk-DWFIH7CB.js +0 -32
- package/dist-cli/chunks/chunk-GUI3PDH2.js +0 -27
- package/dist-cli/chunks/chunk-KLF3K6ZZ.js +0 -4
- package/dist-cli/chunks/chunk-M5QCGLXR.js +0 -944
- package/dist-cli/chunks/chunk-M6SKQGAN.js +0 -5
- package/dist-cli/chunks/chunk-NAYLPOC5.js +0 -24
- package/dist-cli/chunks/chunk-VIND4SP3.js +0 -124
- package/dist-cli/chunks/chunk-XXNLYR64.js +0 -5
- package/dist-cli/chunks/chunk-ZFM24DOX.js +0 -4
- package/dist-cli/chunks/cli-version-SYGNHGFR.js +0 -4
- package/dist-cli/chunks/control-RBTNOLQM.js +0 -4
- package/dist-cli/chunks/daemon-N3SC5DK6.js +0 -4
- package/dist-cli/chunks/drivers-W6E3BZH4.js +0 -4
- package/dist-cli/chunks/flow-7QAE2V5Y.js +0 -4
- package/dist-cli/chunks/help-NLD6KWVG.js +0 -4
- package/dist-cli/chunks/inspect-C347BG52.js +0 -4
- package/dist-cli/chunks/install-desktop-YR6TWZYK.js +0 -4
- package/dist-cli/chunks/privacy-PWWC2BXO.js +0 -4
- package/dist-cli/chunks/reset-Y3PBPFYA.js +0 -4
- package/dist-cli/chunks/runtime-IC6NVVGA.js +0 -4
- package/dist-cli/chunks/setup-Y4QGSJBM.js +0 -4
- package/dist-cli/chunks/state-KFLAZNEY.js +0 -14
- package/dist-cli/chunks/store-VEE22CAY.js +0 -4
- package/dist-cli/chunks/telemetry-PZV4BISJ.js +0 -4
- package/dist-cli/chunks/upload-Y4C3YZDK.js +0 -4
- package/dist-cli/chunks/welcome-ZPKA5PZJ.js +0 -5
- package/dist-lib/mcp.cjs +0 -673
- package/dist-lib/mcp.mjs +0 -641
- package/src/mcp.ts +0 -791
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
// `sootsim describe` —
|
|
2
|
-
//
|
|
3
|
-
// see packages/sootsim-engine/src/test-bridge.ts for the actual dumpTree impl
|
|
4
|
-
// that powers this. the CLI-side job is just: optional preflight for in-flight
|
|
5
|
-
// screen transitions, call dumpTree with the right flags, and pretty-print.
|
|
1
|
+
// `sootsim describe` — format the pruned visible semantic tree.
|
|
6
2
|
|
|
7
3
|
import { maybeHint } from '../../hints'
|
|
8
4
|
import { inspectDescribe, type DescribeDumpOptions } from './core'
|
|
@@ -34,18 +30,6 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
|
|
|
34
30
|
const watchInterval = 1000
|
|
35
31
|
const compact = args.includes('--compact')
|
|
36
32
|
const hideXy = args.includes('--no-xy')
|
|
37
|
-
// when set, strip rows annotated `(clipped:left|right|top|bottom)` from the
|
|
38
|
-
// output. dumpTree marks anything that overflows the viewport so search
|
|
39
|
-
// context is preserved, but the rows balloon the output on screens like
|
|
40
|
-
// 3pc's profile (off-screen list items + edge-pulled chrome). this flag is
|
|
41
|
-
// a client-side filter so we don't need a roundtrip to dumpTree.
|
|
42
|
-
const hideClipped = args.includes('--no-clipped')
|
|
43
|
-
// by default describe hides nodes that sit fully behind a modal/sheet/popover
|
|
44
|
-
// scrim — they aren't reachable, and listing them as `(tap)` misleads agents
|
|
45
|
-
// into tapping content that's actually occluded. --include-occluded surfaces
|
|
46
|
-
// them annotated `(behind)`.
|
|
47
|
-
const includeOccluded = args.includes('--include-occluded')
|
|
48
|
-
|
|
49
33
|
const testIdLike = flagValue(args, '--testid-like')
|
|
50
34
|
const onlyGlob = flagValue(args, '--only')
|
|
51
35
|
const subtreeRoot = flagValue(args, '--subtree')
|
|
@@ -74,35 +58,17 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
|
|
|
74
58
|
subtreeRoot: subtreeRoot || undefined,
|
|
75
59
|
compact,
|
|
76
60
|
hideXy,
|
|
77
|
-
includeOccluded,
|
|
78
61
|
// no terminal to fit, so nothing gets clipped on the way out
|
|
79
62
|
fullText: jsonOut,
|
|
80
63
|
}
|
|
81
64
|
const result = await inspectDescribe(bridge, dumpOpts)
|
|
82
65
|
const tree = result?.tree
|
|
83
|
-
const shell = result?.shell
|
|
84
|
-
const keyboard = result?.keyboard
|
|
85
66
|
|
|
86
67
|
if (jsonOut) {
|
|
87
|
-
printJson({
|
|
68
|
+
printJson({ tree: tree ?? '' })
|
|
88
69
|
return
|
|
89
70
|
}
|
|
90
71
|
|
|
91
|
-
// show shell state in header if available
|
|
92
|
-
if (shell && typeof shell === 'object') {
|
|
93
|
-
const shellParts = [
|
|
94
|
-
shell.state ? `state=${shell.state}` : null,
|
|
95
|
-
shell.activeApp ? `app=${shell.activeApp}` : null,
|
|
96
|
-
shell.showSwitcher ? 'switcher' : null,
|
|
97
|
-
shell.switcherPhase && shell.switcherPhase !== 'idle'
|
|
98
|
-
? `phase=${shell.switcherPhase}`
|
|
99
|
-
: null,
|
|
100
|
-
].filter(Boolean)
|
|
101
|
-
if (shellParts.length > 0) {
|
|
102
|
-
console.log(` shell: ${shellParts.join(' ')}`)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
72
|
if (typeof tree === 'string' && tree.startsWith('__SUBTREE_NOT_FOUND__:')) {
|
|
107
73
|
const missing = tree.slice('__SUBTREE_NOT_FOUND__:'.length)
|
|
108
74
|
console.log(` subtree root not found: ${missing}`)
|
|
@@ -120,26 +86,7 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
|
|
|
120
86
|
return
|
|
121
87
|
}
|
|
122
88
|
|
|
123
|
-
|
|
124
|
-
let hiddenClippedCount = 0
|
|
125
|
-
if (hideClipped && typeof rendered === 'string') {
|
|
126
|
-
const lines = rendered.split('\n')
|
|
127
|
-
const kept: string[] = []
|
|
128
|
-
for (const line of lines) {
|
|
129
|
-
if (line.includes('(clipped:')) {
|
|
130
|
-
hiddenClippedCount += 1
|
|
131
|
-
continue
|
|
132
|
-
}
|
|
133
|
-
kept.push(line)
|
|
134
|
-
}
|
|
135
|
-
rendered = kept.join('\n')
|
|
136
|
-
}
|
|
137
|
-
console.log(rendered)
|
|
138
|
-
if (hiddenClippedCount > 0) {
|
|
139
|
-
console.log(
|
|
140
|
-
` ${hiddenClippedCount} clipped row(s) hidden (omit --no-clipped to see)`,
|
|
141
|
-
)
|
|
142
|
-
}
|
|
89
|
+
console.log(tree)
|
|
143
90
|
|
|
144
91
|
const anyFilterActive = filter || testIdLike || effectiveOnlyGlob || subtreeRoot
|
|
145
92
|
const searchFilterActive = filter || testIdLike || effectiveOnlyGlob
|
|
@@ -157,26 +104,6 @@ export async function runDescribeSubcommand(opts: DescribeOptions): Promise<void
|
|
|
157
104
|
maybeHint('describe-use-filters')
|
|
158
105
|
}
|
|
159
106
|
}
|
|
160
|
-
|
|
161
|
-
// keyboard summary — only when visible. rendered as a footer so it
|
|
162
|
-
// doesn't bury the tree on forms with non-trivial UI above the input.
|
|
163
|
-
if (keyboard && keyboard.visible) {
|
|
164
|
-
const spec = keyboard.spec
|
|
165
|
-
const kbParts = [
|
|
166
|
-
spec?.keyboardType ? `type=${spec.keyboardType}` : null,
|
|
167
|
-
spec?.returnKeyType && spec.returnKeyType !== 'default'
|
|
168
|
-
? `return=${spec.returnKeyType}`
|
|
169
|
-
: null,
|
|
170
|
-
keyboard.mode !== 'letters' ? `mode=${keyboard.mode}` : null,
|
|
171
|
-
keyboard.shifted ? 'shift' : null,
|
|
172
|
-
keyboard.capsLock ? 'caps' : null,
|
|
173
|
-
spec?.autoCapitalize && spec.autoCapitalize !== 'sentences'
|
|
174
|
-
? `autoCap=${spec.autoCapitalize}`
|
|
175
|
-
: null,
|
|
176
|
-
keyboard.accessoryBarId ? `accessory=${keyboard.accessoryBarId}` : null,
|
|
177
|
-
].filter(Boolean)
|
|
178
|
-
console.log(`\n keyboard: ${kbParts.join(' ') || 'visible'}`)
|
|
179
|
-
}
|
|
180
107
|
}
|
|
181
108
|
|
|
182
109
|
if (watch) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { maybeHint } from '../../hints'
|
|
2
|
-
import { inspectFind, rankInteractive, tapCommandForNode } from './core'
|
|
2
|
+
import { inspectFind, inspectNodeCount, rankInteractive, tapCommandForNode } from './core'
|
|
3
3
|
import { printJson, wantsJson } from './shared'
|
|
4
4
|
import type { WsBridge } from '../../ws-bridge'
|
|
5
5
|
|
|
@@ -78,11 +78,8 @@ export async function runFindSubcommand(opts: {
|
|
|
78
78
|
} else if (Array.isArray(result)) {
|
|
79
79
|
if (result.length === 0) {
|
|
80
80
|
console.log(` no ${mode} nodes found`)
|
|
81
|
-
const nodeCount = await bridge
|
|
82
|
-
|
|
83
|
-
code: '(async () => (await window.__sootsimTest?.getNodeCount?.()) || 0)()',
|
|
84
|
-
})
|
|
85
|
-
if (typeof nodeCount === 'number' && nodeCount < 10) {
|
|
81
|
+
const { nodes: nodeCount } = await inspectNodeCount(bridge)
|
|
82
|
+
if (nodeCount < 10) {
|
|
86
83
|
maybeHint('app-still-loading', nodeCount)
|
|
87
84
|
}
|
|
88
85
|
} else if (mode === 'interactive-targets') {
|
|
@@ -25,7 +25,20 @@ export async function runGetLayoutSubcommand(opts: {
|
|
|
25
25
|
const styling = args.includes('--styling')
|
|
26
26
|
const filterIndex = args.indexOf('--filter')
|
|
27
27
|
const filter = filterIndex >= 0 ? args[filterIndex + 1] : undefined
|
|
28
|
-
const elements = await inspectGetLayout(bridge, { styling, filter })
|
|
28
|
+
const elements = await inspectGetLayout(bridge, { styling, filter }).catch(
|
|
29
|
+
(error: unknown) => {
|
|
30
|
+
if (
|
|
31
|
+
styling &&
|
|
32
|
+
error instanceof Error &&
|
|
33
|
+
error.message === 'unsupported RNX Cloud command type: evaluate'
|
|
34
|
+
) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
'get layout --styling is unavailable in RNX Cloud; rerun without --styling or use a local sim',
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
throw error
|
|
40
|
+
},
|
|
41
|
+
)
|
|
29
42
|
if (jsonOut) {
|
|
30
43
|
printJson({ count: elements.length, elements })
|
|
31
44
|
return
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSimSemanticTree } from './core'
|
|
1
2
|
import type { WsBridge } from '../../ws-bridge'
|
|
2
3
|
|
|
3
4
|
// read a --testid / --text flag from args. returns null when neither is
|
|
@@ -26,57 +27,50 @@ export function readTargetFlag(
|
|
|
26
27
|
return null
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
export
|
|
30
|
-
bridge: WsBridge,
|
|
31
|
-
target: { mode: 'testid' | 'text'; value: string },
|
|
32
|
-
): Promise<{
|
|
30
|
+
export interface ResolvedTargetCoords {
|
|
33
31
|
x: number
|
|
34
32
|
y: number
|
|
35
|
-
id?: string | null
|
|
36
33
|
testID?: string | null
|
|
37
34
|
text?: string | null
|
|
38
35
|
type?: string | null
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const result = await bridge.send({
|
|
46
|
-
type: '
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (!t) return null
|
|
50
|
-
const n = ${findExpr}
|
|
51
|
-
if (!n || !n.absolutePosition || !n.layout) return null
|
|
52
|
-
const resolved =
|
|
53
|
-
typeof n.nodeId === 'number' && typeof t.resolveTapTarget === 'function'
|
|
54
|
-
? await t.resolveTapTarget(n.nodeId)
|
|
55
|
-
: null
|
|
56
|
-
const cx =
|
|
57
|
-
typeof resolved?.cx === 'number'
|
|
58
|
-
? resolved.cx
|
|
59
|
-
: n.absolutePosition.x + (n.layout.width || 0) / 2
|
|
60
|
-
const cy =
|
|
61
|
-
typeof resolved?.cy === 'number'
|
|
62
|
-
? resolved.cy
|
|
63
|
-
: n.absolutePosition.y + (n.layout.height || 0) / 2
|
|
64
|
-
return {
|
|
65
|
-
x: cx,
|
|
66
|
-
y: cy,
|
|
67
|
-
id: n.id ?? null,
|
|
68
|
-
testID: n.testID ?? null,
|
|
69
|
-
text: ${JSON.stringify(target.mode === 'text')} ? ${arg} : (n.text ?? n.accessibilityLabel ?? null),
|
|
70
|
-
type: n.type ?? null,
|
|
71
|
-
}
|
|
72
|
-
})()`,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function resolveTargetCoords(
|
|
39
|
+
bridge: WsBridge,
|
|
40
|
+
target: { mode: 'testid' | 'text'; value: string },
|
|
41
|
+
): Promise<ResolvedTargetCoords | null> {
|
|
42
|
+
const result: unknown = await bridge.send({
|
|
43
|
+
type: 'resolve',
|
|
44
|
+
selector:
|
|
45
|
+
target.mode === 'testid' ? { testID: target.value } : { text: target.value },
|
|
73
46
|
})
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
47
|
+
if (result === null) return null
|
|
48
|
+
if (typeof result !== 'object') throw new Error('resolve returned an invalid result')
|
|
49
|
+
const match = Reflect.get(result, 'match')
|
|
50
|
+
const resolvedTarget = Reflect.get(result, 'target')
|
|
51
|
+
const semanticNodes = [match, resolvedTarget]
|
|
52
|
+
const point = Reflect.get(result, 'point')
|
|
53
|
+
const x =
|
|
54
|
+
point !== null && typeof point === 'object' ? Reflect.get(point, 'x') : undefined
|
|
55
|
+
const y =
|
|
56
|
+
point !== null && typeof point === 'object' ? Reflect.get(point, 'y') : undefined
|
|
57
|
+
if (
|
|
58
|
+
!isSimSemanticTree(semanticNodes) ||
|
|
59
|
+
typeof x !== 'number' ||
|
|
60
|
+
!Number.isFinite(x) ||
|
|
61
|
+
typeof y !== 'number' ||
|
|
62
|
+
!Number.isFinite(y)
|
|
63
|
+
) {
|
|
64
|
+
throw new Error('resolve returned an invalid result')
|
|
65
|
+
}
|
|
66
|
+
const semanticMatch = semanticNodes[0]
|
|
67
|
+
if (!semanticMatch) throw new Error('resolve returned an invalid result')
|
|
68
|
+
return {
|
|
69
|
+
x,
|
|
70
|
+
y,
|
|
71
|
+
testID: semanticMatch.testID ?? null,
|
|
72
|
+
text:
|
|
73
|
+
semanticMatch.text ?? (target.mode === 'text' ? target.value : semanticMatch.label),
|
|
74
|
+
type: semanticMatch.type,
|
|
75
|
+
}
|
|
82
76
|
}
|
|
@@ -11,14 +11,7 @@ import {
|
|
|
11
11
|
type ParsedBridgeCliArgs,
|
|
12
12
|
type WsBridge,
|
|
13
13
|
} from '../../ws-bridge'
|
|
14
|
-
import {
|
|
15
|
-
getShellState,
|
|
16
|
-
isShellCommandUnavailable,
|
|
17
|
-
readyProbeHasContent,
|
|
18
|
-
READY_NODE_STABLE_MS,
|
|
19
|
-
WAIT_READY_PROBE,
|
|
20
|
-
type ReadyProbe,
|
|
21
|
-
} from './core'
|
|
14
|
+
import { getShellState, inspectWaitReady, isShellCommandUnavailable } from './core'
|
|
22
15
|
import type { SootSimScreenTransitionWaitResult } from '@sootsim/globals'
|
|
23
16
|
|
|
24
17
|
// shell-state helpers live in the transport-agnostic kernel module so the CLI
|
|
@@ -230,124 +223,36 @@ export interface ReloadReadyResult {
|
|
|
230
223
|
errors: number
|
|
231
224
|
}
|
|
232
225
|
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
// shell-events-bridge on the `sootsim:externalAppReady` event, plus visible
|
|
237
|
-
// inspectable content (or a larger non-placeholder tree) and a brief stable
|
|
238
|
-
// node count. a single long in-page evaluate can hold a stale shell-owned tree
|
|
239
|
-
// snapshot until it returns; separate probes let the host process pending
|
|
240
|
-
// shellTreeUpdate traffic between reads. bails early if the console picks up
|
|
241
|
-
// errors after a grace period with the flag still unset — fatal bundle/eval
|
|
242
|
-
// failures pile up errors fast and never emit ready, so waiting the full
|
|
243
|
-
// budget just wastes wall time. falls back to the same content gate on timeout
|
|
244
|
-
// so apps that never wire up the shell-events bridge don't hard-fail reload.
|
|
226
|
+
// post-reload readiness is the same engine-owned condition as `rnx wait ready`.
|
|
227
|
+
// keeping reload on that primitive prevents another polling implementation
|
|
228
|
+
// from drifting on loading text, live frames, or tree stability.
|
|
245
229
|
export async function pollForReloadReady(
|
|
246
230
|
bridge: WsBridge,
|
|
247
|
-
opts: {
|
|
248
|
-
timeoutMs?: number
|
|
249
|
-
errorGraceMs?: number
|
|
250
|
-
pollIntervalMs?: number
|
|
251
|
-
} = {},
|
|
231
|
+
opts: { timeoutMs?: number } = {},
|
|
252
232
|
): Promise<ReloadReadyResult> {
|
|
253
233
|
const timeoutMs = opts.timeoutMs ?? 10000
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
ready:
|
|
264
|
-
source
|
|
265
|
-
elapsedMs:
|
|
266
|
-
nodes:
|
|
267
|
-
targets:
|
|
268
|
-
liveFrameActive:
|
|
269
|
-
liveFrameChannels:
|
|
270
|
-
liveFramePublishes:
|
|
271
|
-
flag:
|
|
272
|
-
loadingText:
|
|
273
|
-
externalReady:
|
|
274
|
-
externalStatus:
|
|
275
|
-
externalError:
|
|
276
|
-
errors:
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
while (Date.now() < deadline) {
|
|
280
|
-
try {
|
|
281
|
-
const probe = (await bridge.send({
|
|
282
|
-
type: 'evaluate',
|
|
283
|
-
code: WAIT_READY_PROBE,
|
|
284
|
-
})) as Partial<ReadyProbe> | null
|
|
285
|
-
const elapsedMs = Date.now() - start
|
|
286
|
-
const nodes = Number(probe?.nodes) || 0
|
|
287
|
-
const targets = Number(probe?.targets) || 0
|
|
288
|
-
const liveFrameActive = probe?.liveFrameActive === true
|
|
289
|
-
const liveFrameChannels = Number(probe?.liveFrameChannels) || 0
|
|
290
|
-
const liveFramePublishes = Number(probe?.liveFramePublishes) || 0
|
|
291
|
-
const errors = Number(probe?.errors) || 0
|
|
292
|
-
const readyFlag = probe?.flag === true
|
|
293
|
-
const externalReady = probe?.externalReady
|
|
294
|
-
const loadingText =
|
|
295
|
-
typeof probe?.loadingText === 'string' ? probe.loadingText.trim() : ''
|
|
296
|
-
const externalStatus =
|
|
297
|
-
typeof probe?.externalStatus === 'string' ? probe.externalStatus.trim() : ''
|
|
298
|
-
const externalError =
|
|
299
|
-
typeof probe?.externalError === 'string' ? probe.externalError.trim() : ''
|
|
300
|
-
const externalErrored =
|
|
301
|
-
typeof probe?.externalError === 'string' && externalError.length > 0
|
|
302
|
-
lastExternalReady = externalReady
|
|
303
|
-
lastExternalErrored = externalErrored
|
|
304
|
-
if (nodes !== lastNodes) {
|
|
305
|
-
lastNodes = nodes
|
|
306
|
-
nodeStableSince = elapsedMs
|
|
307
|
-
}
|
|
308
|
-
last = {
|
|
309
|
-
ready: false,
|
|
310
|
-
source: 'timeout',
|
|
311
|
-
elapsedMs,
|
|
312
|
-
nodes,
|
|
313
|
-
targets,
|
|
314
|
-
liveFrameActive,
|
|
315
|
-
liveFrameChannels,
|
|
316
|
-
liveFramePublishes,
|
|
317
|
-
flag: probe?.flag,
|
|
318
|
-
loadingText,
|
|
319
|
-
externalReady: typeof externalReady === 'boolean' ? externalReady : null,
|
|
320
|
-
externalStatus,
|
|
321
|
-
externalError,
|
|
322
|
-
errors,
|
|
323
|
-
}
|
|
324
|
-
if (
|
|
325
|
-
readyFlag &&
|
|
326
|
-
externalReady !== false &&
|
|
327
|
-
!externalErrored &&
|
|
328
|
-
!loadingText &&
|
|
329
|
-
readyProbeHasContent({ liveFrameActive, nodes, targets })
|
|
330
|
-
) {
|
|
331
|
-
if (elapsedMs - nodeStableSince >= READY_NODE_STABLE_MS) {
|
|
332
|
-
return { ...last, ready: true, source: 'flag' }
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
if (elapsedMs >= errorGraceMs && errors > 0 && !readyFlag) {
|
|
336
|
-
return { ...last, ready: false, source: 'error-bail' }
|
|
337
|
-
}
|
|
338
|
-
} catch {
|
|
339
|
-
// transient bridge disconnect during full-page reload — keep polling.
|
|
340
|
-
}
|
|
341
|
-
await sleep(pollIntervalMs)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (
|
|
345
|
-
lastExternalReady !== false &&
|
|
346
|
-
!lastExternalErrored &&
|
|
347
|
-
!last.loadingText &&
|
|
348
|
-
readyProbeHasContent(last)
|
|
349
|
-
) {
|
|
350
|
-
return { ...last, ready: true, source: 'nodes-fallback' }
|
|
234
|
+
const status = await inspectWaitReady(bridge, timeoutMs)
|
|
235
|
+
const source = status.ready
|
|
236
|
+
? status.flag === true
|
|
237
|
+
? 'flag'
|
|
238
|
+
: 'nodes-fallback'
|
|
239
|
+
: status.errors > 0 && status.flag !== true
|
|
240
|
+
? 'error-bail'
|
|
241
|
+
: 'timeout'
|
|
242
|
+
return {
|
|
243
|
+
ready: status.ready,
|
|
244
|
+
source,
|
|
245
|
+
elapsedMs: status.elapsedMs,
|
|
246
|
+
nodes: status.nodes,
|
|
247
|
+
targets: status.targets,
|
|
248
|
+
liveFrameActive: status.liveFrameActive,
|
|
249
|
+
liveFrameChannels: status.liveFrameChannels,
|
|
250
|
+
liveFramePublishes: status.liveFramePublishes,
|
|
251
|
+
flag: status.flag,
|
|
252
|
+
loadingText: status.loadingText,
|
|
253
|
+
externalReady: status.externalReady,
|
|
254
|
+
externalStatus: status.externalStatus,
|
|
255
|
+
externalError: status.externalError,
|
|
256
|
+
errors: status.errors,
|
|
351
257
|
}
|
|
352
|
-
return { ...last, ready: false, source: 'timeout', elapsedMs: Date.now() - start }
|
|
353
258
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
// `sootsim get tree` —
|
|
2
|
-
//
|
|
3
|
-
// goes through the merged test bridge (shell + tenant) rather than the raw
|
|
4
|
-
// tree message, which only walks the tenant root.
|
|
1
|
+
// `sootsim get tree` — pruned structured semantic tree, default depth 5.
|
|
5
2
|
|
|
6
|
-
import { inspectTree } from './core'
|
|
3
|
+
import { formatSemanticTree, inspectTree, isSimSemanticTree } from './core'
|
|
7
4
|
import { printJson, wantsJson } from './shared'
|
|
8
5
|
import type { WsBridge } from '../../ws-bridge'
|
|
9
6
|
|
|
@@ -13,20 +10,14 @@ export async function runTreeSubcommand(opts: {
|
|
|
13
10
|
positional: string[]
|
|
14
11
|
}): Promise<void> {
|
|
15
12
|
const { bridge, args, positional } = opts
|
|
16
|
-
// --boxes
|
|
17
|
-
//
|
|
18
|
-
// tooling that needs real geometry, not the rendered text dump. deeper
|
|
19
|
-
// default depth because geometry consumers want the whole tree.
|
|
13
|
+
// --boxes keeps the deeper default expected by geometry consumers. the
|
|
14
|
+
// semantic tree is structured in both modes.
|
|
20
15
|
const boxes = args.includes('--boxes')
|
|
21
16
|
const depth = positional[1] ? Number(positional[1]) : boxes ? 50 : 5
|
|
22
|
-
const { tree } = await inspectTree(
|
|
23
|
-
bridge,
|
|
24
|
-
depth,
|
|
25
|
-
boxes ? { format: 'boxes' } : undefined,
|
|
26
|
-
)
|
|
17
|
+
const { tree } = await inspectTree(bridge, depth)
|
|
27
18
|
if (wantsJson(args)) {
|
|
28
19
|
printJson({ depth, tree: tree ?? null })
|
|
29
20
|
return
|
|
30
21
|
}
|
|
31
|
-
console.log(
|
|
22
|
+
console.log(isSimSemanticTree(tree) ? formatSemanticTree(tree) : '')
|
|
32
23
|
}
|
|
@@ -6,8 +6,8 @@ import type { WsBridge } from '../../ws-bridge'
|
|
|
6
6
|
// inspectable content. the persistent window flag
|
|
7
7
|
// `__sootsimExternalAppReady` is necessary but not sufficient: shell-owned
|
|
8
8
|
// canvas can expose a stable launch/loading tree before the app content lands.
|
|
9
|
-
// the polling loop
|
|
10
|
-
//
|
|
9
|
+
// the engine owns the polling loop; this handler sends one request, then
|
|
10
|
+
// reports the typed result.
|
|
11
11
|
export async function runWaitReadySubcommand(opts: {
|
|
12
12
|
bridge: WsBridge
|
|
13
13
|
args: string[]
|
|
@@ -2,8 +2,8 @@ import { inspectWaitSelector } from './core'
|
|
|
2
2
|
import type { WsBridge } from '../../ws-bridge'
|
|
3
3
|
|
|
4
4
|
// blocks until a node with the given testID is present and laid out, or — with
|
|
5
|
-
// `--gone` — until it is absent. the polling
|
|
6
|
-
//
|
|
5
|
+
// `--gone` — until it is absent. the engine owns the polling loop and this
|
|
6
|
+
// handler sends one request, then reports.
|
|
7
7
|
export async function runWaitSelectorSubcommand(opts: {
|
|
8
8
|
bridge: WsBridge
|
|
9
9
|
args: string[]
|
|
@@ -38,12 +38,8 @@ export async function runWaitSelectorSubcommand(opts: {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
if (found && node) {
|
|
41
|
-
const loc = node.
|
|
42
|
-
|
|
43
|
-
: ''
|
|
44
|
-
const size = node.layout
|
|
45
|
-
? `${Math.round(node.layout.width)}x${Math.round(node.layout.height)}`
|
|
46
|
-
: '?x?'
|
|
41
|
+
const loc = `@(${Math.round(node.geometry.x)},${Math.round(node.geometry.y)})`
|
|
42
|
+
const size = `${Math.round(node.geometry.width)}x${Math.round(node.geometry.height)}`
|
|
47
43
|
console.log(` found #${testId} in ${elapsed}ms ${size} ${loc}`)
|
|
48
44
|
} else {
|
|
49
45
|
console.error(
|
package/cli/commands/inspect.ts
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
filterLogEntries,
|
|
46
46
|
inspectAccessibilityTree,
|
|
47
47
|
inspectErrors,
|
|
48
|
+
inspectFind,
|
|
48
49
|
inspectLogs,
|
|
49
50
|
inspectRequests,
|
|
50
51
|
inspectWarnings,
|
|
@@ -1060,8 +1061,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1060
1061
|
// nothing). value-taking describe flags live in stripValueFlags below.
|
|
1061
1062
|
'--compact',
|
|
1062
1063
|
'--no-xy',
|
|
1063
|
-
'--no-clipped',
|
|
1064
|
-
'--include-occluded',
|
|
1065
1064
|
],
|
|
1066
1065
|
stripValueFlags: [
|
|
1067
1066
|
'--output',
|
|
@@ -1749,12 +1748,28 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1749
1748
|
await runGetLayoutSubcommand({ bridge, args: effectiveArgs })
|
|
1750
1749
|
break
|
|
1751
1750
|
}
|
|
1752
|
-
|
|
1753
|
-
const
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1751
|
+
const found = await inspectFind(bridge, { testId: id })
|
|
1752
|
+
const node = found?.result
|
|
1753
|
+
if (node === null || typeof node !== 'object' || Array.isArray(node)) {
|
|
1754
|
+
console.log('null')
|
|
1755
|
+
break
|
|
1756
|
+
}
|
|
1757
|
+
const absolute = Reflect.get(node, 'absolutePosition')
|
|
1758
|
+
const size = Reflect.get(node, 'layout')
|
|
1759
|
+
console.log(
|
|
1760
|
+
JSON.stringify(
|
|
1761
|
+
absolute && size
|
|
1762
|
+
? {
|
|
1763
|
+
x: Reflect.get(absolute, 'x'),
|
|
1764
|
+
y: Reflect.get(absolute, 'y'),
|
|
1765
|
+
width: Reflect.get(size, 'width'),
|
|
1766
|
+
height: Reflect.get(size, 'height'),
|
|
1767
|
+
}
|
|
1768
|
+
: null,
|
|
1769
|
+
null,
|
|
1770
|
+
2,
|
|
1771
|
+
),
|
|
1772
|
+
)
|
|
1758
1773
|
break
|
|
1759
1774
|
}
|
|
1760
1775
|
|
|
@@ -1906,14 +1921,12 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
1906
1921
|
cx: resolved.x,
|
|
1907
1922
|
cy: resolved.y,
|
|
1908
1923
|
match: {
|
|
1909
|
-
id: target.mode === 'testid' ? target.value : (resolved.id ?? null),
|
|
1910
1924
|
testID:
|
|
1911
1925
|
target.mode === 'testid' ? target.value : (resolved.testID ?? null),
|
|
1912
1926
|
text: target.mode === 'text' ? target.value : (resolved.text ?? null),
|
|
1913
1927
|
type: resolved.type ?? null,
|
|
1914
1928
|
},
|
|
1915
1929
|
target: {
|
|
1916
|
-
id: resolved.id ?? null,
|
|
1917
1930
|
testID: resolved.testID ?? null,
|
|
1918
1931
|
text: resolved.text ?? null,
|
|
1919
1932
|
type: resolved.type ?? null,
|
|
@@ -2684,7 +2697,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2684
2697
|
let y = Number(positional[2])
|
|
2685
2698
|
const target = readTargetFlag(args, positional)
|
|
2686
2699
|
let resolvedTarget: {
|
|
2687
|
-
id?: string | null
|
|
2688
2700
|
testID?: string | null
|
|
2689
2701
|
text?: string | null
|
|
2690
2702
|
type?: string | null
|
|
@@ -2701,7 +2713,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
2701
2713
|
x = resolved.x
|
|
2702
2714
|
y = resolved.y
|
|
2703
2715
|
resolvedTarget = {
|
|
2704
|
-
id: resolved.id ?? null,
|
|
2705
2716
|
testID: resolved.testID ?? null,
|
|
2706
2717
|
text: resolved.text ?? null,
|
|
2707
2718
|
type: resolved.type ?? null,
|
|
@@ -3382,7 +3393,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3382
3393
|
// failures surface as console errors that pile up fast — bail early
|
|
3383
3394
|
// in that case instead of waiting the full budget.
|
|
3384
3395
|
const READY_TIMEOUT_MS = 10000
|
|
3385
|
-
const ERROR_GRACE_MS = 3000
|
|
3386
3396
|
let issuedReload = false
|
|
3387
3397
|
let inPlaceReload = false
|
|
3388
3398
|
try {
|
|
@@ -3432,7 +3442,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3432
3442
|
if (inPlaceReload) {
|
|
3433
3443
|
readyResult = await pollForReloadReady(bridge, {
|
|
3434
3444
|
timeoutMs: READY_TIMEOUT_MS,
|
|
3435
|
-
errorGraceMs: ERROR_GRACE_MS,
|
|
3436
3445
|
})
|
|
3437
3446
|
} else {
|
|
3438
3447
|
// full page reload — wait for a fresh bridge before polling for ready.
|
|
@@ -3452,7 +3461,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3452
3461
|
finalBridge = reconnected
|
|
3453
3462
|
readyResult = await pollForReloadReady(reconnected, {
|
|
3454
3463
|
timeoutMs: PAGE_RELOAD_TIMEOUT_MS,
|
|
3455
|
-
errorGraceMs: ERROR_GRACE_MS,
|
|
3456
3464
|
})
|
|
3457
3465
|
} else {
|
|
3458
3466
|
console.log(
|
|
@@ -3517,7 +3525,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3517
3525
|
|
|
3518
3526
|
case 'storage-clear': {
|
|
3519
3527
|
const READY_TIMEOUT_MS = 10000
|
|
3520
|
-
const ERROR_GRACE_MS = 3000
|
|
3521
3528
|
await clearConsole(bridge)
|
|
3522
3529
|
const cleared = await bridge.send({
|
|
3523
3530
|
type: 'evaluate',
|
|
@@ -3541,7 +3548,6 @@ export async function runInspect(args: string[], opts: InspectOptions) {
|
|
|
3541
3548
|
|
|
3542
3549
|
const readyResult = await pollForReloadReady(bridge, {
|
|
3543
3550
|
timeoutMs: READY_TIMEOUT_MS,
|
|
3544
|
-
errorGraceMs: ERROR_GRACE_MS,
|
|
3545
3551
|
})
|
|
3546
3552
|
|
|
3547
3553
|
if (wantsJson(effectiveArgs)) {
|