peachsim 0.1.577 → 0.1.579
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/LICENSE +1 -1
- package/README.md +11 -9
- package/cli/app-catalog.ts +77 -0
- package/cli/app-fonts.ts +4 -20
- package/cli/app-splash.ts +2 -18
- package/cli/bridge-flow-runner.ts +505 -139
- package/cli/cloud-client.ts +1 -4
- package/cli/cloud-session.ts +1 -4
- package/cli/cloud-test-result-files.ts +3 -0
- package/cli/cloud-test-tunnel.ts +2 -5
- package/cli/command-registry.ts +2 -0
- package/cli/commands/agent.ts +149 -23
- package/cli/commands/assert.ts +1 -4
- package/cli/commands/box/peach-command.ts +62 -0
- package/cli/commands/box/plane-share.ts +0 -70
- package/cli/commands/box/rnx-command.ts +1 -60
- package/cli/commands/box/search-command.ts +14 -0
- package/cli/commands/box.ts +2 -2
- package/cli/commands/control.ts +121 -27
- package/cli/commands/cpu-profile.ts +23 -10
- package/cli/commands/daemon.ts +1 -9
- package/cli/commands/detox.ts +26 -18
- package/cli/commands/device.ts +129 -1
- package/cli/commands/film.ts +25 -16
- package/cli/commands/flow.ts +9 -2
- package/cli/commands/inspect/actions.ts +75 -1
- package/cli/commands/inspect/core.ts +81 -2
- package/cli/commands/inspect/describe.ts +2 -6
- package/cli/commands/inspect/env.ts +1 -1
- package/cli/commands/inspect/settling.ts +20 -3
- package/cli/commands/inspect/shared.ts +1 -4
- package/cli/commands/inspect/sleep.ts +1 -1
- package/cli/commands/inspect.ts +16 -49
- package/cli/commands/install-desktop.ts +8 -6
- package/cli/commands/login.ts +3 -5
- package/cli/commands/maestro-generate.ts +1 -4
- package/cli/commands/maestro.ts +38 -21
- package/cli/commands/no-bridge-hint.ts +0 -14
- package/cli/commands/permissions.ts +2 -2
- package/cli/commands/platform.ts +13 -6
- package/cli/commands/screenshot.ts +6 -1
- package/cli/commands/skills.ts +1 -1
- package/cli/commands/test.ts +6 -2
- package/cli/commands/three-mode.ts +162 -19
- package/cli/commands/upload.ts +3 -18
- package/cli/current-sim.ts +0 -1
- package/cli/desktop-companion.ts +40 -8
- package/cli/drivers/playwright-provisioning.ts +1 -4
- package/cli/flow-export.ts +1 -8
- package/cli/flow-session.ts +0 -4
- package/cli/hints.ts +1 -16
- package/cli/inspect-notice-state.ts +0 -4
- package/cli/main.ts +2 -4
- package/cli/outbound-endpoints.ts +1 -24
- package/cli/parse-args.ts +1 -2
- package/cli/rnx-in-process.ts +3 -1
- package/cli/run-rnx-core.ts +4 -2
- package/cli/run-rnx.ts +18 -10
- package/cli/send-to-box.ts +1 -4
- package/cli/telemetry.ts +1 -1
- package/cli/ws-bridge.ts +1 -5
- package/detox/gestures.ts +20 -6
- package/detox/index.ts +379 -123
- package/detox/navigation-lifecycle.ts +22 -13
- package/dist-lib/agent-daemon-client.cjs +21 -15
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +3 -17
- package/dist-lib/agent-sessions.cjs +5 -4
- package/dist-lib/attached-projects.cjs +1 -77
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +11 -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 +7 -5
- package/dist-lib/bridge-contract-input.mjs +7 -5
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +30 -7
- package/dist-lib/capture-contract.mjs +30 -7
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +17 -11
- package/dist-lib/cloud.mjs +17 -11
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +321 -122
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +427 -212
- package/dist-lib/host/fetch-proxy-handler.cjs +5 -28
- 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 +315 -58
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +67 -31
- package/dist-lib/menu.mjs +64 -28
- package/dist-lib/metro-fingerprint-registry.cjs +8 -4
- package/dist-lib/metro-fingerprint-registry.mjs +6 -4
- package/dist-lib/metro-production-bundle.cjs +2 -2
- package/dist-lib/metro-production-bundle.mjs +2 -2
- package/dist-lib/metro.cjs +8 -4
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +7 -4
- 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 +3 -13
- package/dist-lib/scripts/dev-server-scanner.cjs +5 -17
- package/dist-lib/sdk.cjs +129 -10
- package/dist-lib/sdk.mjs +127 -10
- package/dist-lib/skills.cjs +1635 -1121
- package/dist-lib/swift-compile.cjs +277 -70
- package/dist-lib/swift-compile.mjs +275 -70
- package/dist-lib/swift-package.cjs +17 -5
- package/dist-lib/swift-package.mjs +15 -4
- package/dist-lib/swift-submit.cjs +32 -8
- package/dist-lib/swift-submit.mjs +29 -7
- package/dist-lib/swift.cjs +30912 -577
- package/dist-lib/vite-kotlin.cjs +356 -0
- package/dist-lib/vite-swift.cjs +1743 -0
- package/dist-lib/vite.cjs +208 -1039
- package/kotlin/README.md +18 -0
- package/kotlin/Sources/androidx/annotation/Keep.kt +4 -0
- package/kotlin/Sources/dev/onejs/one/OneNativeSourceDispatch.kt +7 -0
- package/kotlin/Sources/dev/onejs/one/source/OneModule.kt +4 -0
- package/kotlin/Sources/org/json/JSON.kt +244 -0
- package/kotlin/toolchain.json +19 -0
- package/package.json +14 -2
- package/scripts/dev-server-scanner.ts +0 -18
- package/scripts/optional-demo-registry.ts +0 -17
- package/skills/contrast/SKILL.md +2 -2
- package/skills/peach-setup/SKILL.md +16 -0
- package/src/agent-daemon-client.ts +36 -22
- package/src/agent-identity.ts +0 -15
- package/src/agent-prompt.ts +12 -0
- package/src/attached-projects.ts +0 -72
- package/src/backend-origin.ts +10 -0
- package/src/bridge-contract-input.ts +2 -5
- package/src/bridge-contract.ts +2 -0
- package/src/capture-contract.ts +53 -11
- package/src/cloud.ts +4 -9
- package/src/dev-server-open.ts +0 -99
- package/src/home-paths.ts +2 -3
- package/src/host/agent-host.ts +82 -36
- package/src/host/bridge-host.ts +5 -11
- package/src/host/fetch-proxy-handler.ts +19 -43
- package/src/is-record.ts +4 -0
- package/src/menu.ts +82 -37
- package/src/metro-fingerprint-registry.ts +1 -4
- package/src/metro-production-bundle.ts +1 -1
- package/src/plist.ts +1 -4
- package/src/public-brand.ts +5 -3
- package/src/render-mode.ts +0 -12
- package/src/runtime-assets.ts +9 -2
- package/src/screenshots/compose.ts +7 -1
- package/src/screenshots/frame-compose.ts +21 -10
- package/src/screenshots/schema.ts +1 -4
- package/src/sim-client.ts +2 -4
- package/src/skills/builtin/maestro-test.ts +1 -4
- package/src/sleep.ts +4 -0
- package/src/swift-compile.ts +209 -47
- package/src/swift-icu.ts +140 -0
- package/src/swift-package.ts +26 -2
- package/src/swift-submit.ts +84 -4
- package/src/swift.ts +2 -0
- package/src/vite-plugin-kotlin.ts +376 -0
- package/src/vite-plugin-one.ts +224 -36
- package/src/vite-plugin-swift.ts +382 -96
- package/src/vite-plugin.ts +121 -134
- package/src/vite.d.ts +10 -0
- package/cli/resolve-assets.ts +0 -63
- package/src/rolldown-plugin-swift.ts +0 -244
- package/src/team-machine-prompt.ts +0 -73
package/dist-lib/sdk.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.579 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -77,6 +77,7 @@ __export(sdk_exports, {
|
|
|
77
77
|
isShellCommandUnavailable: () => isShellCommandUnavailable,
|
|
78
78
|
isSimSemanticTree: () => isSimSemanticTree,
|
|
79
79
|
isTapSuccess: () => isTapSuccess,
|
|
80
|
+
layoutBoundFontFamily: () => layoutBoundFontFamily,
|
|
80
81
|
layoutGetNativeEval: () => layoutGetNativeEval,
|
|
81
82
|
rankInteractive: () => rankInteractive,
|
|
82
83
|
readyProbeHasContent: () => readyProbeHasContent,
|
|
@@ -89,6 +90,7 @@ __export(sdk_exports, {
|
|
|
89
90
|
shouldSkipAutoSettleForInspectPick: () => shouldSkipAutoSettleForInspectPick,
|
|
90
91
|
tapBest: () => tapBest,
|
|
91
92
|
tapById: () => tapById,
|
|
93
|
+
tapByQuery: () => tapByQuery,
|
|
92
94
|
tapByText: () => tapByText,
|
|
93
95
|
tapCommandForNode: () => tapCommandForNode,
|
|
94
96
|
tapCoordinates: () => tapCoordinates,
|
|
@@ -260,6 +262,24 @@ async function inspectDescribe(bridge, dumpOpts) {
|
|
|
260
262
|
nodeCount: result.total
|
|
261
263
|
};
|
|
262
264
|
}
|
|
265
|
+
function layoutBoundFontFamily(style) {
|
|
266
|
+
const raw = typeof style === "object" && style !== null ? style.fontFamily : void 0;
|
|
267
|
+
if (typeof raw !== "string") return void 0;
|
|
268
|
+
const first = raw.split(",")[0].trim().replace(/^['"]|['"]$/g, "");
|
|
269
|
+
if (!first) return void 0;
|
|
270
|
+
const systemFamilies = /* @__PURE__ */ new Set([
|
|
271
|
+
"system",
|
|
272
|
+
"-apple-system",
|
|
273
|
+
"system-ui",
|
|
274
|
+
"blinkmacsystemfont",
|
|
275
|
+
"segoe ui",
|
|
276
|
+
"roboto",
|
|
277
|
+
"sans-serif",
|
|
278
|
+
"serif",
|
|
279
|
+
"monospace"
|
|
280
|
+
]);
|
|
281
|
+
return systemFamilies.has(first.toLowerCase()) ? void 0 : first;
|
|
282
|
+
}
|
|
263
283
|
function scoreLayoutTextContrast(input) {
|
|
264
284
|
const required = input.fontSize >= 18 || input.fontSize >= 14 && (input.fontWeight ?? 400) >= 700 ? 3 : 4.5;
|
|
265
285
|
const { normal, background } = input;
|
|
@@ -412,6 +432,7 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
412
432
|
const n = w === 'bold' ? 700 : (typeof w === 'number' ? w : (typeof w === 'string' ? parseInt(w, 10) : NaN))
|
|
413
433
|
return Number.isFinite(n) && n >= 600 ? n : undefined
|
|
414
434
|
}
|
|
435
|
+
const familyOf = ${layoutBoundFontFamily.toString()}
|
|
415
436
|
const decoOf = (style) => {
|
|
416
437
|
const d = style && (style.textDecorationLine || style.textDecoration)
|
|
417
438
|
return d && d !== 'none' && d !== 'normal' ? String(d).split(' ')[0] : undefined
|
|
@@ -459,6 +480,27 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
459
480
|
const layout = n.layout || { x: 0, y: 0, width: 0, height: 0 }
|
|
460
481
|
const abs = n.absolute || n.absolutePosition || { x: layout.x, y: layout.y }
|
|
461
482
|
const text = typeof n.text === 'string' && n.text.trim() ? n.text.trim() : undefined
|
|
483
|
+
const rawHitSlop =
|
|
484
|
+
n.hitSlop != null
|
|
485
|
+
? n.hitSlop
|
|
486
|
+
: (n.props && n.props.hitSlop != null)
|
|
487
|
+
? n.props.hitSlop
|
|
488
|
+
: (n.style && n.style.hitSlop != null)
|
|
489
|
+
? n.style.hitSlop
|
|
490
|
+
: (n.authoredStyle && n.authoredStyle.hitSlop != null)
|
|
491
|
+
? n.authoredStyle.hitSlop
|
|
492
|
+
: undefined
|
|
493
|
+
const hitSlop =
|
|
494
|
+
typeof rawHitSlop === 'number'
|
|
495
|
+
? (rawHitSlop !== 0 ? rawHitSlop : undefined)
|
|
496
|
+
: rawHitSlop && typeof rawHitSlop === 'object'
|
|
497
|
+
? {
|
|
498
|
+
t: round(rawHitSlop.top ?? rawHitSlop.t),
|
|
499
|
+
r: round(rawHitSlop.right ?? rawHitSlop.r),
|
|
500
|
+
b: round(rawHitSlop.bottom ?? rawHitSlop.b),
|
|
501
|
+
l: round(rawHitSlop.left ?? rawHitSlop.l),
|
|
502
|
+
}
|
|
503
|
+
: undefined
|
|
462
504
|
const base = {
|
|
463
505
|
...(typeof n.nodeId === 'number'
|
|
464
506
|
? {
|
|
@@ -473,6 +515,7 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
473
515
|
type: typeof n.type === 'string' ? n.type : 'node',
|
|
474
516
|
text,
|
|
475
517
|
box: { x: round(abs.x), y: round(abs.y), w: round(layout.width), h: round(layout.height) },
|
|
518
|
+
...(hitSlop !== undefined ? { hitSlop } : {}),
|
|
476
519
|
}
|
|
477
520
|
if (!includeStyle) return base
|
|
478
521
|
// computedStyle has the resolved values; style is the curated subset \u2014
|
|
@@ -489,6 +532,7 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
489
532
|
bg: colorStr(style.backgroundColor),
|
|
490
533
|
opacity: opacityOf(style),
|
|
491
534
|
fontWeight: weightOf(style),
|
|
535
|
+
fontFamily: text ? familyOf(style) : undefined,
|
|
492
536
|
textDecoration: decoOf(style),
|
|
493
537
|
overflow: overflowOf(style),
|
|
494
538
|
borderWidth,
|
|
@@ -588,11 +632,24 @@ function formatLayoutElements(elements, opts) {
|
|
|
588
632
|
const uniform = p.t === p.r && p.r === p.b && p.b === p.l;
|
|
589
633
|
parts.push(uniform ? `pad:${p.t}` : `pad:${p.t},${p.r},${p.b},${p.l}`);
|
|
590
634
|
}
|
|
635
|
+
if (el.hitSlop !== void 0) {
|
|
636
|
+
if (typeof el.hitSlop === "number") {
|
|
637
|
+
parts.push(`hitSlop:${el.hitSlop}`);
|
|
638
|
+
} else {
|
|
639
|
+
const hs = el.hitSlop;
|
|
640
|
+
const uniform = hs.t === hs.r && hs.r === hs.b && hs.b === hs.l;
|
|
641
|
+
parts.push(
|
|
642
|
+
uniform ? `hitSlop:${hs.t}` : `hitSlop:${hs.t},${hs.r},${hs.b},${hs.l}`
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
591
646
|
if (el.fontSize !== void 0 && el.fontSize > 0) {
|
|
592
647
|
parts.push(`font:${el.fontSize}`);
|
|
593
648
|
}
|
|
594
649
|
if (opts?.styling) {
|
|
595
650
|
if (el.fontWeight) parts.push(`weight:${el.fontWeight}`);
|
|
651
|
+
if (el.fontFamily) parts.push(`family:"${el.fontFamily}"`);
|
|
652
|
+
if (el.fontLoaded === false) parts.push(`fontLoaded:false`);
|
|
596
653
|
if (el.color) parts.push(`color:${el.color}`);
|
|
597
654
|
if (el.bg) parts.push(`bg:${el.bg}`);
|
|
598
655
|
if (el.contrast) {
|
|
@@ -624,6 +681,7 @@ async function inspectAccessibilityTree(bridge) {
|
|
|
624
681
|
});
|
|
625
682
|
if (!isSemanticQueryResult(result)) return [];
|
|
626
683
|
return result.nodes.flatMap((node) => {
|
|
684
|
+
if (node.accessibilityHidden) return [];
|
|
627
685
|
if (!node.role && !node.label && !node.text && !node.pressable) return [];
|
|
628
686
|
return [
|
|
629
687
|
{
|
|
@@ -715,7 +773,8 @@ function scoreInteractive(n) {
|
|
|
715
773
|
function tapCommandForNode(n) {
|
|
716
774
|
if (n.testID) return `peach do tap-id ${shellEscape(n.testID)}`;
|
|
717
775
|
const text = typeof n.text === "string" ? n.text.trim() : "";
|
|
718
|
-
if (text.length > 0 && text.length <= 80)
|
|
776
|
+
if (text.length > 0 && text.length <= 80)
|
|
777
|
+
return `peach do tap-text ${shellEscape(text)}`;
|
|
719
778
|
const x = Math.round(((n.absolutePosition?.x ?? 0) + (n.layout?.width ?? 0) / 2) * 10) / 10;
|
|
720
779
|
const y = Math.round(((n.absolutePosition?.y ?? 0) + (n.layout?.height ?? 0) / 2) * 10) / 10;
|
|
721
780
|
return `peach do tap ${x} ${y}`;
|
|
@@ -1370,7 +1429,8 @@ async function waitForSootsimIdle({
|
|
|
1370
1429
|
maxMs,
|
|
1371
1430
|
pollMs = 50,
|
|
1372
1431
|
stablePolls = 3,
|
|
1373
|
-
strict = false
|
|
1432
|
+
strict = false,
|
|
1433
|
+
paintStill = false
|
|
1374
1434
|
}) {
|
|
1375
1435
|
const result = await bridge.send(
|
|
1376
1436
|
{
|
|
@@ -1382,6 +1442,7 @@ async function waitForSootsimIdle({
|
|
|
1382
1442
|
const pollMs = ${Math.max(1, Math.round(pollMs))}
|
|
1383
1443
|
const requiredStablePolls = ${Math.max(1, Math.round(stablePolls))}
|
|
1384
1444
|
const strict = ${strict ? "true" : "false"}
|
|
1445
|
+
const paintStill = ${paintStill ? "true" : "false"}
|
|
1385
1446
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
1386
1447
|
|
|
1387
1448
|
// route-aware settle: a tap that pushes/pops a screen is async \u2014 the
|
|
@@ -1413,10 +1474,12 @@ async function waitForSootsimIdle({
|
|
|
1413
1474
|
let requestTotal = 0
|
|
1414
1475
|
let requestInFlight = 0
|
|
1415
1476
|
let renderStatsAvailable = false
|
|
1477
|
+
let frameCount = -1
|
|
1416
1478
|
try {
|
|
1417
1479
|
const stats = await window.__sootsimRenderHost?.queryStats?.()
|
|
1418
1480
|
if (stats) {
|
|
1419
1481
|
renderStatsAvailable = true
|
|
1482
|
+
frameCount = typeof stats.frameCount === 'number' ? stats.frameCount : -1
|
|
1420
1483
|
animating =
|
|
1421
1484
|
stats.hasActiveAnims === true ||
|
|
1422
1485
|
stats.hasActiveNativeAnimations === true ||
|
|
@@ -1449,7 +1512,7 @@ async function waitForSootsimIdle({
|
|
|
1449
1512
|
}
|
|
1450
1513
|
walk(root)
|
|
1451
1514
|
}
|
|
1452
|
-
return { layout: nodes.join(';'), animating, layoutDirty, pendingFetches, renderStatsAvailable, requestTotal, requestInFlight }
|
|
1515
|
+
return { layout: nodes.join(';'), frameCount, animating, layoutDirty, pendingFetches, renderStatsAvailable, requestTotal, requestInFlight }
|
|
1453
1516
|
}
|
|
1454
1517
|
|
|
1455
1518
|
// how long generic background network is allowed to keep us waiting AFTER
|
|
@@ -1464,6 +1527,8 @@ async function waitForSootsimIdle({
|
|
|
1464
1527
|
// only within this grace once the screen is visually still.
|
|
1465
1528
|
const networkQuietGraceMs = 1200
|
|
1466
1529
|
let lastLayout = ''
|
|
1530
|
+
let lastFrameCount = -2
|
|
1531
|
+
let paintedPolls = 0
|
|
1467
1532
|
let lastRequestTotal = -1
|
|
1468
1533
|
let stable = 0
|
|
1469
1534
|
let visuallyStillSince = 0
|
|
@@ -1480,13 +1545,18 @@ async function waitForSootsimIdle({
|
|
|
1480
1545
|
if (snapshot.layoutDirty) dirtyPolls++
|
|
1481
1546
|
if (snapshot.animating) animatingPolls++
|
|
1482
1547
|
if (polls > 1 && snapshot.layout !== lastLayout) layoutChangedPolls++
|
|
1548
|
+
const painted = paintStill && snapshot.frameCount !== lastFrameCount
|
|
1549
|
+
if (polls > 1 && painted) paintedPolls++
|
|
1483
1550
|
const strictOk =
|
|
1484
1551
|
!strict ||
|
|
1485
1552
|
(snapshot.renderStatsAvailable && !snapshot.animating && !snapshot.layoutDirty)
|
|
1486
1553
|
// visually settled: no animations, no image content loading, layout
|
|
1487
1554
|
// unchanged since the last poll.
|
|
1488
1555
|
const visuallyStill =
|
|
1489
|
-
strictOk &&
|
|
1556
|
+
strictOk &&
|
|
1557
|
+
!painted &&
|
|
1558
|
+
snapshot.pendingFetches === 0 &&
|
|
1559
|
+
snapshot.layout === lastLayout
|
|
1490
1560
|
// generic network quiet: nothing in flight and no new requests issued.
|
|
1491
1561
|
const networkQuiet =
|
|
1492
1562
|
snapshot.requestInFlight === 0 && snapshot.requestTotal === lastRequestTotal
|
|
@@ -1507,6 +1577,7 @@ async function waitForSootsimIdle({
|
|
|
1507
1577
|
visuallyStillSince = 0
|
|
1508
1578
|
}
|
|
1509
1579
|
lastLayout = snapshot.layout
|
|
1580
|
+
lastFrameCount = snapshot.frameCount
|
|
1510
1581
|
lastRequestTotal = snapshot.requestTotal
|
|
1511
1582
|
await sleep(pollMs)
|
|
1512
1583
|
}
|
|
@@ -1517,6 +1588,7 @@ async function waitForSootsimIdle({
|
|
|
1517
1588
|
if (last.layoutDirty) blockers.push('layout still dirty')
|
|
1518
1589
|
if (last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
1519
1590
|
if (last.layout !== lastLayout) blockers.push('layout still changing')
|
|
1591
|
+
if (paintStill && last.frameCount !== lastFrameCount) blockers.push('still painting')
|
|
1520
1592
|
if (last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
|
|
1521
1593
|
return {
|
|
1522
1594
|
settled: false,
|
|
@@ -1524,7 +1596,7 @@ async function waitForSootsimIdle({
|
|
|
1524
1596
|
blockedBy:
|
|
1525
1597
|
(blockers.length ? blockers.join(', ') : 'unknown') +
|
|
1526
1598
|
' over ' + polls + ' polls (layout changed ' + layoutChangedPolls +
|
|
1527
|
-
'x, layoutDirty ' + dirtyPolls + 'x, animating ' + animatingPolls + 'x)',
|
|
1599
|
+
'x, layoutDirty ' + dirtyPolls + 'x, animating ' + animatingPolls + 'x, painted ' + paintedPolls + 'x)',
|
|
1528
1600
|
}
|
|
1529
1601
|
})()`
|
|
1530
1602
|
},
|
|
@@ -1840,6 +1912,48 @@ async function tapByText(bridge, query, options = {}, opts = {}) {
|
|
|
1840
1912
|
}
|
|
1841
1913
|
});
|
|
1842
1914
|
}
|
|
1915
|
+
var TAP_QUERY_FINDERS = {
|
|
1916
|
+
label: "findByLabel",
|
|
1917
|
+
role: "findByRole",
|
|
1918
|
+
hint: "findByHint",
|
|
1919
|
+
state: "findByA11yState"
|
|
1920
|
+
};
|
|
1921
|
+
function isTapNode(value) {
|
|
1922
|
+
return value !== null && typeof value === "object" && typeof Reflect.get(value, "nodeId") === "number";
|
|
1923
|
+
}
|
|
1924
|
+
function isTapTargetInfo(value) {
|
|
1925
|
+
return value !== null && typeof value === "object" && typeof Reflect.get(value, "cx") === "number" && typeof Reflect.get(value, "cy") === "number" && isTapNode(Reflect.get(value, "target"));
|
|
1926
|
+
}
|
|
1927
|
+
async function tapByQuery(bridge, query, opts = {}) {
|
|
1928
|
+
const call = (method, arg) => bridge.send({ type: "call", path: `SootSim.bridges.test.${method}`, args: [arg] });
|
|
1929
|
+
return tapResolvedTarget(bridge, {
|
|
1930
|
+
agent: opts.agent,
|
|
1931
|
+
timing: opts.timing,
|
|
1932
|
+
textFallback: typeof query.value === "string" ? query.value : void 0,
|
|
1933
|
+
resolve: async () => {
|
|
1934
|
+
const node = await call(TAP_QUERY_FINDERS[query.by], query.value);
|
|
1935
|
+
if (!isTapNode(node)) return { cx: null };
|
|
1936
|
+
const tap = await call("resolveTapTarget", node.nodeId);
|
|
1937
|
+
if (!isTapTargetInfo(tap)) return { cx: null };
|
|
1938
|
+
return payloadFromResolved(
|
|
1939
|
+
{
|
|
1940
|
+
x: tap.cx,
|
|
1941
|
+
y: tap.cy,
|
|
1942
|
+
nodeId: tap.target.nodeId,
|
|
1943
|
+
testID: tap.target.testID,
|
|
1944
|
+
text: tap.target.text ?? tap.target.accessibilityLabel,
|
|
1945
|
+
type: tap.target.type
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
nodeId: node.nodeId,
|
|
1949
|
+
testID: node.testID,
|
|
1950
|
+
text: node.text ?? node.accessibilityLabel,
|
|
1951
|
+
type: node.type
|
|
1952
|
+
}
|
|
1953
|
+
);
|
|
1954
|
+
}
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1843
1957
|
async function tapBest(bridge, query, opts = {}) {
|
|
1844
1958
|
return tapResolvedTarget(bridge, {
|
|
1845
1959
|
agent: opts.agent,
|
|
@@ -1904,6 +2018,11 @@ async function openAppUrl(bridge, target) {
|
|
|
1904
2018
|
return normalized;
|
|
1905
2019
|
}
|
|
1906
2020
|
|
|
2021
|
+
// src/sleep.ts
|
|
2022
|
+
function sleep(ms) {
|
|
2023
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2024
|
+
}
|
|
2025
|
+
|
|
1907
2026
|
// src/sim-client.ts
|
|
1908
2027
|
var SimClientError = class extends Error {
|
|
1909
2028
|
constructor(message) {
|
|
@@ -1946,9 +2065,6 @@ var SimResetError = class extends SimClientError {
|
|
|
1946
2065
|
this.result = result;
|
|
1947
2066
|
}
|
|
1948
2067
|
};
|
|
1949
|
-
function sleep(ms) {
|
|
1950
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1951
|
-
}
|
|
1952
2068
|
function decodePngDataUrl(dataUrl) {
|
|
1953
2069
|
if (typeof dataUrl !== "string" || !dataUrl.startsWith("data:image/png;base64,")) {
|
|
1954
2070
|
throw new SimClientError(
|
|
@@ -1971,7 +2087,8 @@ var TARGET_SEARCH_PARAMS = [
|
|
|
1971
2087
|
"port",
|
|
1972
2088
|
"inspectOpen",
|
|
1973
2089
|
"appFonts",
|
|
1974
|
-
"appSplash"
|
|
2090
|
+
"appSplash",
|
|
2091
|
+
"appCatalog"
|
|
1975
2092
|
];
|
|
1976
2093
|
function buildSimOpenUrl(currentUrl, target) {
|
|
1977
2094
|
const url = new URL(currentUrl);
|
|
@@ -2412,6 +2529,7 @@ var SimClient = class {
|
|
|
2412
2529
|
isShellCommandUnavailable,
|
|
2413
2530
|
isSimSemanticTree,
|
|
2414
2531
|
isTapSuccess,
|
|
2532
|
+
layoutBoundFontFamily,
|
|
2415
2533
|
layoutGetNativeEval,
|
|
2416
2534
|
rankInteractive,
|
|
2417
2535
|
readyProbeHasContent,
|
|
@@ -2424,6 +2542,7 @@ var SimClient = class {
|
|
|
2424
2542
|
shouldSkipAutoSettleForInspectPick,
|
|
2425
2543
|
tapBest,
|
|
2426
2544
|
tapById,
|
|
2545
|
+
tapByQuery,
|
|
2427
2546
|
tapByText,
|
|
2428
2547
|
tapCommandForNode,
|
|
2429
2548
|
tapCoordinates,
|
package/dist-lib/sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.579 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -164,6 +164,24 @@ async function inspectDescribe(bridge, dumpOpts) {
|
|
|
164
164
|
nodeCount: result.total
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
|
+
function layoutBoundFontFamily(style) {
|
|
168
|
+
const raw = typeof style === "object" && style !== null ? style.fontFamily : void 0;
|
|
169
|
+
if (typeof raw !== "string") return void 0;
|
|
170
|
+
const first = raw.split(",")[0].trim().replace(/^['"]|['"]$/g, "");
|
|
171
|
+
if (!first) return void 0;
|
|
172
|
+
const systemFamilies = /* @__PURE__ */ new Set([
|
|
173
|
+
"system",
|
|
174
|
+
"-apple-system",
|
|
175
|
+
"system-ui",
|
|
176
|
+
"blinkmacsystemfont",
|
|
177
|
+
"segoe ui",
|
|
178
|
+
"roboto",
|
|
179
|
+
"sans-serif",
|
|
180
|
+
"serif",
|
|
181
|
+
"monospace"
|
|
182
|
+
]);
|
|
183
|
+
return systemFamilies.has(first.toLowerCase()) ? void 0 : first;
|
|
184
|
+
}
|
|
167
185
|
function scoreLayoutTextContrast(input) {
|
|
168
186
|
const required = input.fontSize >= 18 || input.fontSize >= 14 && (input.fontWeight ?? 400) >= 700 ? 3 : 4.5;
|
|
169
187
|
const { normal, background } = input;
|
|
@@ -316,6 +334,7 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
316
334
|
const n = w === 'bold' ? 700 : (typeof w === 'number' ? w : (typeof w === 'string' ? parseInt(w, 10) : NaN))
|
|
317
335
|
return Number.isFinite(n) && n >= 600 ? n : undefined
|
|
318
336
|
}
|
|
337
|
+
const familyOf = ${layoutBoundFontFamily.toString()}
|
|
319
338
|
const decoOf = (style) => {
|
|
320
339
|
const d = style && (style.textDecorationLine || style.textDecoration)
|
|
321
340
|
return d && d !== 'none' && d !== 'normal' ? String(d).split(' ')[0] : undefined
|
|
@@ -363,6 +382,27 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
363
382
|
const layout = n.layout || { x: 0, y: 0, width: 0, height: 0 }
|
|
364
383
|
const abs = n.absolute || n.absolutePosition || { x: layout.x, y: layout.y }
|
|
365
384
|
const text = typeof n.text === 'string' && n.text.trim() ? n.text.trim() : undefined
|
|
385
|
+
const rawHitSlop =
|
|
386
|
+
n.hitSlop != null
|
|
387
|
+
? n.hitSlop
|
|
388
|
+
: (n.props && n.props.hitSlop != null)
|
|
389
|
+
? n.props.hitSlop
|
|
390
|
+
: (n.style && n.style.hitSlop != null)
|
|
391
|
+
? n.style.hitSlop
|
|
392
|
+
: (n.authoredStyle && n.authoredStyle.hitSlop != null)
|
|
393
|
+
? n.authoredStyle.hitSlop
|
|
394
|
+
: undefined
|
|
395
|
+
const hitSlop =
|
|
396
|
+
typeof rawHitSlop === 'number'
|
|
397
|
+
? (rawHitSlop !== 0 ? rawHitSlop : undefined)
|
|
398
|
+
: rawHitSlop && typeof rawHitSlop === 'object'
|
|
399
|
+
? {
|
|
400
|
+
t: round(rawHitSlop.top ?? rawHitSlop.t),
|
|
401
|
+
r: round(rawHitSlop.right ?? rawHitSlop.r),
|
|
402
|
+
b: round(rawHitSlop.bottom ?? rawHitSlop.b),
|
|
403
|
+
l: round(rawHitSlop.left ?? rawHitSlop.l),
|
|
404
|
+
}
|
|
405
|
+
: undefined
|
|
366
406
|
const base = {
|
|
367
407
|
...(typeof n.nodeId === 'number'
|
|
368
408
|
? {
|
|
@@ -377,6 +417,7 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
377
417
|
type: typeof n.type === 'string' ? n.type : 'node',
|
|
378
418
|
text,
|
|
379
419
|
box: { x: round(abs.x), y: round(abs.y), w: round(layout.width), h: round(layout.height) },
|
|
420
|
+
...(hitSlop !== undefined ? { hitSlop } : {}),
|
|
380
421
|
}
|
|
381
422
|
if (!includeStyle) return base
|
|
382
423
|
// computedStyle has the resolved values; style is the curated subset \u2014
|
|
@@ -393,6 +434,7 @@ function layoutGetNativeEval(opts = {}) {
|
|
|
393
434
|
bg: colorStr(style.backgroundColor),
|
|
394
435
|
opacity: opacityOf(style),
|
|
395
436
|
fontWeight: weightOf(style),
|
|
437
|
+
fontFamily: text ? familyOf(style) : undefined,
|
|
396
438
|
textDecoration: decoOf(style),
|
|
397
439
|
overflow: overflowOf(style),
|
|
398
440
|
borderWidth,
|
|
@@ -492,11 +534,24 @@ function formatLayoutElements(elements, opts) {
|
|
|
492
534
|
const uniform = p.t === p.r && p.r === p.b && p.b === p.l;
|
|
493
535
|
parts.push(uniform ? `pad:${p.t}` : `pad:${p.t},${p.r},${p.b},${p.l}`);
|
|
494
536
|
}
|
|
537
|
+
if (el.hitSlop !== void 0) {
|
|
538
|
+
if (typeof el.hitSlop === "number") {
|
|
539
|
+
parts.push(`hitSlop:${el.hitSlop}`);
|
|
540
|
+
} else {
|
|
541
|
+
const hs = el.hitSlop;
|
|
542
|
+
const uniform = hs.t === hs.r && hs.r === hs.b && hs.b === hs.l;
|
|
543
|
+
parts.push(
|
|
544
|
+
uniform ? `hitSlop:${hs.t}` : `hitSlop:${hs.t},${hs.r},${hs.b},${hs.l}`
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
495
548
|
if (el.fontSize !== void 0 && el.fontSize > 0) {
|
|
496
549
|
parts.push(`font:${el.fontSize}`);
|
|
497
550
|
}
|
|
498
551
|
if (opts?.styling) {
|
|
499
552
|
if (el.fontWeight) parts.push(`weight:${el.fontWeight}`);
|
|
553
|
+
if (el.fontFamily) parts.push(`family:"${el.fontFamily}"`);
|
|
554
|
+
if (el.fontLoaded === false) parts.push(`fontLoaded:false`);
|
|
500
555
|
if (el.color) parts.push(`color:${el.color}`);
|
|
501
556
|
if (el.bg) parts.push(`bg:${el.bg}`);
|
|
502
557
|
if (el.contrast) {
|
|
@@ -528,6 +583,7 @@ async function inspectAccessibilityTree(bridge) {
|
|
|
528
583
|
});
|
|
529
584
|
if (!isSemanticQueryResult(result)) return [];
|
|
530
585
|
return result.nodes.flatMap((node) => {
|
|
586
|
+
if (node.accessibilityHidden) return [];
|
|
531
587
|
if (!node.role && !node.label && !node.text && !node.pressable) return [];
|
|
532
588
|
return [
|
|
533
589
|
{
|
|
@@ -619,7 +675,8 @@ function scoreInteractive(n) {
|
|
|
619
675
|
function tapCommandForNode(n) {
|
|
620
676
|
if (n.testID) return `peach do tap-id ${shellEscape(n.testID)}`;
|
|
621
677
|
const text = typeof n.text === "string" ? n.text.trim() : "";
|
|
622
|
-
if (text.length > 0 && text.length <= 80)
|
|
678
|
+
if (text.length > 0 && text.length <= 80)
|
|
679
|
+
return `peach do tap-text ${shellEscape(text)}`;
|
|
623
680
|
const x = Math.round(((n.absolutePosition?.x ?? 0) + (n.layout?.width ?? 0) / 2) * 10) / 10;
|
|
624
681
|
const y = Math.round(((n.absolutePosition?.y ?? 0) + (n.layout?.height ?? 0) / 2) * 10) / 10;
|
|
625
682
|
return `peach do tap ${x} ${y}`;
|
|
@@ -1274,7 +1331,8 @@ async function waitForSootsimIdle({
|
|
|
1274
1331
|
maxMs,
|
|
1275
1332
|
pollMs = 50,
|
|
1276
1333
|
stablePolls = 3,
|
|
1277
|
-
strict = false
|
|
1334
|
+
strict = false,
|
|
1335
|
+
paintStill = false
|
|
1278
1336
|
}) {
|
|
1279
1337
|
const result = await bridge.send(
|
|
1280
1338
|
{
|
|
@@ -1286,6 +1344,7 @@ async function waitForSootsimIdle({
|
|
|
1286
1344
|
const pollMs = ${Math.max(1, Math.round(pollMs))}
|
|
1287
1345
|
const requiredStablePolls = ${Math.max(1, Math.round(stablePolls))}
|
|
1288
1346
|
const strict = ${strict ? "true" : "false"}
|
|
1347
|
+
const paintStill = ${paintStill ? "true" : "false"}
|
|
1289
1348
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
1290
1349
|
|
|
1291
1350
|
// route-aware settle: a tap that pushes/pops a screen is async \u2014 the
|
|
@@ -1317,10 +1376,12 @@ async function waitForSootsimIdle({
|
|
|
1317
1376
|
let requestTotal = 0
|
|
1318
1377
|
let requestInFlight = 0
|
|
1319
1378
|
let renderStatsAvailable = false
|
|
1379
|
+
let frameCount = -1
|
|
1320
1380
|
try {
|
|
1321
1381
|
const stats = await window.__sootsimRenderHost?.queryStats?.()
|
|
1322
1382
|
if (stats) {
|
|
1323
1383
|
renderStatsAvailable = true
|
|
1384
|
+
frameCount = typeof stats.frameCount === 'number' ? stats.frameCount : -1
|
|
1324
1385
|
animating =
|
|
1325
1386
|
stats.hasActiveAnims === true ||
|
|
1326
1387
|
stats.hasActiveNativeAnimations === true ||
|
|
@@ -1353,7 +1414,7 @@ async function waitForSootsimIdle({
|
|
|
1353
1414
|
}
|
|
1354
1415
|
walk(root)
|
|
1355
1416
|
}
|
|
1356
|
-
return { layout: nodes.join(';'), animating, layoutDirty, pendingFetches, renderStatsAvailable, requestTotal, requestInFlight }
|
|
1417
|
+
return { layout: nodes.join(';'), frameCount, animating, layoutDirty, pendingFetches, renderStatsAvailable, requestTotal, requestInFlight }
|
|
1357
1418
|
}
|
|
1358
1419
|
|
|
1359
1420
|
// how long generic background network is allowed to keep us waiting AFTER
|
|
@@ -1368,6 +1429,8 @@ async function waitForSootsimIdle({
|
|
|
1368
1429
|
// only within this grace once the screen is visually still.
|
|
1369
1430
|
const networkQuietGraceMs = 1200
|
|
1370
1431
|
let lastLayout = ''
|
|
1432
|
+
let lastFrameCount = -2
|
|
1433
|
+
let paintedPolls = 0
|
|
1371
1434
|
let lastRequestTotal = -1
|
|
1372
1435
|
let stable = 0
|
|
1373
1436
|
let visuallyStillSince = 0
|
|
@@ -1384,13 +1447,18 @@ async function waitForSootsimIdle({
|
|
|
1384
1447
|
if (snapshot.layoutDirty) dirtyPolls++
|
|
1385
1448
|
if (snapshot.animating) animatingPolls++
|
|
1386
1449
|
if (polls > 1 && snapshot.layout !== lastLayout) layoutChangedPolls++
|
|
1450
|
+
const painted = paintStill && snapshot.frameCount !== lastFrameCount
|
|
1451
|
+
if (polls > 1 && painted) paintedPolls++
|
|
1387
1452
|
const strictOk =
|
|
1388
1453
|
!strict ||
|
|
1389
1454
|
(snapshot.renderStatsAvailable && !snapshot.animating && !snapshot.layoutDirty)
|
|
1390
1455
|
// visually settled: no animations, no image content loading, layout
|
|
1391
1456
|
// unchanged since the last poll.
|
|
1392
1457
|
const visuallyStill =
|
|
1393
|
-
strictOk &&
|
|
1458
|
+
strictOk &&
|
|
1459
|
+
!painted &&
|
|
1460
|
+
snapshot.pendingFetches === 0 &&
|
|
1461
|
+
snapshot.layout === lastLayout
|
|
1394
1462
|
// generic network quiet: nothing in flight and no new requests issued.
|
|
1395
1463
|
const networkQuiet =
|
|
1396
1464
|
snapshot.requestInFlight === 0 && snapshot.requestTotal === lastRequestTotal
|
|
@@ -1411,6 +1479,7 @@ async function waitForSootsimIdle({
|
|
|
1411
1479
|
visuallyStillSince = 0
|
|
1412
1480
|
}
|
|
1413
1481
|
lastLayout = snapshot.layout
|
|
1482
|
+
lastFrameCount = snapshot.frameCount
|
|
1414
1483
|
lastRequestTotal = snapshot.requestTotal
|
|
1415
1484
|
await sleep(pollMs)
|
|
1416
1485
|
}
|
|
@@ -1421,6 +1490,7 @@ async function waitForSootsimIdle({
|
|
|
1421
1490
|
if (last.layoutDirty) blockers.push('layout still dirty')
|
|
1422
1491
|
if (last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
1423
1492
|
if (last.layout !== lastLayout) blockers.push('layout still changing')
|
|
1493
|
+
if (paintStill && last.frameCount !== lastFrameCount) blockers.push('still painting')
|
|
1424
1494
|
if (last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
|
|
1425
1495
|
return {
|
|
1426
1496
|
settled: false,
|
|
@@ -1428,7 +1498,7 @@ async function waitForSootsimIdle({
|
|
|
1428
1498
|
blockedBy:
|
|
1429
1499
|
(blockers.length ? blockers.join(', ') : 'unknown') +
|
|
1430
1500
|
' over ' + polls + ' polls (layout changed ' + layoutChangedPolls +
|
|
1431
|
-
'x, layoutDirty ' + dirtyPolls + 'x, animating ' + animatingPolls + 'x)',
|
|
1501
|
+
'x, layoutDirty ' + dirtyPolls + 'x, animating ' + animatingPolls + 'x, painted ' + paintedPolls + 'x)',
|
|
1432
1502
|
}
|
|
1433
1503
|
})()`
|
|
1434
1504
|
},
|
|
@@ -1744,6 +1814,48 @@ async function tapByText(bridge, query, options = {}, opts = {}) {
|
|
|
1744
1814
|
}
|
|
1745
1815
|
});
|
|
1746
1816
|
}
|
|
1817
|
+
var TAP_QUERY_FINDERS = {
|
|
1818
|
+
label: "findByLabel",
|
|
1819
|
+
role: "findByRole",
|
|
1820
|
+
hint: "findByHint",
|
|
1821
|
+
state: "findByA11yState"
|
|
1822
|
+
};
|
|
1823
|
+
function isTapNode(value) {
|
|
1824
|
+
return value !== null && typeof value === "object" && typeof Reflect.get(value, "nodeId") === "number";
|
|
1825
|
+
}
|
|
1826
|
+
function isTapTargetInfo(value) {
|
|
1827
|
+
return value !== null && typeof value === "object" && typeof Reflect.get(value, "cx") === "number" && typeof Reflect.get(value, "cy") === "number" && isTapNode(Reflect.get(value, "target"));
|
|
1828
|
+
}
|
|
1829
|
+
async function tapByQuery(bridge, query, opts = {}) {
|
|
1830
|
+
const call = (method, arg) => bridge.send({ type: "call", path: `SootSim.bridges.test.${method}`, args: [arg] });
|
|
1831
|
+
return tapResolvedTarget(bridge, {
|
|
1832
|
+
agent: opts.agent,
|
|
1833
|
+
timing: opts.timing,
|
|
1834
|
+
textFallback: typeof query.value === "string" ? query.value : void 0,
|
|
1835
|
+
resolve: async () => {
|
|
1836
|
+
const node = await call(TAP_QUERY_FINDERS[query.by], query.value);
|
|
1837
|
+
if (!isTapNode(node)) return { cx: null };
|
|
1838
|
+
const tap = await call("resolveTapTarget", node.nodeId);
|
|
1839
|
+
if (!isTapTargetInfo(tap)) return { cx: null };
|
|
1840
|
+
return payloadFromResolved(
|
|
1841
|
+
{
|
|
1842
|
+
x: tap.cx,
|
|
1843
|
+
y: tap.cy,
|
|
1844
|
+
nodeId: tap.target.nodeId,
|
|
1845
|
+
testID: tap.target.testID,
|
|
1846
|
+
text: tap.target.text ?? tap.target.accessibilityLabel,
|
|
1847
|
+
type: tap.target.type
|
|
1848
|
+
},
|
|
1849
|
+
{
|
|
1850
|
+
nodeId: node.nodeId,
|
|
1851
|
+
testID: node.testID,
|
|
1852
|
+
text: node.text ?? node.accessibilityLabel,
|
|
1853
|
+
type: node.type
|
|
1854
|
+
}
|
|
1855
|
+
);
|
|
1856
|
+
}
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1747
1859
|
async function tapBest(bridge, query, opts = {}) {
|
|
1748
1860
|
return tapResolvedTarget(bridge, {
|
|
1749
1861
|
agent: opts.agent,
|
|
@@ -1808,6 +1920,11 @@ async function openAppUrl(bridge, target) {
|
|
|
1808
1920
|
return normalized;
|
|
1809
1921
|
}
|
|
1810
1922
|
|
|
1923
|
+
// src/sleep.ts
|
|
1924
|
+
function sleep(ms) {
|
|
1925
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1811
1928
|
// src/sim-client.ts
|
|
1812
1929
|
var SimClientError = class extends Error {
|
|
1813
1930
|
constructor(message) {
|
|
@@ -1850,9 +1967,6 @@ var SimResetError = class extends SimClientError {
|
|
|
1850
1967
|
this.result = result;
|
|
1851
1968
|
}
|
|
1852
1969
|
};
|
|
1853
|
-
function sleep(ms) {
|
|
1854
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1855
|
-
}
|
|
1856
1970
|
function decodePngDataUrl(dataUrl) {
|
|
1857
1971
|
if (typeof dataUrl !== "string" || !dataUrl.startsWith("data:image/png;base64,")) {
|
|
1858
1972
|
throw new SimClientError(
|
|
@@ -1875,7 +1989,8 @@ var TARGET_SEARCH_PARAMS = [
|
|
|
1875
1989
|
"port",
|
|
1876
1990
|
"inspectOpen",
|
|
1877
1991
|
"appFonts",
|
|
1878
|
-
"appSplash"
|
|
1992
|
+
"appSplash",
|
|
1993
|
+
"appCatalog"
|
|
1879
1994
|
];
|
|
1880
1995
|
function buildSimOpenUrl(currentUrl, target) {
|
|
1881
1996
|
const url = new URL(currentUrl);
|
|
@@ -2315,6 +2430,7 @@ export {
|
|
|
2315
2430
|
isShellCommandUnavailable,
|
|
2316
2431
|
isSimSemanticTree,
|
|
2317
2432
|
isTapSuccess,
|
|
2433
|
+
layoutBoundFontFamily,
|
|
2318
2434
|
layoutGetNativeEval,
|
|
2319
2435
|
rankInteractive,
|
|
2320
2436
|
readyProbeHasContent,
|
|
@@ -2327,6 +2443,7 @@ export {
|
|
|
2327
2443
|
shouldSkipAutoSettleForInspectPick,
|
|
2328
2444
|
tapBest,
|
|
2329
2445
|
tapById,
|
|
2446
|
+
tapByQuery,
|
|
2330
2447
|
tapByText,
|
|
2331
2448
|
tapCommandForNode,
|
|
2332
2449
|
tapCoordinates,
|