rnxsim 0.1.473 → 0.1.475

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/cli/commands/inspect/core.ts +2 -2
  2. package/cli/commands/inspect/wait-selector.ts +12 -4
  3. package/detox/index.ts +22 -4
  4. package/dist-lib/agent-daemon-client.cjs +1 -1
  5. package/dist-lib/agent-events.cjs +1 -1
  6. package/dist-lib/agent-identity.cjs +1 -1
  7. package/dist-lib/agent-sessions.cjs +1 -1
  8. package/dist-lib/attached-projects.cjs +1 -1
  9. package/dist-lib/auth/shared-session.cjs +1 -1
  10. package/dist-lib/backend-origin.cjs +1 -1
  11. package/dist-lib/beta.cjs +1 -1
  12. package/dist-lib/beta.mjs +1 -1
  13. package/dist-lib/bridge-constants.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.cjs +8 -5
  15. package/dist-lib/bridge-contract-input.mjs +8 -5
  16. package/dist-lib/bridge-contract.cjs +1 -1
  17. package/dist-lib/bridge-contract.mjs +1 -1
  18. package/dist-lib/capture-contract.cjs +1 -1
  19. package/dist-lib/capture-contract.mjs +1 -1
  20. package/dist-lib/cli-constants.cjs +1 -1
  21. package/dist-lib/cloud-contract.cjs +1 -1
  22. package/dist-lib/cloud-contract.mjs +1 -1
  23. package/dist-lib/cloud.cjs +1 -1
  24. package/dist-lib/cloud.mjs +1 -1
  25. package/dist-lib/config.cjs +1 -1
  26. package/dist-lib/detox/index.cjs +32 -7
  27. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  28. package/dist-lib/home-paths.cjs +1 -1
  29. package/dist-lib/host/bridge-host.cjs +1 -1
  30. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  31. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  33. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  34. package/dist-lib/host/websocket-proxy.cjs +1 -1
  35. package/dist-lib/index.cjs +1 -1
  36. package/dist-lib/jump-to-source-babel.cjs +1 -1
  37. package/dist-lib/jump-to-source-native.cjs +1 -1
  38. package/dist-lib/menu.cjs +1 -1
  39. package/dist-lib/menu.mjs +1 -1
  40. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  41. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  42. package/dist-lib/metro-production-bundle.cjs +1 -1
  43. package/dist-lib/metro-production-bundle.mjs +1 -1
  44. package/dist-lib/metro.cjs +1 -1
  45. package/dist-lib/profiles.cjs +1 -1
  46. package/dist-lib/public-brand.cjs +1 -1
  47. package/dist-lib/react-native-host-modules.cjs +1 -1
  48. package/dist-lib/react-native-host-modules.mjs +1 -1
  49. package/dist-lib/render-mode.cjs +1 -1
  50. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  51. package/dist-lib/sdk.cjs +2 -2
  52. package/dist-lib/sdk.mjs +2 -2
  53. package/dist-lib/skills.cjs +87 -25
  54. package/dist-lib/vite.cjs +1 -1
  55. package/package.json +1 -1
  56. package/src/bridge-contract-input.ts +12 -4
  57. package/src/bridge-contract.ts +8 -1
