sootsim 0.1.227 → 0.1.229
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 -14
- package/detox/element-types.ts +3 -3
- package/detox/expectations.ts +29 -24
- package/detox/gestures.ts +16 -16
- package/detox/index.ts +34 -32
- package/dist-cli/bin.js +4 -4
- package/dist-cli/chunks/{agent-HBVXCRJT.js → agent-O26YYN6Z.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-X376DPV2.js → agent-wrapper-GSMHXP6S.js} +2 -2
- package/dist-cli/chunks/{app-fonts-LIQTD5RP.js → app-fonts-TVTDVD7S.js} +2 -2
- package/dist-cli/chunks/{assert-X6PPLN72.js → assert-KEWRJSST.js} +2 -2
- package/dist-cli/chunks/{auth-INRWIM2C.js → auth-KQXLD6AC.js} +2 -2
- package/dist-cli/chunks/beta-BXBII74U.js +2 -0
- package/dist-cli/chunks/{camera-LGFHYCJ5.js → camera-RTNVNBMT.js} +2 -2
- package/dist-cli/chunks/{chunk-YB2LM6VB.js → chunk-32O3YKA2.js} +6 -6
- package/dist-cli/chunks/{chunk-SBIAPF6E.js → chunk-3FGXJMSF.js} +1 -1
- package/dist-cli/chunks/{chunk-QWRYD2QV.js → chunk-3FYUTNM4.js} +18 -18
- package/dist-cli/chunks/{chunk-A4BOYB55.js → chunk-3UE5OA64.js} +2 -2
- package/dist-cli/chunks/{chunk-LCJSTEIR.js → chunk-456MZ4LU.js} +2 -2
- package/dist-cli/chunks/{chunk-E75EBS77.js → chunk-4O73AHYA.js} +2 -2
- package/dist-cli/chunks/chunk-4WAZOAAS.js +2 -0
- package/dist-cli/chunks/{chunk-RNWJQ4UR.js → chunk-62GPXYH7.js} +1 -1
- package/dist-cli/chunks/chunk-6Q3M6FMW.js +24 -0
- package/dist-cli/chunks/chunk-6VQIZJLG.js +1 -0
- package/dist-cli/chunks/chunk-7FSM4I7A.js +1 -0
- package/dist-cli/chunks/{chunk-J2JAOIMN.js → chunk-7IBNJPSB.js} +2 -2
- package/dist-cli/chunks/{chunk-GUCFICA4.js → chunk-7LSM7YNF.js} +1 -1
- package/dist-cli/chunks/{chunk-J7IFVTWX.js → chunk-AB7XCG3A.js} +1 -1
- package/dist-cli/chunks/{chunk-MG6JE3AM.js → chunk-AZWH6YSL.js} +2 -2
- package/dist-cli/chunks/{chunk-ESK7B2BQ.js → chunk-BZOTL2IQ.js} +6 -6
- package/dist-cli/chunks/{chunk-2XXPF6LP.js → chunk-CE3XI55C.js} +2 -2
- package/dist-cli/chunks/{chunk-HRYKZ5YY.js → chunk-DXF6DHIR.js} +5 -5
- package/dist-cli/chunks/{chunk-DB3GMVOH.js → chunk-FF7GZMWQ.js} +2 -2
- package/dist-cli/chunks/chunk-GVOFX6LJ.js +118 -0
- package/dist-cli/chunks/{chunk-HXHB5A6R.js → chunk-HKBDDBKZ.js} +2 -2
- package/dist-cli/chunks/{chunk-UGWURWHN.js → chunk-HKZICBKI.js} +2 -2
- package/dist-cli/chunks/{chunk-E3DLUOFK.js → chunk-JK4AGL2U.js} +7 -7
- package/dist-cli/chunks/{chunk-NIN75M5H.js → chunk-OUJVQUX4.js} +2 -2
- package/dist-cli/chunks/chunk-OWSZCLYZ.js +2 -0
- package/dist-cli/chunks/{chunk-XESYTWFM.js → chunk-P3ORPGKZ.js} +29 -29
- package/dist-cli/chunks/{chunk-Q4FB222M.js → chunk-PNLTVAPK.js} +3 -3
- package/dist-cli/chunks/{chunk-4J7BIXEB.js → chunk-PY65YXHI.js} +2 -2
- package/dist-cli/chunks/{chunk-7LDHOQ7B.js → chunk-S4CJUMUZ.js} +34 -34
- package/dist-cli/chunks/{chunk-T6MEERRI.js → chunk-SCGYOJJP.js} +2 -2
- package/dist-cli/chunks/{chunk-HXSV263V.js → chunk-SHBXXKJW.js} +1 -1
- package/dist-cli/chunks/chunk-SPBHQVJ4.js +2 -0
- package/dist-cli/chunks/{chunk-F53C5HAB.js → chunk-SYZKYAPC.js} +1 -1
- package/dist-cli/chunks/{chunk-3L5EXWCP.js → chunk-THDVL3ST.js} +1 -1
- package/dist-cli/chunks/{chunk-HTVB3FW2.js → chunk-TJXRSDEU.js} +2 -2
- package/dist-cli/chunks/{chunk-NU755HCE.js → chunk-TWUPMUWQ.js} +1 -1
- package/dist-cli/chunks/{chunk-F5HOYUD2.js → chunk-U4OPCVAL.js} +1 -1
- package/dist-cli/chunks/chunk-UCVK6JDW.js +3 -0
- package/dist-cli/chunks/chunk-UGFZIHBA.js +2 -0
- package/dist-cli/chunks/{chunk-LM544J6V.js → chunk-V2TABN7W.js} +1 -1
- package/dist-cli/chunks/{chunk-D42IRY2Y.js → chunk-VKVRAWJR.js} +2 -2
- package/dist-cli/chunks/{chunk-7L5IKIHC.js → chunk-VUJ5FLL7.js} +1 -1
- package/dist-cli/chunks/{chunk-2BQOZATN.js → chunk-WRPO6J3Z.js} +3 -3
- package/dist-cli/chunks/chunk-XQHCHVHE.js +4 -0
- package/dist-cli/chunks/{chunk-NHE3YHDU.js → chunk-ZORXBO54.js} +2 -2
- package/dist-cli/chunks/cli-version-W42GGXV7.js +2 -0
- package/dist-cli/chunks/{compat-MH673TEJ.js → compat-HPS6RGWD.js} +3 -3
- package/dist-cli/chunks/{config-SSCDV5ZJ.js → config-EKIT7WKS.js} +2 -2
- package/dist-cli/chunks/{control-54R2XDLV.js → control-QFNWOCLW.js} +2 -2
- package/dist-cli/chunks/daemon-B6RUIEYN.js +2 -0
- package/dist-cli/chunks/{debug-PFP646II.js → debug-EU5JDWZR.js} +3 -3
- package/dist-cli/chunks/{desktop-BPYYJ3EM.js → desktop-OOCDJB3I.js} +3 -3
- package/dist-cli/chunks/{detox-BIUVHXYH.js → detox-BXXEPJ3F.js} +2 -2
- package/dist-cli/chunks/{device-BNSPNIP6.js → device-6B6NKGAW.js} +2 -2
- package/dist-cli/chunks/{diagnose-BPTDSGOB.js → diagnose-FOWBMKO6.js} +2 -2
- package/dist-cli/chunks/drivers-DC6SRA2P.js +2 -0
- package/dist-cli/chunks/{film-ILA6VSOG.js → film-MVJCHWBU.js} +3 -3
- package/dist-cli/chunks/flow-XO4D3LRA.js +2 -0
- package/dist-cli/chunks/help-WNPSM6ZU.js +2 -0
- package/dist-cli/chunks/{hidden-runtime-alias-TD7IVAPF.js → hidden-runtime-alias-OVGHDXOR.js} +2 -2
- package/dist-cli/chunks/{home-paths-H36JDTNO.js → home-paths-3W46OKY6.js} +2 -2
- package/dist-cli/chunks/inspect-4J5NJCXS.js +2 -0
- package/dist-cli/chunks/install-desktop-GAEFTQ2K.js +2 -0
- package/dist-cli/chunks/{login-5WGZX2ZD.js → login-CU72MJHE.js} +4 -4
- package/dist-cli/chunks/{logout-V53WTVIZ.js → logout-SF5EPW7M.js} +2 -2
- package/dist-cli/chunks/{maestro-HGKYRD54.js → maestro-NYFSOD2H.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-6DNZSKDP.js → maestro-generate-VDAXEVCE.js} +3 -3
- package/dist-cli/chunks/{mode-YFMKORE5.js → mode-VSABDCU5.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-YQZA2MRD.js +2 -0
- package/dist-cli/chunks/{perf-EOIGFDWM.js → perf-5XMCN7A2.js} +2 -2
- package/dist-cli/chunks/{record-2F54QS6Y.js → record-NAYAEQPD.js} +10 -10
- package/dist-cli/chunks/runtime-LR63M7XX.js +2 -0
- package/dist-cli/chunks/screenshot-command-HFNYL2CY.js +151 -0
- package/dist-cli/chunks/{screenshots-capture-DIICN24R.js → screenshots-capture-JCBFMJFS.js} +3 -3
- package/dist-cli/chunks/{serve-66NC6PPZ.js → serve-Z5HVGJ3C.js} +5 -5
- package/dist-cli/chunks/{setup-ZYN4BTBR.js → setup-YKDBK3RX.js} +3 -3
- package/dist-cli/chunks/{skills-MDBIER7U.js → skills-DQOWHZBC.js} +2 -2
- package/dist-cli/chunks/{storage-AQ3SEO4Y.js → storage-TKTKWTWE.js} +2 -2
- package/dist-cli/chunks/store-FPAX23SK.js +2 -0
- package/dist-cli/chunks/telemetry-CWRFOESH.js +2 -0
- package/dist-cli/chunks/{timeline-VEGHQZ36.js → timeline-QJPIAP7L.js} +2 -2
- package/dist-cli/chunks/{upgrade-RNDCRPLJ.js → upgrade-4ZEV4BY2.js} +3 -3
- package/dist-cli/chunks/upload-OF4CO6WM.js +2 -0
- package/dist-cli/chunks/{version-XUMPKQUM.js → version-OVU37MXP.js} +2 -2
- package/dist-cli/chunks/{web-ESQGHVPD.js → web-JUDK5W4T.js} +2 -2
- package/dist-cli/chunks/{what-happened-6NJENKUF.js → what-happened-TKCIGNLL.js} +2 -2
- 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 +2 -2
- package/dist-lib/backend-origin.cjs +18 -18
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +4 -4
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +321 -79
- package/dist-lib/dev-bundle-resolution.cjs +2 -2
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +18 -13
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- 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.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +7 -7
- package/dist-lib/sdk.cjs +12 -4
- package/dist-lib/sdk.mjs +12 -4
- package/dist-lib/skills.cjs +456 -170
- package/dist-lib/vite.cjs +1 -1
- package/package.json +4 -4
- package/scripts/dev-server-scanner.ts +5 -5
- package/scripts/postinstall.cjs +1 -1
- package/scripts/preuninstall.cjs +1 -1
- package/skills/{soot → contrast}/SKILL.md +4 -4
- package/skills/sootsim-perf/SKILL.md +3 -1
- package/src/auth/shared-session.ts +1 -1
- package/src/backend-origin.ts +11 -11
- package/src/bridge-constants.ts +3 -3
- package/src/home-paths.ts +1 -1
- package/src/host/agent-host.ts +2 -2
- package/src/host/bridge-host.ts +21 -21
- package/src/native-dev-bundle-url.ts +3 -3
- package/src/runtime-assets.ts +3 -3
- package/src/runtime-delivery.ts +10 -4
- package/src/screenshots/compose.ts +4 -1
- package/src/screenshots/frame-compose.ts +4 -1
- package/src/screenshots/orchestrate.ts +7 -2
- package/src/vite-plugin-one.ts +3 -3
- package/src/vite-plugin.ts +3 -3
- package/dist-cli/chunks/beta-WLLSIVLW.js +0 -2
- package/dist-cli/chunks/chunk-35EAEAN4.js +0 -24
- package/dist-cli/chunks/chunk-44Z2X5R4.js +0 -2
- package/dist-cli/chunks/chunk-4BLOZ3AF.js +0 -2
- package/dist-cli/chunks/chunk-7K5K5NKB.js +0 -2
- package/dist-cli/chunks/chunk-7RWDQCIT.js +0 -1
- package/dist-cli/chunks/chunk-BVD2JFOX.js +0 -1
- package/dist-cli/chunks/chunk-HBEEYWK5.js +0 -2
- package/dist-cli/chunks/chunk-JNUGPBWC.js +0 -118
- package/dist-cli/chunks/chunk-KBSJA7HK.js +0 -3
- package/dist-cli/chunks/chunk-Z2E2DDIQ.js +0 -4
- package/dist-cli/chunks/cli-version-NNBCIQKL.js +0 -2
- package/dist-cli/chunks/daemon-GL5GQTWB.js +0 -2
- package/dist-cli/chunks/drivers-KBKJVF2Y.js +0 -2
- package/dist-cli/chunks/flow-L247VVBM.js +0 -2
- package/dist-cli/chunks/help-QIZEANNK.js +0 -2
- package/dist-cli/chunks/inspect-6OAVS27G.js +0 -2
- package/dist-cli/chunks/install-desktop-LKYAUUQY.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-YGNESGBH.js +0 -2
- package/dist-cli/chunks/runtime-FYVV4DCQ.js +0 -2
- package/dist-cli/chunks/screenshot-command-R535TYXY.js +0 -151
- package/dist-cli/chunks/store-6ZGLOTZI.js +0 -2
- package/dist-cli/chunks/telemetry-V76UPVDV.js +0 -2
- package/dist-cli/chunks/upload-KRBS3Y7Q.js +0 -2
package/dist-lib/detox/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.229 | (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;
|
|
@@ -36,8 +36,8 @@ __export(detox_exports, {
|
|
|
36
36
|
cleanup: () => cleanup,
|
|
37
37
|
device: () => device,
|
|
38
38
|
element: () => element,
|
|
39
|
-
expect: () =>
|
|
40
|
-
waitFor: () =>
|
|
39
|
+
expect: () => sootsimExpect,
|
|
40
|
+
waitFor: () => sootsimWaitFor
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(detox_exports);
|
|
43
43
|
var fs = __toESM(require("fs"), 1);
|
|
@@ -46,7 +46,108 @@ var import_playwright = require("playwright");
|
|
|
46
46
|
|
|
47
47
|
// ../../scripts/lib/reap-browser.ts
|
|
48
48
|
var import_node_child_process = require("node:child_process");
|
|
49
|
+
var discoveredChromePids = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
var reapPids = /* @__PURE__ */ new Set();
|
|
51
|
+
var installed = false;
|
|
52
|
+
function currentRuntime() {
|
|
53
|
+
return { platform: process.platform, env: process.env };
|
|
54
|
+
}
|
|
55
|
+
function softwareChromeAllowed(runtime = currentRuntime()) {
|
|
56
|
+
return runtime.platform === "linux" && runtime.env.GITHUB_ACTIONS === "true" && runtime.env.RUNNER_OS === "Linux";
|
|
57
|
+
}
|
|
58
|
+
function isSoftwareRendererArgument(value) {
|
|
59
|
+
const arg = String(value);
|
|
60
|
+
return /^--disable-gpu(?:=.*)?$/i.test(arg) || /^--enable-unsafe-swiftshader(?:=.*)?$/i.test(arg) || /^--use-angle=(?:swiftshader|swiftshader-webgl)$/i.test(arg) || /^--use-gl=swiftshader$/i.test(arg);
|
|
61
|
+
}
|
|
62
|
+
function softwareRendererArgumentInText(command) {
|
|
63
|
+
const unsafe = command.match(
|
|
64
|
+
/(?:^|\s)(--disable-gpu(?:=[^\s]+)?|--enable-unsafe-swiftshader(?:=[^\s]+)?|--use-angle=(?:swiftshader|swiftshader-webgl)|--use-gl=swiftshader)(?=\s|$)/i
|
|
65
|
+
);
|
|
66
|
+
return unsafe?.[1] ?? null;
|
|
67
|
+
}
|
|
68
|
+
function expectedAngle(platform) {
|
|
69
|
+
if (platform === "darwin") return "metal";
|
|
70
|
+
if (platform === "linux") return "vulkan";
|
|
71
|
+
return "default";
|
|
72
|
+
}
|
|
73
|
+
function assertGpuBrowserCommand(command, runtime = currentRuntime()) {
|
|
74
|
+
if (softwareChromeAllowed(runtime)) return;
|
|
75
|
+
const unsafe = softwareRendererArgumentInText(command);
|
|
76
|
+
if (unsafe) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`[reap-browser] refused software-rendering Chrome process argument ${unsafe}`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const angle = expectedAngle(runtime.platform);
|
|
82
|
+
const args = command.split(/\s+/);
|
|
83
|
+
if (!args.includes(`--use-angle=${angle}`) || !args.includes("--enable-gpu")) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`[reap-browser] Chrome process did not retain the required ${angle} GPU arguments`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (runtime.platform === "darwin" && command.includes("/Applications/Google Chrome.app/")) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
"[reap-browser] refused the user's installed Google Chrome; use Playwright channel chromium"
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function collectGpuRendererStrings(info) {
|
|
95
|
+
if (!info || typeof info !== "object") return [];
|
|
96
|
+
const record = info;
|
|
97
|
+
const gpu = record.gpu;
|
|
98
|
+
if (!gpu || typeof gpu !== "object") return [];
|
|
99
|
+
const gpuRecord = gpu;
|
|
100
|
+
const values = [];
|
|
101
|
+
const aux = gpuRecord.auxAttributes;
|
|
102
|
+
if (aux && typeof aux === "object") {
|
|
103
|
+
for (const value of Object.values(aux)) {
|
|
104
|
+
if (typeof value === "string") values.push(value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const devices = gpuRecord.devices;
|
|
108
|
+
if (Array.isArray(devices)) {
|
|
109
|
+
for (const device2 of devices) {
|
|
110
|
+
if (!device2 || typeof device2 !== "object") continue;
|
|
111
|
+
for (const value of Object.values(device2)) {
|
|
112
|
+
if (typeof value === "string") values.push(value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return values;
|
|
117
|
+
}
|
|
118
|
+
function browserProcessPid(info) {
|
|
119
|
+
if (!info || typeof info !== "object") return null;
|
|
120
|
+
const record = info;
|
|
121
|
+
if (!Array.isArray(record.processInfo)) return null;
|
|
122
|
+
for (const entry of record.processInfo) {
|
|
123
|
+
if (!entry || typeof entry !== "object") continue;
|
|
124
|
+
const processInfo = entry;
|
|
125
|
+
if (processInfo.type === "browser" && typeof processInfo.id === "number" && Number.isInteger(processInfo.id) && processInfo.id > 0) {
|
|
126
|
+
return processInfo.id;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
function assertGpuRendererInfo(info, runtime = currentRuntime()) {
|
|
132
|
+
if (softwareChromeAllowed(runtime)) return;
|
|
133
|
+
const renderers = collectGpuRendererStrings(info);
|
|
134
|
+
const summary = renderers.join(" | ");
|
|
135
|
+
if (!summary || /swiftshader|llvmpipe|software rasterizer/i.test(summary)) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`[reap-browser] Chrome reported a software renderer${summary ? `: ${summary}` : ""}`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
if (runtime.platform === "darwin" && !/metal/i.test(summary)) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`[reap-browser] Chrome did not report an ANGLE Metal renderer: ${summary}`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
49
146
|
function rootChromePid(b) {
|
|
147
|
+
if (b && typeof b === "object") {
|
|
148
|
+
const discovered = discoveredChromePids.get(b);
|
|
149
|
+
if (discovered !== void 0) return discovered;
|
|
150
|
+
}
|
|
50
151
|
const w = b;
|
|
51
152
|
if (w && typeof w.process === "function") {
|
|
52
153
|
try {
|
|
@@ -76,8 +177,96 @@ function killTree(pid) {
|
|
|
76
177
|
} catch {
|
|
77
178
|
}
|
|
78
179
|
}
|
|
79
|
-
|
|
80
|
-
|
|
180
|
+
function browserControl(b) {
|
|
181
|
+
const candidate = b;
|
|
182
|
+
if (!candidate || typeof candidate !== "object") return null;
|
|
183
|
+
if (typeof candidate.newBrowserCDPSession === "function" || typeof candidate.process === "function") {
|
|
184
|
+
return candidate;
|
|
185
|
+
}
|
|
186
|
+
if (typeof candidate.browser !== "function") return null;
|
|
187
|
+
try {
|
|
188
|
+
const browser = candidate.browser();
|
|
189
|
+
return browser ? browserControl(browser) : null;
|
|
190
|
+
} catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function registerChromePid(browser, control, pid) {
|
|
195
|
+
if (browser && typeof browser === "object") discoveredChromePids.set(browser, pid);
|
|
196
|
+
discoveredChromePids.set(control, pid);
|
|
197
|
+
reapPids.add(pid);
|
|
198
|
+
installReaper();
|
|
199
|
+
}
|
|
200
|
+
async function discoverChromePid(browser) {
|
|
201
|
+
const known = rootChromePid(browser);
|
|
202
|
+
if (known !== null) return known;
|
|
203
|
+
const control = browserControl(browser);
|
|
204
|
+
if (!control || typeof control.newBrowserCDPSession !== "function") return null;
|
|
205
|
+
const session = await control.newBrowserCDPSession();
|
|
206
|
+
try {
|
|
207
|
+
const pid = browserProcessPid(await session.send("SystemInfo.getProcessInfo"));
|
|
208
|
+
if (pid === null) return null;
|
|
209
|
+
registerChromePid(browser, control, pid);
|
|
210
|
+
return pid;
|
|
211
|
+
} finally {
|
|
212
|
+
await session.detach?.();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async function rejectLaunchedBrowser(browser) {
|
|
216
|
+
const root = rootChromePid(browser);
|
|
217
|
+
if (root !== null) {
|
|
218
|
+
reapPids.delete(root);
|
|
219
|
+
killTree(root);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const candidate = browser;
|
|
223
|
+
if (candidate && typeof candidate.close === "function") {
|
|
224
|
+
try {
|
|
225
|
+
await candidate.close();
|
|
226
|
+
} catch {
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
async function validateLaunchedGpuBrowser(browser, runtime, rendererTarget) {
|
|
231
|
+
if (softwareChromeAllowed(runtime)) return;
|
|
232
|
+
const root = rootChromePid(browser);
|
|
233
|
+
const launchedControl = browserControl(browser);
|
|
234
|
+
if (root !== null && launchedControl) {
|
|
235
|
+
registerChromePid(browser, launchedControl, root);
|
|
236
|
+
}
|
|
237
|
+
if (root !== null && (runtime.platform === "darwin" || runtime.platform === "linux")) {
|
|
238
|
+
const command = (0, import_node_child_process.execFileSync)("ps", ["-p", String(root), "-o", "command="], {
|
|
239
|
+
encoding: "utf8"
|
|
240
|
+
}).trim();
|
|
241
|
+
assertGpuBrowserCommand(command, runtime);
|
|
242
|
+
}
|
|
243
|
+
const rendererBrowser = rendererTarget ? await rendererTarget(browser) : browser;
|
|
244
|
+
const control = browserControl(rendererBrowser);
|
|
245
|
+
if (control && typeof control.newBrowserCDPSession === "function") {
|
|
246
|
+
const session = await control.newBrowserCDPSession();
|
|
247
|
+
try {
|
|
248
|
+
const pid = browserProcessPid(await session.send("SystemInfo.getProcessInfo"));
|
|
249
|
+
if (pid === null) {
|
|
250
|
+
throw new Error("[reap-browser] Chrome did not report its browser process id");
|
|
251
|
+
}
|
|
252
|
+
registerChromePid(browser, control, pid);
|
|
253
|
+
if (rendererBrowser && typeof rendererBrowser === "object") {
|
|
254
|
+
discoveredChromePids.set(rendererBrowser, pid);
|
|
255
|
+
}
|
|
256
|
+
if (runtime.platform === "darwin" || runtime.platform === "linux") {
|
|
257
|
+
const command = (0, import_node_child_process.execFileSync)("ps", ["-p", String(pid), "-o", "command="], {
|
|
258
|
+
encoding: "utf8"
|
|
259
|
+
}).trim();
|
|
260
|
+
assertGpuBrowserCommand(command, runtime);
|
|
261
|
+
}
|
|
262
|
+
assertGpuRendererInfo(await session.send("SystemInfo.getInfo"), runtime);
|
|
263
|
+
return;
|
|
264
|
+
} finally {
|
|
265
|
+
await session.detach?.();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
throw new Error("[reap-browser] could not validate the launched Chrome GPU renderer");
|
|
269
|
+
}
|
|
81
270
|
function installReaper() {
|
|
82
271
|
if (installed) return;
|
|
83
272
|
installed = true;
|
|
@@ -96,16 +285,24 @@ function installReaper() {
|
|
|
96
285
|
}
|
|
97
286
|
async function launchReapedScoped(launch) {
|
|
98
287
|
const browser = await launch();
|
|
99
|
-
|
|
288
|
+
let root = rootChromePid(browser);
|
|
289
|
+
if (root === null) {
|
|
290
|
+
try {
|
|
291
|
+
root = await discoverChromePid(browser);
|
|
292
|
+
} catch {
|
|
293
|
+
root = null;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
100
296
|
const mine = /* @__PURE__ */ new Set();
|
|
101
297
|
if (root != null) {
|
|
102
298
|
mine.add(root);
|
|
103
299
|
reapPids.add(root);
|
|
104
300
|
installReaper();
|
|
105
301
|
}
|
|
106
|
-
const evented = browser;
|
|
302
|
+
const evented = browserControl(browser) ?? browser;
|
|
107
303
|
if (typeof evented.on === "function") {
|
|
108
|
-
evented.
|
|
304
|
+
const disconnectEvent = typeof evented.newBrowserCDPSession === "function" ? "disconnected" : "close";
|
|
305
|
+
evented.on(disconnectEvent, () => {
|
|
109
306
|
for (const pid of mine) reapPids.delete(pid);
|
|
110
307
|
});
|
|
111
308
|
}
|
|
@@ -119,8 +316,8 @@ async function launchReapedScoped(launch) {
|
|
|
119
316
|
return { browser, reapNow };
|
|
120
317
|
}
|
|
121
318
|
var gpuChromeMissing = false;
|
|
122
|
-
function gpuChromeArgs() {
|
|
123
|
-
const angle =
|
|
319
|
+
function gpuChromeArgs(platform = process.platform) {
|
|
320
|
+
const angle = expectedAngle(platform);
|
|
124
321
|
return [
|
|
125
322
|
`--use-angle=${angle}`,
|
|
126
323
|
"--enable-gpu",
|
|
@@ -129,9 +326,38 @@ function gpuChromeArgs() {
|
|
|
129
326
|
"--ignore-gpu-blocklist"
|
|
130
327
|
];
|
|
131
328
|
}
|
|
132
|
-
function gpuChromeLaunchOptions(opts = {}) {
|
|
329
|
+
function gpuChromeLaunchOptions(opts = {}, runtime = currentRuntime()) {
|
|
133
330
|
const callerArgs = Array.isArray(opts.args) ? opts.args : [];
|
|
331
|
+
const unsafe = callerArgs.find(isSoftwareRendererArgument);
|
|
332
|
+
if (unsafe !== void 0) {
|
|
333
|
+
throw new Error(
|
|
334
|
+
`[reap-browser] refused software-rendering Chrome launch argument ${String(unsafe)}`
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
if (opts.executablePath !== void 0) {
|
|
338
|
+
throw new Error(
|
|
339
|
+
"[reap-browser] executablePath bypasses Playwright Chrome for Testing and is not allowed"
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
if (opts.ignoreDefaultArgs === true) {
|
|
343
|
+
throw new Error(
|
|
344
|
+
"[reap-browser] ignoreDefaultArgs=true bypasses required Chrome launch defaults"
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
const managedGpuArgs = /* @__PURE__ */ new Set([
|
|
348
|
+
"--enable-gpu",
|
|
349
|
+
"--enable-gpu-rasterization",
|
|
350
|
+
"--enable-zero-copy",
|
|
351
|
+
"--ignore-gpu-blocklist"
|
|
352
|
+
]);
|
|
353
|
+
const unmanagedCallerArgs = callerArgs.filter((arg) => {
|
|
354
|
+
const value = String(arg);
|
|
355
|
+
return !managedGpuArgs.has(value) && !value.startsWith("--use-angle=");
|
|
356
|
+
});
|
|
134
357
|
const callerIgnored = Array.isArray(opts.ignoreDefaultArgs) ? opts.ignoreDefaultArgs : [];
|
|
358
|
+
const ignoredDefaults = [
|
|
359
|
+
.../* @__PURE__ */ new Set([...callerIgnored, "--disable-gpu", "--enable-unsafe-swiftshader"])
|
|
360
|
+
];
|
|
135
361
|
return {
|
|
136
362
|
...opts,
|
|
137
363
|
// playwright's `chromium` channel is the full Google Chrome for Testing
|
|
@@ -139,22 +365,19 @@ function gpuChromeLaunchOptions(opts = {}) {
|
|
|
139
365
|
// com.google.chrome.for.testing, so automation cannot become the target of
|
|
140
366
|
// Dock open/quit events intended for the user's com.google.Chrome browser.
|
|
141
367
|
channel: "chromium",
|
|
142
|
-
args: [...gpuChromeArgs()
|
|
143
|
-
ignoreDefaultArgs:
|
|
368
|
+
args: [...unmanagedCallerArgs, ...gpuChromeArgs(runtime.platform)],
|
|
369
|
+
ignoreDefaultArgs: ignoredDefaults
|
|
144
370
|
};
|
|
145
371
|
}
|
|
146
|
-
function preferGpuChrome(launch, opts) {
|
|
372
|
+
function preferGpuChrome(launch, opts, rendererTarget) {
|
|
147
373
|
return async () => {
|
|
148
|
-
const
|
|
374
|
+
const runtime = currentRuntime();
|
|
375
|
+
const allowSoftwareFallback = softwareChromeAllowed(runtime);
|
|
376
|
+
const gpuOptions = gpuChromeLaunchOptions(opts, runtime);
|
|
149
377
|
if (!gpuChromeMissing) {
|
|
378
|
+
let browser;
|
|
150
379
|
try {
|
|
151
|
-
|
|
152
|
-
if (!allowSoftwareFallback && callerArgs.some(
|
|
153
|
-
(arg) => arg === "--enable-unsafe-swiftshader" || /^--use-angle=(?:swiftshader|swiftshader-webgl)$/i.test(String(arg))
|
|
154
|
-
)) {
|
|
155
|
-
throw new Error("[reap-browser] refused local SwiftShader launch arguments");
|
|
156
|
-
}
|
|
157
|
-
return await launch(gpuChromeLaunchOptions(opts));
|
|
380
|
+
browser = await launch(gpuOptions);
|
|
158
381
|
} catch (err) {
|
|
159
382
|
const msg = err instanceof Error ? err.message : String(err);
|
|
160
383
|
const missing = /not found at|not installed|Chromium distribution|Executable doesn't exist|No such file/i.test(
|
|
@@ -169,15 +392,29 @@ function preferGpuChrome(launch, opts) {
|
|
|
169
392
|
}
|
|
170
393
|
gpuChromeMissing = true;
|
|
171
394
|
console.warn(
|
|
172
|
-
"[reap-browser]
|
|
395
|
+
"[reap-browser] GitHub Actions Linux Chrome for Testing not found, falling back to chromium_headless_shell software rendering."
|
|
173
396
|
);
|
|
397
|
+
return launch(softwareFallbackChromeLaunchOptions(opts));
|
|
174
398
|
}
|
|
399
|
+
try {
|
|
400
|
+
await validateLaunchedGpuBrowser(browser, runtime, rendererTarget);
|
|
401
|
+
} catch (err) {
|
|
402
|
+
await rejectLaunchedBrowser(browser);
|
|
403
|
+
throw err;
|
|
404
|
+
}
|
|
405
|
+
return browser;
|
|
175
406
|
}
|
|
176
|
-
return launch(opts);
|
|
407
|
+
return launch(softwareFallbackChromeLaunchOptions(opts));
|
|
177
408
|
};
|
|
178
409
|
}
|
|
179
|
-
|
|
180
|
-
|
|
410
|
+
function softwareFallbackChromeLaunchOptions(opts) {
|
|
411
|
+
const fallback = { ...opts };
|
|
412
|
+
delete fallback.channel;
|
|
413
|
+
delete fallback.executablePath;
|
|
414
|
+
return fallback;
|
|
415
|
+
}
|
|
416
|
+
async function launchReapedChromeScoped(launch, opts = {}, rendererTarget) {
|
|
417
|
+
return launchReapedScoped(preferGpuChrome(launch, opts, rendererTarget));
|
|
181
418
|
}
|
|
182
419
|
|
|
183
420
|
// detox/gestures.ts
|
|
@@ -324,36 +561,36 @@ async function readSootsimPageMetrics(page) {
|
|
|
324
561
|
async function readSootsimInteractiveViewport(page) {
|
|
325
562
|
return (await readSootsimPageMetrics(page)).interactiveWindow;
|
|
326
563
|
}
|
|
327
|
-
async function sootsimToPage(page,
|
|
564
|
+
async function sootsimToPage(page, sootsimX, sootsimY) {
|
|
328
565
|
const metrics = await readSootsimPageMetrics(page);
|
|
329
566
|
const scaleX = metrics.canvas.width / metrics.window.width;
|
|
330
567
|
const scaleY = metrics.canvas.height / metrics.window.height;
|
|
331
568
|
return {
|
|
332
|
-
x: metrics.canvas.left +
|
|
333
|
-
y: metrics.canvas.top +
|
|
569
|
+
x: metrics.canvas.left + sootsimX * scaleX,
|
|
570
|
+
y: metrics.canvas.top + sootsimY * scaleY
|
|
334
571
|
};
|
|
335
572
|
}
|
|
336
573
|
async function dragScrollNode(page, node, pixels, direction) {
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
let
|
|
340
|
-
let
|
|
574
|
+
const startSootSimX = node.absolutePosition.x + node.layout.width / 2;
|
|
575
|
+
const startSootSimY = node.absolutePosition.y + node.layout.height / 2;
|
|
576
|
+
let endSootSimX = startSootSimX;
|
|
577
|
+
let endSootSimY = startSootSimY;
|
|
341
578
|
switch (direction) {
|
|
342
579
|
case "down":
|
|
343
|
-
|
|
580
|
+
endSootSimY -= pixels;
|
|
344
581
|
break;
|
|
345
582
|
case "up":
|
|
346
|
-
|
|
583
|
+
endSootSimY += pixels;
|
|
347
584
|
break;
|
|
348
585
|
case "left":
|
|
349
|
-
|
|
586
|
+
endSootSimX += pixels;
|
|
350
587
|
break;
|
|
351
588
|
case "right":
|
|
352
|
-
|
|
589
|
+
endSootSimX -= pixels;
|
|
353
590
|
break;
|
|
354
591
|
}
|
|
355
|
-
const startPage = await sootsimToPage(page,
|
|
356
|
-
const endPage = await sootsimToPage(page,
|
|
592
|
+
const startPage = await sootsimToPage(page, startSootSimX, startSootSimY);
|
|
593
|
+
const endPage = await sootsimToPage(page, endSootSimX, endSootSimY);
|
|
357
594
|
const steps = Math.max(16, Math.ceil(pixels / 8));
|
|
358
595
|
await page.mouse.move(startPage.x, startPage.y);
|
|
359
596
|
await page.mouse.down();
|
|
@@ -519,11 +756,11 @@ function describeNodeVisibility(node, viewport) {
|
|
|
519
756
|
});
|
|
520
757
|
}
|
|
521
758
|
function createExpect(findNode, getPage2) {
|
|
522
|
-
return function
|
|
523
|
-
return new
|
|
759
|
+
return function sootsimExpect2(el) {
|
|
760
|
+
return new SootSimExpectation(el._matcher, findNode, getPage2, false);
|
|
524
761
|
};
|
|
525
762
|
}
|
|
526
|
-
var
|
|
763
|
+
var SootSimExpectation = class _SootSimExpectation {
|
|
527
764
|
matcher;
|
|
528
765
|
findNode;
|
|
529
766
|
getPage;
|
|
@@ -535,7 +772,12 @@ var SootExpectation = class _SootExpectation {
|
|
|
535
772
|
this.negated = negated;
|
|
536
773
|
}
|
|
537
774
|
get not() {
|
|
538
|
-
return new
|
|
775
|
+
return new _SootSimExpectation(
|
|
776
|
+
this.matcher,
|
|
777
|
+
this.findNode,
|
|
778
|
+
this.getPage,
|
|
779
|
+
!this.negated
|
|
780
|
+
);
|
|
539
781
|
}
|
|
540
782
|
async toExist() {
|
|
541
783
|
const node = await this.findNode(this.matcher);
|
|
@@ -700,11 +942,11 @@ var SootExpectation = class _SootExpectation {
|
|
|
700
942
|
}
|
|
701
943
|
};
|
|
702
944
|
function createWaitFor(findNode, getPage2) {
|
|
703
|
-
return function
|
|
704
|
-
return new
|
|
945
|
+
return function sootsimWaitFor2(el) {
|
|
946
|
+
return new SootSimWaitForChain(el._matcher, findNode, getPage2);
|
|
705
947
|
};
|
|
706
948
|
}
|
|
707
|
-
var
|
|
949
|
+
var SootSimWaitForChain = class {
|
|
708
950
|
matcher;
|
|
709
951
|
findNode;
|
|
710
952
|
getPage;
|
|
@@ -727,7 +969,7 @@ var SootWaitForChain = class {
|
|
|
727
969
|
throw new Error(`waitFor toExist failed: ${JSON.stringify(this.matcher)}`);
|
|
728
970
|
}
|
|
729
971
|
};
|
|
730
|
-
return new
|
|
972
|
+
return new SootSimWaitForAction(this.assertionFn, this.findNode, this.getPage);
|
|
731
973
|
}
|
|
732
974
|
toBeVisible() {
|
|
733
975
|
this.assertionFn = async () => {
|
|
@@ -741,7 +983,7 @@ var SootWaitForChain = class {
|
|
|
741
983
|
);
|
|
742
984
|
}
|
|
743
985
|
};
|
|
744
|
-
return new
|
|
986
|
+
return new SootSimWaitForAction(this.assertionFn, this.findNode, this.getPage);
|
|
745
987
|
}
|
|
746
988
|
toBeNotVisible() {
|
|
747
989
|
this.assertionFn = async () => {
|
|
@@ -751,7 +993,7 @@ var SootWaitForChain = class {
|
|
|
751
993
|
throw new Error(`waitFor toBeNotVisible failed: ${JSON.stringify(this.matcher)}`);
|
|
752
994
|
}
|
|
753
995
|
};
|
|
754
|
-
return new
|
|
996
|
+
return new SootSimWaitForAction(this.assertionFn, this.findNode, this.getPage);
|
|
755
997
|
}
|
|
756
998
|
toHaveText(expectedText) {
|
|
757
999
|
this.assertionFn = async () => {
|
|
@@ -768,7 +1010,7 @@ var SootWaitForChain = class {
|
|
|
768
1010
|
);
|
|
769
1011
|
}
|
|
770
1012
|
};
|
|
771
|
-
return new
|
|
1013
|
+
return new SootSimWaitForAction(this.assertionFn, this.findNode, this.getPage);
|
|
772
1014
|
}
|
|
773
1015
|
toHaveValue(value) {
|
|
774
1016
|
this.assertionFn = async () => {
|
|
@@ -779,10 +1021,10 @@ var SootWaitForChain = class {
|
|
|
779
1021
|
throw new Error(`waitFor toHaveValue: expected "${value}" in "${actual}"`);
|
|
780
1022
|
}
|
|
781
1023
|
};
|
|
782
|
-
return new
|
|
1024
|
+
return new SootSimWaitForAction(this.assertionFn, this.findNode, this.getPage);
|
|
783
1025
|
}
|
|
784
1026
|
};
|
|
785
|
-
var
|
|
1027
|
+
var SootSimWaitForAction = class {
|
|
786
1028
|
assertionFn;
|
|
787
1029
|
findNode;
|
|
788
1030
|
getPage;
|
|
@@ -816,7 +1058,7 @@ var SootWaitForAction = class {
|
|
|
816
1058
|
}
|
|
817
1059
|
}
|
|
818
1060
|
whileElement(matcher) {
|
|
819
|
-
return new
|
|
1061
|
+
return new SootSimWaitForScrollAction(
|
|
820
1062
|
this.assertionFn,
|
|
821
1063
|
this.findNode,
|
|
822
1064
|
this.getPage,
|
|
@@ -824,7 +1066,7 @@ var SootWaitForAction = class {
|
|
|
824
1066
|
);
|
|
825
1067
|
}
|
|
826
1068
|
};
|
|
827
|
-
var
|
|
1069
|
+
var SootSimWaitForScrollAction = class {
|
|
828
1070
|
assertionFn;
|
|
829
1071
|
findNode;
|
|
830
1072
|
getPage;
|
|
@@ -1385,7 +1627,7 @@ async function dispatchSootsimEventInPage(type, detail) {
|
|
|
1385
1627
|
{ detail, type }
|
|
1386
1628
|
);
|
|
1387
1629
|
}
|
|
1388
|
-
function
|
|
1630
|
+
function createSootSimElement(matcher) {
|
|
1389
1631
|
const el = {
|
|
1390
1632
|
_matcher: matcher,
|
|
1391
1633
|
async tap(point) {
|
|
@@ -1394,8 +1636,8 @@ function createSootElement(matcher) {
|
|
|
1394
1636
|
const node = await findNodeByMatcher(matcher);
|
|
1395
1637
|
if (!node) throw new Error(`element not found for tap: ${JSON.stringify(matcher)}`);
|
|
1396
1638
|
const defaultPoint = point ? null : await getDefaultTapPoint(page, node);
|
|
1397
|
-
const
|
|
1398
|
-
const
|
|
1639
|
+
const targetSootSimX = typeof point?.x === "number" ? node.absolutePosition.x + point.x : defaultPoint?.x ?? node.absolutePosition.x + node.layout.width / 2;
|
|
1640
|
+
const targetSootSimY = typeof point?.y === "number" ? node.absolutePosition.y + point.y : defaultPoint?.y ?? node.absolutePosition.y + node.layout.height / 2;
|
|
1399
1641
|
await page.evaluate(
|
|
1400
1642
|
async ({ x, y }) => {
|
|
1401
1643
|
const interactTap = window.SootSim?.bridges?.interact?.tap;
|
|
@@ -1409,7 +1651,7 @@ function createSootElement(matcher) {
|
|
|
1409
1651
|
}
|
|
1410
1652
|
await tap(x, y);
|
|
1411
1653
|
},
|
|
1412
|
-
{ x:
|
|
1654
|
+
{ x: targetSootSimX, y: targetSootSimY }
|
|
1413
1655
|
);
|
|
1414
1656
|
await page.waitForTimeout(50);
|
|
1415
1657
|
if (_synchronizationEnabled) {
|
|
@@ -1465,12 +1707,12 @@ function createSootElement(matcher) {
|
|
|
1465
1707
|
throw new Error(
|
|
1466
1708
|
`target element not found: ${JSON.stringify(targetElement._matcher)}`
|
|
1467
1709
|
);
|
|
1468
|
-
const
|
|
1469
|
-
const
|
|
1470
|
-
const
|
|
1471
|
-
const
|
|
1472
|
-
const startPage = await sootsimToPage(page,
|
|
1473
|
-
const endPage = await sootsimToPage(page,
|
|
1710
|
+
const startSootSimX = srcNode.absolutePosition.x + srcNode.layout.width * normalizedStartX;
|
|
1711
|
+
const startSootSimY = srcNode.absolutePosition.y + srcNode.layout.height * normalizedStartY;
|
|
1712
|
+
const endSootSimX = tgtNode.absolutePosition.x + tgtNode.layout.width * normalizedEndX;
|
|
1713
|
+
const endSootSimY = tgtNode.absolutePosition.y + tgtNode.layout.height * normalizedEndY;
|
|
1714
|
+
const startPage = await sootsimToPage(page, startSootSimX, startSootSimY);
|
|
1715
|
+
const endPage = await sootsimToPage(page, endSootSimX, endSootSimY);
|
|
1474
1716
|
const steps = speed === "slow" ? 20 : 10;
|
|
1475
1717
|
await page.mouse.move(startPage.x, startPage.y);
|
|
1476
1718
|
await page.mouse.down();
|
|
@@ -1568,23 +1810,23 @@ function createSootElement(matcher) {
|
|
|
1568
1810
|
throw new Error(`element not found for swipe: ${JSON.stringify(matcher)}`);
|
|
1569
1811
|
const page = getPage();
|
|
1570
1812
|
const { absolutePosition, layout } = node;
|
|
1571
|
-
const
|
|
1572
|
-
const
|
|
1573
|
-
let
|
|
1574
|
-
let
|
|
1813
|
+
const startSootSimX = absolutePosition.x + layout.width * 0.5;
|
|
1814
|
+
const startSootSimY = absolutePosition.y + layout.height * 0.5;
|
|
1815
|
+
let endSootSimX = startSootSimX;
|
|
1816
|
+
let endSootSimY = startSootSimY;
|
|
1575
1817
|
const dist = direction === "up" || direction === "down" ? layout.height * percentage : layout.width * percentage;
|
|
1576
1818
|
switch (direction) {
|
|
1577
1819
|
case "up":
|
|
1578
|
-
|
|
1820
|
+
endSootSimY -= dist;
|
|
1579
1821
|
break;
|
|
1580
1822
|
case "down":
|
|
1581
|
-
|
|
1823
|
+
endSootSimY += dist;
|
|
1582
1824
|
break;
|
|
1583
1825
|
case "left":
|
|
1584
|
-
|
|
1826
|
+
endSootSimX -= dist;
|
|
1585
1827
|
break;
|
|
1586
1828
|
case "right":
|
|
1587
|
-
|
|
1829
|
+
endSootSimX += dist;
|
|
1588
1830
|
break;
|
|
1589
1831
|
}
|
|
1590
1832
|
const steps = speed === "slow" ? 20 : speed === "fast" ? 8 : 12;
|
|
@@ -1598,10 +1840,10 @@ function createSootElement(matcher) {
|
|
|
1598
1840
|
await drag(fromX, fromY, toX, toY, steps2, stepMs);
|
|
1599
1841
|
},
|
|
1600
1842
|
{
|
|
1601
|
-
fromX:
|
|
1602
|
-
fromY:
|
|
1603
|
-
toX:
|
|
1604
|
-
toY:
|
|
1843
|
+
fromX: startSootSimX,
|
|
1844
|
+
fromY: startSootSimY,
|
|
1845
|
+
toX: endSootSimX,
|
|
1846
|
+
toY: endSootSimY,
|
|
1605
1847
|
steps,
|
|
1606
1848
|
stepMs: stepDelay
|
|
1607
1849
|
}
|
|
@@ -1695,7 +1937,7 @@ function createSootElement(matcher) {
|
|
|
1695
1937
|
return el;
|
|
1696
1938
|
}
|
|
1697
1939
|
function element(matcher) {
|
|
1698
|
-
return
|
|
1940
|
+
return createSootSimElement(matcher);
|
|
1699
1941
|
}
|
|
1700
1942
|
var device = {
|
|
1701
1943
|
_currentUrl: "",
|
|
@@ -2061,8 +2303,8 @@ var device = {
|
|
|
2061
2303
|
return getPage();
|
|
2062
2304
|
}
|
|
2063
2305
|
};
|
|
2064
|
-
var
|
|
2065
|
-
var
|
|
2306
|
+
var sootsimExpect = createExpect(findNodeByMatcher, getPage);
|
|
2307
|
+
var sootsimWaitFor = createWaitFor(findNodeByMatcher, getPage);
|
|
2066
2308
|
async function cleanup() {
|
|
2067
2309
|
await closeBrowser();
|
|
2068
2310
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.229 | (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;
|
|
@@ -55,7 +55,7 @@ function applyPreviewProdBundle(parsed) {
|
|
|
55
55
|
function normalizeNativeDevBundleUrl(bundleUrl) {
|
|
56
56
|
try {
|
|
57
57
|
const isAbsolute = isAbsoluteHttpUrl(bundleUrl);
|
|
58
|
-
const parsed = new URL(bundleUrl, "http://
|
|
58
|
+
const parsed = new URL(bundleUrl, "http://sootsim.local");
|
|
59
59
|
parsed.pathname = parsed.pathname.replace(/\.\.bundle$/, ".bundle");
|
|
60
60
|
if (!isNativeDevBundlePath(parsed.pathname)) return bundleUrl;
|
|
61
61
|
parsed.searchParams.delete("transform.bytecode");
|
package/dist-lib/home-paths.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.229 | (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;
|