@@ -1146,7 +1146,7 @@ export async function inspectWaitSelector(
1146
1146
  bridge: InspectBridge,
1147
1147
  testId: string,
1148
1148
  timeoutMs = 5000,
1149
- opts: { gone?: boolean } = {},
1149
+ opts: { gone?: boolean; structural?: boolean } = {},
1150
1150
  ): Promise<{ found: boolean; node?: SimSemanticNode; elapsed: number }> {
1151
1151
  const gone = opts.gone === true
1152
1152
  const result: SemanticWaitResult = await bridge.send(
@@ -1154,7 +1154,7 @@ export async function inspectWaitSelector(
1154
1154
  type: 'waitFor',
1155
1155
  waitForOptions: {
1156
1156
  condition: {
1157
- type: gone ? 'absent' : 'present',
1157
+ type: gone ? 'absent' : opts.structural === true ? 'mounted' : 'present',
1158
1158
  selector: { testID: testId },
1159
1159
  },
1160
1160
  timeoutMs,
@@ -2,9 +2,13 @@ import { rnxExit } from '../../run-rnx'
2
2
  import { inspectWaitSelector } from './core'
3
3
  import type { WsBridge } from '../../ws-bridge'
4
4
 
5
- // blocks until a node with the given testID is present and laid out, or — with
6
- // `--gone` — until it is absent. the engine owns the polling loop and this
7
- // handler sends one request, then reports.
5
+ // blocks until a node with the given testID is visible and laid out, or — with
6
+ // `--gone` — until it is absent. `--structural` drops the visibility test and
7
+ // waits only for the node to exist, which is what a marker rendered as proof
8
+ // (a build id, a launch phase) needs: it is 1x1 and painted under the app, so
9
+ // it is permanently occluded and the visible check can never match it. the
10
+ // engine owns the polling loop and this handler sends one request, then
11
+ // reports.
8
12
  export async function runWaitSelectorSubcommand(opts: {
9
13
  bridge: WsBridge
10
14
  args: string[]
@@ -14,16 +18,20 @@ export async function runWaitSelectorSubcommand(opts: {
14
18
  const { bridge, args, positional, inspectUsage } = opts
15
19
  const testId = positional[1]
16
20
  if (!testId) {
17
- console.error(inspectUsage('selector', '<testid> [--max-ms 5000] [--gone]'))
21
+ console.error(
22
+ inspectUsage('selector', '<testid> [--max-ms 5000] [--gone] [--structural]'),
23
+ )
18
24
  rnxExit(1)
19
25
  }
20
26
  const maxMsIdx = args.indexOf('--max-ms')
21
27
  const timeoutMs =
22
28
  maxMsIdx >= 0 && args[maxMsIdx + 1] ? Math.max(100, Number(args[maxMsIdx + 1])) : 5000
23
29
  const gone = args.includes('--gone')
30
+ const structural = args.includes('--structural')
24
31
 
25
32
  const { found, node, elapsed } = await inspectWaitSelector(bridge, testId, timeoutMs, {
26
33
  gone,
34
+ structural,
27
35
  })
28
36
 
29
37
  if (gone) {
package/detox/index.ts CHANGED
@@ -519,8 +519,10 @@ async function getDefaultTapPoint(
519
519
  width: nodeInfo.layout?.width ?? 0,
520
520
  height: nodeInfo.layout?.height ?? 0,
521
521
  }
522
+ const viewport = await readSootsimInteractiveViewport(page)
522
523
  const fullFrameTolerance = 0.5
523
- const fullyVisible =
524
+ // the resolved center may belong to a descendant of the matched frame.
525
+ const canTapCenter =
524
526
  typeof nodeInfo.absolutePosition?.x === 'number' &&
525
527
  typeof nodeInfo.absolutePosition?.y === 'number' &&
526
528
  typeof nodeInfo.layout?.width === 'number' &&
@@ -528,10 +530,13 @@ async function getDefaultTapPoint(
528
530
  Math.abs(frame.x - nodeInfo.absolutePosition.x) <= fullFrameTolerance &&
529
531
  Math.abs(frame.y - nodeInfo.absolutePosition.y) <= fullFrameTolerance &&
530
532
  frame.width >= nodeInfo.layout.width - fullFrameTolerance &&
531
- frame.height >= nodeInfo.layout.height - fullFrameTolerance
532
- if (fullyVisible) return center
533
+ frame.height >= nodeInfo.layout.height - fullFrameTolerance &&
534
+ center.x >= 0 &&
535
+ center.y >= 0 &&
536
+ center.x < viewport.width &&
537
+ center.y < viewport.height
538
+ if (canTapCenter) return center
533
539
 
534
- const viewport = await readSootsimInteractiveViewport(page)
535
540
  const left = Math.max(0, frame.x)
536
541
  const top = Math.max(0, frame.y)
537
542
  const right = Math.min(viewport.width, frame.x + frame.width)
@@ -1556,6 +1561,7 @@ export const device = {
1556
1561
  // between, because no lockstep frame steps while it runs.
1557
1562
  hold?: { durationMs: number; x: number; y: number } | null
1558
1563
  rootFrame?: { height: number; width: number; x: number; y: number } | null
1564
+ settleMs?: number
1559
1565
  trigger?: () => unknown
1560
1566
  },
1561
1567
  ): Promise<{
@@ -1584,6 +1590,10 @@ export const device = {
1584
1590
  }> {
1585
1591
  const page = getPage()
1586
1592
  const token = `motion-${process.pid}-${Date.now()}-${Math.random()}`
1593
+ const settleMs = options.settleMs ?? 0
1594
+ if (!Number.isFinite(settleMs) || settleMs < 0) {
1595
+ throw new Error('rnx motion capture needs a non-negative settleMs')
1596
+ }
1587
1597
  await page.evaluate(measureMotionChange, {
1588
1598
  definition: MOTION_CHANGE_DEFINITION,
1589
1599
  installGlobal: true,
@@ -1854,6 +1864,13 @@ export const device = {
1854
1864
  virtualTimestampMs: receipt.virtualTimestampMs,
1855
1865
  })
1856
1866
  }
1867
+ if (input.settleMs > 0) {
1868
+ const maximumOffsetMs = input.stages.reduce(
1869
+ (maximum, stage) => Math.max(maximum, stage.offsetMs),
1870
+ 0,
1871
+ )
1872
+ await controller.stepToOffset(visibleStart, maximumOffsetMs + input.settleMs)
1873
+ }
1857
1874
  return {
1858
1875
  frames: snapshots.map(encode),
1859
1876
  visibleChangeDetection: {
@@ -1878,6 +1895,7 @@ export const device = {
1878
1895
  hold: options.hold ?? null,
1879
1896
  motionChangeDefinition: MOTION_CHANGE_DEFINITION,
1880
1897
  rootFrame: options.rootFrame ?? null,
1898
+ settleMs,
1881
1899
  stages,
1882
1900
  token,
1883
1901
  },
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
package/dist-lib/beta.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
package/dist-lib/beta.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/beta.ts
4
4
  var IS_BETA = true;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -196,8 +196,11 @@ function parsePerformStep(value, index) {
196
196
  case "waitFor": {
197
197
  const timeoutMs = semanticWaitTimeout(step, path);
198
198
  const condition = step.condition === void 0 ? void 0 : stringValue(step.condition, `${path}.condition`);
199
- if (condition !== void 0 && condition !== "present" && condition !== "absent") {
200
- return validationFailure(`${path}.condition`, "must be present or absent");
199
+ if (condition !== void 0 && condition !== "present" && condition !== "mounted" && condition !== "absent") {
200
+ return validationFailure(
201
+ `${path}.condition`,
202
+ "must be present, mounted, or absent"
203
+ );
201
204
  }
202
205
  const selector = step.testID === void 0 ? { id: stringValue(step.id, `${path}.id`) } : { testID: stringValue(step.testID, `${path}.testID`) };
203
206
  return {
@@ -303,10 +306,10 @@ function parseSemanticWaitOptions(value) {
303
306
  ...timeoutMs === void 0 ? {} : { timeoutMs }
304
307
  };
305
308
  }
306
- if (type !== "present" && type !== "absent") {
309
+ if (type !== "present" && type !== "mounted" && type !== "absent") {
307
310
  return validationFailure(
308
311
  "waitFor.condition.type",
309
- "must be ready, present, or absent"
312
+ "must be ready, present, mounted, or absent"
310
313
  );
311
314
  }
312
315
  return {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_MAX_MS = 5e3;
@@ -161,8 +161,11 @@ function parsePerformStep(value, index) {
161
161
  case "waitFor": {
162
162
  const timeoutMs = semanticWaitTimeout(step, path);
163
163
  const condition = step.condition === void 0 ? void 0 : stringValue(step.condition, `${path}.condition`);
164
- if (condition !== void 0 && condition !== "present" && condition !== "absent") {
165
- return validationFailure(`${path}.condition`, "must be present or absent");
164
+ if (condition !== void 0 && condition !== "present" && condition !== "mounted" && condition !== "absent") {
165
+ return validationFailure(
166
+ `${path}.condition`,
167
+ "must be present, mounted, or absent"
168
+ );
166
169
  }
167
170
  const selector = step.testID === void 0 ? { id: stringValue(step.id, `${path}.id`) } : { testID: stringValue(step.testID, `${path}.testID`) };
168
171
  return {
@@ -268,10 +271,10 @@ function parseSemanticWaitOptions(value) {
268
271
  ...timeoutMs === void 0 ? {} : { timeoutMs }
269
272
  };
270
273
  }
271
- if (type !== "present" && type !== "absent") {
274
+ if (type !== "present" && type !== "mounted" && type !== "absent") {
272
275
  return validationFailure(
273
276
  "waitFor.condition.type",
274
- "must be ready, present, or absent"
277
+ "must be ready, present, mounted, or absent"
275
278
  );
276
279
  }
277
280
  return {
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/bridge-contract.ts
4
4
  var SIM_LONG_PRESS_DEFAULT_MS = 500;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/capture-contract.ts
4
4
  var RNX_SCREEN_CAPTURE_VERSION = 1;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/cloud-contract.ts
4
4
  var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -265,7 +265,8 @@ function processIdentity(pid) {
265
265
  }
266
266
  }
267
267
  function softwareChromeAllowed(runtime = currentRuntime()) {
268
- return runtime.platform === "linux" && runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux";
268
+ if (runtime.platform !== "linux") return false;
269
+ return runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux" || runtime.env.CONTRAST_CF_FACTORY_CONTAINER === "1";
269
270
  }
270
271
  function isSoftwareRendererArgument(value) {
271
272
  const arg = String(value);
@@ -708,7 +709,7 @@ function softwareChromeLaunchOptions(opts) {
708
709
  }
709
710
  const callerArgs = Array.isArray(opts.args) ? opts.args.map(String) : [];
710
711
  const unmanagedCallerArgs = callerArgs.filter((arg) => {
711
- return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
712
+ return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && arg !== "--disable-gpu-watchdog" && arg !== "--enable-skia-graphite" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
712
713
  });
713
714
  const software = {
714
715
  ...opts,
@@ -721,7 +722,19 @@ function softwareChromeLaunchOptions(opts) {
721
722
  ...unmanagedCallerArgs,
722
723
  "--use-angle=swiftshader",
723
724
  "--enable-unsafe-swiftshader",
724
- "--enable-unsafe-webgpu"
725
+ "--enable-unsafe-webgpu",
726
+ // without Skia Graphite as chromium's own compositor, SwiftShader has no
727
+ // shared-image backing for a WebGPU canvas swap chain at any size: the
728
+ // first configured canvas fails "Could not find SharedImageBackingFactory"
729
+ // and chromium destroys the device mid-capture. compute-only WebGPU
730
+ // still works, so an adapter probe cannot see this.
731
+ "--enable-skia-graphite",
732
+ // the GPU watchdog kills the GPU process when a task outlives its
733
+ // timeout, and SwiftShader precompiling Graphite pipelines on two CPU
734
+ // cores can legitimately outlive it. the cost: a genuinely wedged GPU
735
+ // process now holds its job until the job's own timeout instead of
736
+ // dying fast.
737
+ "--disable-gpu-watchdog"
725
738
  ],
726
739
  ["Vulkan"]
727
740
  )
@@ -2162,10 +2175,10 @@ async function getDefaultTapPoint(page, nodeInfo) {
2162
2175
  width: nodeInfo.layout?.width ?? 0,
2163
2176
  height: nodeInfo.layout?.height ?? 0
2164
2177
  };
2165
- const fullFrameTolerance = 0.5;
2166
- const fullyVisible = typeof nodeInfo.absolutePosition?.x === "number" && typeof nodeInfo.absolutePosition?.y === "number" && typeof nodeInfo.layout?.width === "number" && typeof nodeInfo.layout?.height === "number" && Math.abs(frame.x - nodeInfo.absolutePosition.x) <= fullFrameTolerance && Math.abs(frame.y - nodeInfo.absolutePosition.y) <= fullFrameTolerance && frame.width >= nodeInfo.layout.width - fullFrameTolerance && frame.height >= nodeInfo.layout.height - fullFrameTolerance;
2167
- if (fullyVisible) return center;
2168
2178
  const viewport = await readSootsimInteractiveViewport(page);
2179
+ const fullFrameTolerance = 0.5;
2180
+ const canTapCenter = typeof nodeInfo.absolutePosition?.x === "number" && typeof nodeInfo.absolutePosition?.y === "number" && typeof nodeInfo.layout?.width === "number" && typeof nodeInfo.layout?.height === "number" && Math.abs(frame.x - nodeInfo.absolutePosition.x) <= fullFrameTolerance && Math.abs(frame.y - nodeInfo.absolutePosition.y) <= fullFrameTolerance && frame.width >= nodeInfo.layout.width - fullFrameTolerance && frame.height >= nodeInfo.layout.height - fullFrameTolerance && center.x >= 0 && center.y >= 0 && center.x < viewport.width && center.y < viewport.height;
2181
+ if (canTapCenter) return center;
2169
2182
  const left = Math.max(0, frame.x);
2170
2183
  const top = Math.max(0, frame.y);
2171
2184
  const right = Math.min(viewport.width, frame.x + frame.width);
@@ -2899,6 +2912,10 @@ var device = {
2899
2912
  async takeScreenshotStagesFromVisibleChangeFast(namePrefix, stages, options) {
2900
2913
  const page = getPage();
2901
2914
  const token = `motion-${process.pid}-${Date.now()}-${Math.random()}`;
2915
+ const settleMs = options.settleMs ?? 0;
2916
+ if (!Number.isFinite(settleMs) || settleMs < 0) {
2917
+ throw new Error("rnx motion capture needs a non-negative settleMs");
2918
+ }
2902
2919
  await page.evaluate(import_motion_change.measureMotionChange, {
2903
2920
  definition: import_motion_change.MOTION_CHANGE_DEFINITION,
2904
2921
  installGlobal: true
@@ -3072,6 +3089,13 @@ var device = {
3072
3089
  virtualTimestampMs: receipt.virtualTimestampMs
3073
3090
  });
3074
3091
  }
3092
+ if (input.settleMs > 0) {
3093
+ const maximumOffsetMs = input.stages.reduce(
3094
+ (maximum, stage) => Math.max(maximum, stage.offsetMs),
3095
+ 0
3096
+ );
3097
+ await controller.stepToOffset(visibleStart, maximumOffsetMs + input.settleMs);
3098
+ }
3075
3099
  return {
3076
3100
  frames: snapshots.map(encode),
3077
3101
  visibleChangeDetection: {
@@ -3096,6 +3120,7 @@ var device = {
3096
3120
  hold: options.hold ?? null,
3097
3121
  motionChangeDefinition: import_motion_change.MOTION_CHANGE_DEFINITION,
3098
3122
  rootFrame: options.rootFrame ?? null,
3123
+ settleMs,
3099
3124
  stages,
3100
3125
  token
3101
3126
  }
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
package/dist-lib/menu.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
package/dist-lib/menu.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/public-brand.ts
4
4
  var name = "rnx";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-fingerprint-registry.ts
4
4
  var RNX_METRO_FINGERPRINT_SCHEMA_VERSION = 2;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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;
@@ -787,7 +787,7 @@ async function inspectWaitSelector(bridge, testId, timeoutMs = 5e3, opts = {}) {
787
787
  type: "waitFor",
788
788
  waitForOptions: {
789
789
  condition: {
790
- type: gone ? "absent" : "present",
790
+ type: gone ? "absent" : opts.structural === true ? "mounted" : "present",
791
791
  selector: { testID: testId }
792
792
  },
793
793
  timeoutMs
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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);
@@ -691,7 +691,7 @@ async function inspectWaitSelector(bridge, testId, timeoutMs = 5e3, opts = {}) {
691
691
  type: "waitFor",
692
692
  waitForOptions: {
693
693
  condition: {
694
- type: gone ? "absent" : "present",
694
+ type: gone ? "absent" : opts.structural === true ? "mounted" : "present",
695
695
  selector: { testID: testId }
696
696
  },
697
697
  timeoutMs
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
@@ -57,7 +57,8 @@ function processIdentity(pid) {
57
57
  }
58
58
  }
59
59
  function softwareChromeAllowed(runtime = currentRuntime()) {
60
- return runtime.platform === "linux" && runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux";
60
+ if (runtime.platform !== "linux") return false;
61
+ return runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux" || runtime.env.CONTRAST_CF_FACTORY_CONTAINER === "1";
61
62
  }
62
63
  function isSoftwareRendererArgument(value) {
63
64
  const arg = String(value);
@@ -482,7 +483,7 @@ function softwareChromeLaunchOptions(opts) {
482
483
  }
483
484
  const callerArgs = Array.isArray(opts.args) ? opts.args.map(String) : [];
484
485
  const unmanagedCallerArgs = callerArgs.filter((arg) => {
485
- return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
486
+ return !arg.startsWith("--use-angle=") && arg !== "--enable-gpu" && arg !== "--enable-gpu-rasterization" && arg !== "--enable-zero-copy" && arg !== "--ignore-gpu-blocklist" && arg !== "--disable-gpu-watchdog" && arg !== "--enable-skia-graphite" && !/^--enable-unsafe-webgpu(?:=.*)?$/i.test(arg) && !/^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg);
486
487
  });
487
488
  const software = {
488
489
  ...opts,
@@ -495,7 +496,19 @@ function softwareChromeLaunchOptions(opts) {
495
496
  ...unmanagedCallerArgs,
496
497
  "--use-angle=swiftshader",
497
498
  "--enable-unsafe-swiftshader",
498
- "--enable-unsafe-webgpu"
499
+ "--enable-unsafe-webgpu",
500
+ // without Skia Graphite as chromium's own compositor, SwiftShader has no
501
+ // shared-image backing for a WebGPU canvas swap chain at any size: the
502
+ // first configured canvas fails "Could not find SharedImageBackingFactory"
503
+ // and chromium destroys the device mid-capture. compute-only WebGPU
504
+ // still works, so an adapter probe cannot see this.
505
+ "--enable-skia-graphite",
506
+ // the GPU watchdog kills the GPU process when a task outlives its
507
+ // timeout, and SwiftShader precompiling Graphite pipelines on two CPU
508
+ // cores can legitimately outlive it. the cost: a genuinely wedged GPU
509
+ // process now holds its job until the job's own timeout instead of
510
+ // dying fast.
511
+ "--disable-gpu-watchdog"
499
512
  ],
500
513
  ["Vulkan"]
501
514
  )
@@ -4198,7 +4211,53 @@ var init_capability_outcomes2 = __esm({
4198
4211
  "react-native-safe-area-context": {
4199
4212
  exactTestedVersion: "5.7.0",
4200
4213
  supportedVersionRange: ">=4.0.0",
4201
- lastMeasured: null,
4214
+ lastMeasured: {
4215
+ byWeighting: {
4216
+ strict: {
4217
+ android: {
4218
+ passedWeight: 0,
4219
+ failedWeight: 0,
4220
+ unassessedWeight: 13,
4221
+ totalWeight: 13,
4222
+ assessedWeight: 0,
4223
+ compatibility: null,
4224
+ assessed: 0
4225
+ },
4226
+ ios: {
4227
+ passedWeight: 0,
4228
+ failedWeight: 0,
4229
+ unassessedWeight: 13,
4230
+ totalWeight: 13,
4231
+ assessedWeight: 0,
4232
+ compatibility: null,
4233
+ assessed: 0
4234
+ }
4235
+ },
4236
+ usage: {
4237
+ android: {
4238
+ passedWeight: 0,
4239
+ failedWeight: 0,
4240
+ unassessedWeight: 389,
4241
+ totalWeight: 389,
4242
+ assessedWeight: 0,
4243
+ compatibility: null,
4244
+ assessed: 0
4245
+ },
4246
+ ios: {
4247
+ passedWeight: 0,
4248
+ failedWeight: 0,
4249
+ unassessedWeight: 389,
4250
+ totalWeight: 389,
4251
+ assessedWeight: 0,
4252
+ compatibility: null,
4253
+ assessed: 0
4254
+ }
4255
+ }
4256
+ },
4257
+ capturedAt: "2026-09-10T08:03:06.591Z",
4258
+ receipts: ["safe-area-initial-insets-2026-09-09-p40993-r2"],
4259
+ sourceCommit: "a13aa54553c70fd1ab96e3cfaaf0d81d58bc19ea"
4260
+ },
4202
4261
  unmatchedReferenceCount: 74,
4203
4262
  byPlatform: {
4204
4263
  android: {
@@ -4393,13 +4452,13 @@ var init_capability_outcomes2 = __esm({
4393
4452
  assessed: 0
4394
4453
  },
4395
4454
  ios: {
4396
- passedWeight: 0,
4455
+ passedWeight: 27,
4397
4456
  failedWeight: 0,
4398
- unassessedWeight: 115,
4457
+ unassessedWeight: 88,
4399
4458
  totalWeight: 115,
4400
- assessedWeight: 0,
4401
- compatibility: null,
4402
- assessed: 0
4459
+ assessedWeight: 27,
4460
+ compatibility: 1,
4461
+ assessed: 0.23478260869565218
4403
4462
  }
4404
4463
  },
4405
4464
  usage: {
@@ -4413,18 +4472,21 @@ var init_capability_outcomes2 = __esm({
4413
4472
  assessed: 0
4414
4473
  },
4415
4474
  ios: {
4416
- passedWeight: 0,
4475
+ passedWeight: 691,
4417
4476
  failedWeight: 0,
4418
- unassessedWeight: 5540,
4477
+ unassessedWeight: 4849,
4419
4478
  totalWeight: 5540,
4420
- assessedWeight: 0,
4421
- compatibility: null,
4422
- assessed: 0
4479
+ assessedWeight: 691,
4480
+ compatibility: 1,
4481
+ assessed: 0.12472924187725631
4423
4482
  }
4424
4483
  }
4425
4484
  },
4426
4485
  capturedAt: "2026-09-08T05:40:18.932Z",
4427
- receipts: ["retained-essentials-react-native-svg-r22458-20260908"],
4486
+ receipts: [
4487
+ "retained-essentials-react-native-svg-r22458-20260908",
4488
+ "svg-geometry-2026-09-09-p40993-r2"
4489
+ ],
4428
4490
  sourceCommit: "ea3eb82eeea6f6925ae708b7028cb577ad37f36a"
4429
4491
  },
4430
4492
  unmatchedReferenceCount: 4459,
@@ -5935,8 +5997,8 @@ var init_registry = __esm({
5935
5997
  id: "provider-and-window-metrics",
5936
5998
  usage: 3,
5937
5999
  importance: 3,
5938
- estimate: 0.97,
5939
- rationale: "SafeAreaProvider and initialWindowMetrics expose live frame and inset values from the device-spec and keyboard sources. The compatibility facade does not export the upstream initialWindowSafeAreaInsets value, so direct imports of that public constant do not receive the native package value."
6000
+ estimate: 1,
6001
+ rationale: "SafeAreaProvider, initialWindowMetrics and the deprecated initialWindowSafeAreaInsets constant expose live frame and inset values from the device-spec and keyboard sources. The inspected provider and window-metric path has no app-facing behavior gap."
5940
6002
  },
5941
6003
  {
5942
6004
  id: "edge-aware-layout",
@@ -5962,8 +6024,8 @@ var init_registry = __esm({
5962
6024
  ],
5963
6025
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-safe-area-context"],
5964
6026
  note: "live device/system-bar/ime metrics, edges/mode padding, hooks",
5965
- working: "SafeAreaProvider with live Android system-bar and IME-resized frame metrics, SafeAreaView (edges/mode padding/margin), useSafeAreaInsets, useSafeAreaFrame, SafeAreaInsetsContext, SafeAreaFrameContext, initialWindowMetrics, SafeAreaListener onInsetsChange, withSafeAreaInsets HOC",
5966
- missing: "initialWindowSafeAreaInsets is not exported; rotation-specific provider frame deltas remain unassessed"
6027
+ working: "SafeAreaProvider with live Android system-bar and IME-resized frame metrics, SafeAreaView (edges/mode padding/margin), useSafeAreaInsets, useSafeAreaFrame, SafeAreaInsetsContext, SafeAreaFrameContext, initialWindowMetrics, initialWindowSafeAreaInsets, SafeAreaListener onInsetsChange, withSafeAreaInsets HOC",
6028
+ missing: "rotation-specific provider frame deltas remain unassessed"
5967
6029
  }
5968
6030
  ]
5969
6031
  },
@@ -6015,14 +6077,14 @@ var init_registry = __esm({
6015
6077
  id: "filters-and-imperative-geometry",
6016
6078
  usage: 1,
6017
6079
  importance: 2,
6018
- estimate: 0.25,
6019
- rationale: "getTotalLength and getPointAtLength implement path metrics for paths and basic shapes, including curves, arcs, clamping and detached refs. This receives 25% of the grouped feature. Filters, native export, bounding boxes, matrices and point-in-fill/stroke remain unsupported; invalid-path points return zero where native returns NaN."
6080
+ estimate: 0.45,
6081
+ rationale: "getTotalLength, getPointAtLength, getBBox with its fill, stroke, markers and clipped options, getCTM, getScreenCTM, isPointInFill and isPointInStroke match 66 iOS-pinned calls within 1e-4 in a paired capture, covering curves, arcs, rounded-rect clamping, native stroke outlines and miter limits, clip bounds, invalid-path NaN points and detached refs. Native filters and toDataURL export remain unsupported, estimated as 55% of the grouped feature."
6020
6082
  }
6021
6083
  ],
6022
6084
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-svg"],
6023
- note: "CanvasKit rendering for shapes, text, XML, gradients, references, masks, clipping, and images; path metrics are implemented; native SVG filters, export and other geometry queries remain unsupported",
6024
- working: "Svg, Path, Circle, Rect, Line, Ellipse, Polygon, Polyline, G, Text, TSpan, TextPath shaped glyphs along referenced paths, Defs, Pattern fills, Marker geometry on paths/lines/polylines/polygons, LinearGradient and RadialGradient with objectBoundingBox/userSpaceOnUse coordinates, focal points and gradientTransform, Stop, Mask, ClipPath, Image, Use and Symbol references, SvgXml, SvgUri, SvgAst, SvgFromXml, SvgCss, parse, fetchText, camelCase, getTotalLength and getPointAtLength for Path, Line, Rect including rounded corners, Circle, Ellipse, Polygon and Polyline, shape transforms, fill/stroke/opacity/dasharray, currentColor, viewBox scaling",
6025
- missing: "native SVG filter components and toDataURL, hit-testing, bounding-box, and matrix methods refuse calls; invalid-path points differ from native NaN; ForeignObject does not render; marker context paints remain unverified; TextPath advanced layout, per-glyph positioning and objectBoundingBox paints are unsupported; pattern non-scaling strokes use the tile matrix; no font or emoji fallback parity claim"
6085
+ note: "CanvasKit rendering for shapes, text, XML, gradients, references, masks, clipping, and images; path metrics, bounding boxes, matrices and point-in-fill/stroke queries match native; native SVG filters and export remain unsupported",
6086
+ working: "Svg, Path, Circle, Rect, Line, Ellipse, Polygon, Polyline, G, Text, TSpan, TextPath shaped glyphs along referenced paths, Defs, Pattern fills, Marker geometry on paths/lines/polylines/polygons, LinearGradient and RadialGradient with objectBoundingBox/userSpaceOnUse coordinates, focal points and gradientTransform, Stop, Mask, ClipPath, Image, Use and Symbol references, SvgXml, SvgUri, SvgAst, SvgFromXml, SvgCss, parse, fetchText, camelCase, getTotalLength and getPointAtLength for Path, Line, Rect including rounded corners, Circle, Ellipse, Polygon and Polyline, getBBox, getCTM, getScreenCTM, isPointInFill, isPointInStroke, shape transforms, fill/stroke/opacity/dasharray, currentColor, viewBox scaling",
6087
+ missing: "native SVG filter components and toDataURL refuse calls; ForeignObject does not render; marker context paints remain unverified; TextPath advanced layout, per-glyph positioning and objectBoundingBox paints are unsupported; pattern non-scaling strokes use the tile matrix; no font or emoji fallback parity claim"
6026
6088
  }
6027
6089
  ]
6028
6090
  },
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.473 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.475 | (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 __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.473",
3
+ "version": "0.1.475",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for rnx.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -206,8 +206,16 @@ export function parsePerformStep(value: unknown, index: number): SimPerformStep
206
206
  step.condition === undefined
207
207
  ? undefined
208
208
  : stringValue(step.condition, `${path}.condition`)
209
- if (condition !== undefined && condition !== 'present' && condition !== 'absent') {
210
- return validationFailure(`${path}.condition`, 'must be present or absent')
209
+ if (
210
+ condition !== undefined &&
211
+ condition !== 'present' &&
212
+ condition !== 'mounted' &&
213
+ condition !== 'absent'
214
+ ) {
215
+ return validationFailure(
216
+ `${path}.condition`,
217
+ 'must be present, mounted, or absent',
218
+ )
211
219
  }
212
220
  const selector =
213
221
  step.testID === undefined
@@ -331,10 +339,10 @@ export function parseSemanticWaitOptions(value: unknown): SemanticWaitOptions {
331
339
  ...(timeoutMs === undefined ? {} : { timeoutMs }),
332
340
  }
333
341
  }
334
- if (type !== 'present' && type !== 'absent') {
342
+ if (type !== 'present' && type !== 'mounted' && type !== 'absent') {
335
343
  return validationFailure(
336
344
  'waitFor.condition.type',
337
- 'must be ready, present, or absent',
345
+ 'must be ready, present, mounted, or absent',
338
346
  )
339
347
  }
340
348
  return {
@@ -159,7 +159,7 @@ export type PerformStep =
159
159
  type: 'waitFor'
160
160
  testID?: string
161
161
  id?: string
162
- condition?: 'present' | 'absent'
162
+ condition?: 'present' | 'mounted' | 'absent'
163
163
  timeoutMs?: number
164
164
  }
165
165
 
@@ -202,9 +202,16 @@ export interface PerformResult {
202
202
  // waitFor — engine-side semantic condition polling
203
203
  // ---------------------------------------------------------------------------
204
204
 
205
+ // `present` is what a person can see: the node must survive the occlusion pass,
206
+ // so a button behind a sheet does not count. `mounted` asks only whether the
207
+ // node exists and is laid out, which is the right question for a marker the app
208
+ // renders as proof of something (a build id, a launch phase) rather than as
209
+ // something to look at — those are 1x1 and painted under the whole app, so they
210
+ // are permanently occluded and `present` can never match one.
205
211
  export type SemanticWaitCondition =
206
212
  | { type: 'ready' }
207
213
  | { type: 'present'; selector: SimSemanticResolveSelector }
214
+ | { type: 'mounted'; selector: SimSemanticResolveSelector }
208
215
  | { type: 'absent'; selector: SimSemanticResolveSelector }
209
216
 
210
217
  export interface SemanticWaitOptions {