sootsim 0.1.259 → 0.1.261

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 (152) hide show
  1. package/detox/jest-preset.cjs +1 -0
  2. package/detox/jest-setup-after-env.cjs +18 -0
  3. package/dist-cli/bin.js +4 -4
  4. package/dist-cli/chunks/{agent-Y5XPRQ2D.js → agent-RXKGHJYJ.js} +2 -2
  5. package/dist-cli/chunks/{agent-wrapper-EIGM5MZ5.js → agent-wrapper-A2CMG2BA.js} +2 -2
  6. package/dist-cli/chunks/{app-fonts-F66DJNOU.js → app-fonts-JMZWYM5K.js} +2 -2
  7. package/dist-cli/chunks/{assert-4UNH35YI.js → assert-EOJ3EHJQ.js} +2 -2
  8. package/dist-cli/chunks/{auth-3VXKAWDD.js → auth-SIJSL6ZW.js} +2 -2
  9. package/dist-cli/chunks/beta-BCHJBPJM.js +2 -0
  10. package/dist-cli/chunks/{camera-TVRTON3X.js → camera-BKZSMPSA.js} +2 -2
  11. package/dist-cli/chunks/chunk-2XGPQPBQ.js +1 -0
  12. package/dist-cli/chunks/{chunk-XVDDOJWS.js → chunk-6ZERINEJ.js} +2 -2
  13. package/dist-cli/chunks/{chunk-VUXUMQEC.js → chunk-75TC4YBZ.js} +2 -2
  14. package/dist-cli/chunks/{chunk-UDZJW6SR.js → chunk-7EIZLBLT.js} +1 -1
  15. package/dist-cli/chunks/chunk-AXJTPAHA.js +2 -0
  16. package/dist-cli/chunks/{chunk-OVZ4WWJC.js → chunk-BARVOECN.js} +3 -3
  17. package/dist-cli/chunks/{chunk-4QVZO2IV.js → chunk-BM5GBB56.js} +1 -1
  18. package/dist-cli/chunks/{chunk-KKKRQKVE.js → chunk-DKDYYXRY.js} +2 -2
  19. package/dist-cli/chunks/{chunk-55HDNMCI.js → chunk-GIVBLMYH.js} +2 -2
  20. package/dist-cli/chunks/{chunk-D3T6TPWZ.js → chunk-HK3WEUHS.js} +2 -2
  21. package/dist-cli/chunks/{chunk-2GC6B6ZJ.js → chunk-HZHQMMJ3.js} +1 -1
  22. package/dist-cli/chunks/{chunk-YI4ZUUFY.js → chunk-ILTQ4ZPZ.js} +3 -3
  23. package/dist-cli/chunks/{chunk-46SE2OG4.js → chunk-JHJYM5IX.js} +1 -1
  24. package/dist-cli/chunks/chunk-JNHCJEUS.js +2 -0
  25. package/dist-cli/chunks/{chunk-HLI3NHBR.js → chunk-K2DYN4E4.js} +3 -3
  26. package/dist-cli/chunks/{chunk-OSHPYGDN.js → chunk-KNRPSHXD.js} +1 -1
  27. package/dist-cli/chunks/{chunk-4SDLMKK5.js → chunk-LFT2G6CS.js} +1 -1
  28. package/dist-cli/chunks/{chunk-ARUD4K7V.js → chunk-MAKP6XWE.js} +1 -1
  29. package/dist-cli/chunks/{chunk-EQEZMYYU.js → chunk-MLKQ6UCQ.js} +2 -2
  30. package/dist-cli/chunks/{chunk-DHF4VP6F.js → chunk-NC3JIEPR.js} +2 -2
  31. package/dist-cli/chunks/{chunk-JEG2BY3L.js → chunk-NE6RIOHA.js} +2 -2
  32. package/dist-cli/chunks/{chunk-YSVATVIB.js → chunk-NER5BICF.js} +2 -2
  33. package/dist-cli/chunks/{chunk-5NNPUZ4U.js → chunk-NIW6FA7Z.js} +1 -1
  34. package/dist-cli/chunks/{chunk-FOJYE5VS.js → chunk-NPFX6EB3.js} +1 -1
  35. package/dist-cli/chunks/{chunk-Q7GIZYXH.js → chunk-NRPETN6L.js} +2 -2
  36. package/dist-cli/chunks/{chunk-Z5OYAYQO.js → chunk-OILZ3XOV.js} +2 -2
  37. package/dist-cli/chunks/{chunk-3BEO6YPO.js → chunk-PQMCTB2S.js} +2 -2
  38. package/dist-cli/chunks/{chunk-MGK5XZSP.js → chunk-QHFMMVZS.js} +1 -1
  39. package/dist-cli/chunks/{chunk-4WWQ4SHW.js → chunk-QKU7E35D.js} +1 -1
  40. package/dist-cli/chunks/{chunk-BN2FNCSW.js → chunk-QM6C26WM.js} +3 -3
  41. package/dist-cli/chunks/{chunk-7E5C6Y2O.js → chunk-QP7HQHRB.js} +2 -2
  42. package/dist-cli/chunks/{chunk-ANBTDAWQ.js → chunk-QS4WA56I.js} +2 -2
  43. package/dist-cli/chunks/{chunk-BYBAZTMQ.js → chunk-R5AUBYLC.js} +1 -1
  44. package/dist-cli/chunks/chunk-RLPH773J.js +1 -0
  45. package/dist-cli/chunks/{chunk-2DDWJAT5.js → chunk-RZYPYVAE.js} +2 -2
  46. package/dist-cli/chunks/{chunk-V4TOXWP7.js → chunk-SYJEB5TC.js} +2 -2
  47. package/dist-cli/chunks/{chunk-XJXI5J7N.js → chunk-UH722XMQ.js} +3 -3
  48. package/dist-cli/chunks/{chunk-5BFCOQAM.js → chunk-UPXPN2SA.js} +2 -2
  49. package/dist-cli/chunks/{chunk-IAE5QGBW.js → chunk-V5JUP7E5.js} +2 -2
  50. package/dist-cli/chunks/{chunk-VCTPUENT.js → chunk-WNCRDOVZ.js} +1 -1
  51. package/dist-cli/chunks/{chunk-QLTUXFJF.js → chunk-WVA7UPF2.js} +1 -1
  52. package/dist-cli/chunks/{chunk-NI2TLQ7P.js → chunk-XGZRIJRY.js} +25 -25
  53. package/dist-cli/chunks/{chunk-X4X3S7AO.js → chunk-ZUDTLJQC.js} +1 -1
  54. package/dist-cli/chunks/{chunk-KUUI2GRK.js → chunk-ZUKJYGD4.js} +2 -2
  55. package/dist-cli/chunks/cli-version-QSLFZF4X.js +2 -0
  56. package/dist-cli/chunks/{compat-SH2X4HRP.js → compat-GVAGEQAZ.js} +3 -3
  57. package/dist-cli/chunks/{config-3SFT2VG7.js → config-GMSFGZWY.js} +2 -2
  58. package/dist-cli/chunks/{control-UUEOKOW5.js → control-DUUEIJ4L.js} +2 -2
  59. package/dist-cli/chunks/daemon-7D67LUBQ.js +2 -0
  60. package/dist-cli/chunks/{debug-SIOQEV3E.js → debug-IIBOAEZB.js} +3 -3
  61. package/dist-cli/chunks/{desktop-3JRJQ5L5.js → desktop-MEMBM7BZ.js} +3 -3
  62. package/dist-cli/chunks/detox-J2ZIS7ZG.js +50 -0
  63. package/dist-cli/chunks/{device-VN7DX635.js → device-NEMPOW5X.js} +2 -2
  64. package/dist-cli/chunks/{diagnose-2YZUEQER.js → diagnose-XLD6UYAA.js} +2 -2
  65. package/dist-cli/chunks/drivers-QUSXEJ5B.js +2 -0
  66. package/dist-cli/chunks/{film-7ANS4KZ2.js → film-PN6U3DXD.js} +3 -3
  67. package/dist-cli/chunks/flow-MDGQP7KY.js +2 -0
  68. package/dist-cli/chunks/help-ZBFQ4TRI.js +2 -0
  69. package/dist-cli/chunks/{hidden-runtime-alias-L4P5JXZI.js → hidden-runtime-alias-ASB2DGU3.js} +2 -2
  70. package/dist-cli/chunks/{home-paths-Q3NEFW2T.js → home-paths-FLQYZTZC.js} +2 -2
  71. package/dist-cli/chunks/inspect-GE7F3UD5.js +2 -0
  72. package/dist-cli/chunks/install-desktop-NJFBRUQK.js +2 -0
  73. package/dist-cli/chunks/{login-E3LMU5M2.js → login-ELTUXIGJ.js} +4 -4
  74. package/dist-cli/chunks/{logout-EDU3Q3PN.js → logout-JUHMBKCF.js} +2 -2
  75. package/dist-cli/chunks/{maestro-YPMQ5T3A.js → maestro-FX22V3QM.js} +3 -3
  76. package/dist-cli/chunks/maestro-generate-QALAHEDN.js +34 -0
  77. package/dist-cli/chunks/{mode-FX6JHSIW.js → mode-Z32XIGKC.js} +2 -2
  78. package/dist-cli/chunks/optional-demo-registry-P5LGBWMR.js +2 -0
  79. package/dist-cli/chunks/{perf-2FPZ4WM7.js → perf-4W3HMHDG.js} +2 -2
  80. package/dist-cli/chunks/{record-PVXBQS37.js → record-J23EU2PJ.js} +3 -3
  81. package/dist-cli/chunks/runtime-NUA23EAD.js +2 -0
  82. package/dist-cli/chunks/{screenshot-command-FHT46DAS.js → screenshot-command-AVQKBRJD.js} +5 -5
  83. package/dist-cli/chunks/{screenshots-capture-4JKW4LO5.js → screenshots-capture-LQ4WG4YD.js} +2 -2
  84. package/dist-cli/chunks/{serve-VOBB5L4R.js → serve-VJW3DHXR.js} +2 -2
  85. package/dist-cli/chunks/{setup-JRK7OMNF.js → setup-DLZZ5GYH.js} +3 -3
  86. package/dist-cli/chunks/{skills-G2EGKHAC.js → skills-43K6ZI7K.js} +2 -2
  87. package/dist-cli/chunks/{storage-WUHC3DDJ.js → storage-6AFPJODY.js} +2 -2
  88. package/dist-cli/chunks/store-MNIZHXQW.js +2 -0
  89. package/dist-cli/chunks/telemetry-WK7QRXMO.js +2 -0
  90. package/dist-cli/chunks/{timeline-HZFFJYRK.js → timeline-4GTSVWUU.js} +2 -2
  91. package/dist-cli/chunks/{upgrade-CSHTNNFC.js → upgrade-KHV5HMEC.js} +2 -2
  92. package/dist-cli/chunks/upload-56DF47MA.js +2 -0
  93. package/dist-cli/chunks/{version-ZQUMDD7H.js → version-DZ3NNQYK.js} +2 -2
  94. package/dist-cli/chunks/{web-SH74DBQB.js → web-OALK6L2K.js} +2 -2
  95. package/dist-cli/chunks/{what-happened-LRO7J5BV.js → what-happened-COLALBX2.js} +2 -2
  96. package/dist-lib/agent-daemon-client.cjs +1 -1
  97. package/dist-lib/agent-events.cjs +1 -1
  98. package/dist-lib/agent-identity.cjs +1 -1
  99. package/dist-lib/agent-sessions.cjs +1 -1
  100. package/dist-lib/attached-projects.cjs +1 -1
  101. package/dist-lib/auth/shared-session.cjs +1 -1
  102. package/dist-lib/backend-origin.cjs +1 -1
  103. package/dist-lib/beta.cjs +1 -1
  104. package/dist-lib/beta.mjs +1 -1
  105. package/dist-lib/bridge-constants.cjs +1 -1
  106. package/dist-lib/cli-constants.cjs +1 -1
  107. package/dist-lib/config.cjs +1 -1
  108. package/dist-lib/detox/index.cjs +12 -9
  109. package/dist-lib/detox/jest-preset.cjs +1 -0
  110. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  111. package/dist-lib/home-paths.cjs +1 -1
  112. package/dist-lib/host/bridge-host.cjs +1 -1
  113. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  114. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  115. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  116. package/dist-lib/host/websocket-proxy.cjs +1 -1
  117. package/dist-lib/index.cjs +1 -1
  118. package/dist-lib/jump-to-source-babel.cjs +1 -1
  119. package/dist-lib/menu.cjs +1 -1
  120. package/dist-lib/menu.mjs +1 -1
  121. package/dist-lib/metro.cjs +1 -1
  122. package/dist-lib/profiles.cjs +1 -1
  123. package/dist-lib/render-mode.cjs +1 -1
  124. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  125. package/dist-lib/sdk.cjs +1 -1
  126. package/dist-lib/sdk.mjs +1 -1
  127. package/dist-lib/skills.cjs +20 -14
  128. package/dist-lib/vite.cjs +1 -1
  129. package/package.json +1 -1
  130. package/src/screenshots/frame-compose.ts +8 -5
  131. package/src/vite-plugin.ts +18 -21
  132. package/detox/jest-environment.ts +0 -86
  133. package/detox/run-test.ts +0 -113
  134. package/dist-cli/chunks/beta-3BITBQAB.js +0 -2
  135. package/dist-cli/chunks/chunk-4TKQWCCG.js +0 -1
  136. package/dist-cli/chunks/chunk-GWSEPKCY.js +0 -2
  137. package/dist-cli/chunks/chunk-NXZAVEZK.js +0 -2
  138. package/dist-cli/chunks/chunk-QVRTNQRH.js +0 -1
  139. package/dist-cli/chunks/cli-version-DCWEI5UA.js +0 -2
  140. package/dist-cli/chunks/daemon-CAOFTJEQ.js +0 -2
  141. package/dist-cli/chunks/detox-IOXKXWRT.js +0 -50
  142. package/dist-cli/chunks/drivers-DFPU4A4I.js +0 -2
  143. package/dist-cli/chunks/flow-JV2H54P3.js +0 -2
  144. package/dist-cli/chunks/help-4KULPPHD.js +0 -2
  145. package/dist-cli/chunks/inspect-OPDVT6OL.js +0 -2
  146. package/dist-cli/chunks/install-desktop-FWSKBMOQ.js +0 -2
  147. package/dist-cli/chunks/maestro-generate-VRJDXEAS.js +0 -34
  148. package/dist-cli/chunks/optional-demo-registry-AQIAQEP7.js +0 -2
  149. package/dist-cli/chunks/runtime-GREWVZJS.js +0 -2
  150. package/dist-cli/chunks/store-RR7SOYWS.js +0 -2
  151. package/dist-cli/chunks/telemetry-K276VZJW.js +0 -2
  152. package/dist-cli/chunks/upload-RJ7GSDJT.js +0 -2
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{C as N,D as F,F as y,Q as T,R as b,S}from"./chunk-4WWQ4SHW.js";import{g as A,i as _}from"./chunk-55HDNMCI.js";import"./chunk-BYBAZTMQ.js";import{c as k}from"./chunk-OVZ4WWJC.js";import"./chunk-2GC6B6ZJ.js";import"./chunk-5NNPUZ4U.js";function O(n){let t=[];for(let e=0;e<n.length;e++)if(n[e]==="--since"&&e+1<n.length){t.push(e,e+1);let s=n[e+1].trim(),l=/^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(s);if(l){let r=Number(l[1]),u=l[2]??"ms",v=u==="s"?r*1e3:u==="m"?r*6e4:r;return{since:Date.now()-v,consumed:t}}let i=Number(s);if(Number.isFinite(i)&&i>1e12)return{since:i,consumed:t}}return{consumed:t}}function B(n){let t=[];for(let e=0;e<n.length;e++)if(n[e]==="--kinds"&&e+1<n.length)return t.push(e,e+1),{kinds:n[e+1].split(",").map(s=>s.trim()).filter(Boolean),consumed:t};return{consumed:t}}function D(n){let t=[];for(let e=0;e<n.length;e++)if(n[e]==="--limit"&&e+1<n.length){t.push(e,e+1);let s=Number(n[e+1]);if(Number.isFinite(s)&&s>0)return{limit:s,consumed:t}}return{consumed:t}}function x(n){let t=[],e={label:"initial state",events:[],startedAt:n[0]?.t??null};t.push(e);for(let s of n)if(e.events.push(s),s.kind==="screen"||s.kind==="route"){let l=s.data,i=l?.phase;if(!i||i==="enter"||i==="appear"||i==="active"){let r=l?.name||l?.activeName||l?.path||l?.pathname||s.kind;t.length===1&&e.events.length===1?e.label=`${s.kind}: ${r}`:(e={label:`${s.kind}: ${r}`,events:[],startedAt:s.t},t.push(e))}}return t}async function J(n,t){let e=A(n,{port:t.port,stripBooleanFlags:["--summary","--all","--json","--no-advance","--help","-h","--flow","--noisy"],stripValueFlags:["--since","--kinds","--limit"]});(n.includes("--help")||n.includes("-h"))&&(console.log(`
1
+ /*! sootsim v0.1.261 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{C as N,D as F,F as y,Q as T,R as b,S}from"./chunk-QKU7E35D.js";import{g as A,i as _}from"./chunk-GIVBLMYH.js";import"./chunk-R5AUBYLC.js";import{c as k}from"./chunk-BARVOECN.js";import"./chunk-HZHQMMJ3.js";import"./chunk-NIW6FA7Z.js";function O(n){let t=[];for(let e=0;e<n.length;e++)if(n[e]==="--since"&&e+1<n.length){t.push(e,e+1);let s=n[e+1].trim(),l=/^(\d+(?:\.\d+)?)(ms|s|m)?$/.exec(s);if(l){let r=Number(l[1]),u=l[2]??"ms",v=u==="s"?r*1e3:u==="m"?r*6e4:r;return{since:Date.now()-v,consumed:t}}let i=Number(s);if(Number.isFinite(i)&&i>1e12)return{since:i,consumed:t}}return{consumed:t}}function B(n){let t=[];for(let e=0;e<n.length;e++)if(n[e]==="--kinds"&&e+1<n.length)return t.push(e,e+1),{kinds:n[e+1].split(",").map(s=>s.trim()).filter(Boolean),consumed:t};return{consumed:t}}function D(n){let t=[];for(let e=0;e<n.length;e++)if(n[e]==="--limit"&&e+1<n.length){t.push(e,e+1);let s=Number(n[e+1]);if(Number.isFinite(s)&&s>0)return{limit:s,consumed:t}}return{consumed:t}}function x(n){let t=[],e={label:"initial state",events:[],startedAt:n[0]?.t??null};t.push(e);for(let s of n)if(e.events.push(s),s.kind==="screen"||s.kind==="route"){let l=s.data,i=l?.phase;if(!i||i==="enter"||i==="appear"||i==="active"){let r=l?.name||l?.activeName||l?.path||l?.pathname||s.kind;t.length===1&&e.events.length===1?e.label=`${s.kind}: ${r}`:(e={label:`${s.kind}: ${r}`,events:[],startedAt:s.t},t.push(e))}}return t}async function J(n,t){let e=A(n,{port:t.port,stripBooleanFlags:["--summary","--all","--json","--no-advance","--help","-h","--flow","--noisy"],stripValueFlags:["--since","--kinds","--limit"]});(n.includes("--help")||n.includes("-h"))&&(console.log(`
3
3
  sootsim what-happened \u2014 show recent events from the semantic timeline
4
4
 
5
5
  usage:
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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;
@@ -267,20 +267,23 @@ async function validateLaunchedGpuBrowser(browser, runtime, rendererTarget) {
267
267
  }
268
268
  throw new Error("[reap-browser] could not validate the launched Chrome GPU renderer");
269
269
  }
270
+ var signalShutdownClaimed = false;
270
271
  function installReaper() {
271
272
  if (installed) return;
272
273
  installed = true;
273
274
  const reap = () => {
274
275
  for (const pid of reapPids) killTree(pid);
275
276
  };
276
- process.on("SIGTERM", () => {
277
- reap();
278
- process.exit(0);
279
- });
280
- process.on("SIGINT", () => {
281
- reap();
282
- process.exit(0);
283
- });
277
+ if (!signalShutdownClaimed) {
278
+ process.on("SIGTERM", () => {
279
+ reap();
280
+ process.exit(0);
281
+ });
282
+ process.on("SIGINT", () => {
283
+ reap();
284
+ process.exit(0);
285
+ });
286
+ }
284
287
  process.on("exit", reap);
285
288
  }
286
289
  async function launchReapedScoped(launch) {
@@ -20,6 +20,7 @@ module.exports = {
20
20
  forceExit: true,
21
21
  verbose: true,
22
22
  testEnvironment: 'node',
23
+ setupFilesAfterEnv: [path.join(PACKAGE_ROOT, 'detox', 'jest-setup-after-env.cjs')],
23
24
  transform: {
24
25
  '^.+\\.tsx?$': [
25
26
  'ts-jest',
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/menu.ts
4
4
  var SOOTSIM_ENGINE_EVENT_NAME = "sootsim:engine-event";
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // cli/commands/inspect/core.ts
4
4
  function resolveMaxMsFlag(args, fallbackMs) {
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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;
@@ -257,14 +257,16 @@ function installReaper() {
257
257
  const reap = () => {
258
258
  for (const pid of reapPids) killTree(pid);
259
259
  };
260
- process.on("SIGTERM", () => {
261
- reap();
262
- process.exit(0);
263
- });
264
- process.on("SIGINT", () => {
265
- reap();
266
- process.exit(0);
267
- });
260
+ if (!signalShutdownClaimed) {
261
+ process.on("SIGTERM", () => {
262
+ reap();
263
+ process.exit(0);
264
+ });
265
+ process.on("SIGINT", () => {
266
+ reap();
267
+ process.exit(0);
268
+ });
269
+ }
268
270
  process.on("exit", reap);
269
271
  }
270
272
  async function launchReapedScoped(launch) {
@@ -403,7 +405,7 @@ function softwareFallbackChromeLaunchOptions(opts) {
403
405
  async function launchReapedChrome(launch, opts = {}, rendererTarget) {
404
406
  return launchReaped(preferGpuChrome(launch, opts, rendererTarget));
405
407
  }
406
- var import_node_child_process, discoveredChromePids, reapPids, installed, gpuChromeMissing;
408
+ var import_node_child_process, discoveredChromePids, reapPids, installed, signalShutdownClaimed, gpuChromeMissing;
407
409
  var init_reap_browser = __esm({
408
410
  "../../scripts/lib/reap-browser.ts"() {
409
411
  "use strict";
@@ -411,6 +413,7 @@ var init_reap_browser = __esm({
411
413
  discoveredChromePids = /* @__PURE__ */ new WeakMap();
412
414
  reapPids = /* @__PURE__ */ new Set();
413
415
  installed = false;
416
+ signalShutdownClaimed = false;
414
417
  gpuChromeMissing = false;
415
418
  }
416
419
  });
@@ -15678,7 +15681,9 @@ function findTopAncestor(start, maxDepth = 20) {
15678
15681
  const comm = getProcessComm(pid);
15679
15682
  if (comm && IMMORTAL_HOST_COMM_RE.test(comm)) return prev;
15680
15683
  const parent = getParentPid(pid);
15681
- if (!parent || parent <= 1) return pid;
15684
+ if (!parent || parent <= 1) {
15685
+ return comm ? pid : prev;
15686
+ }
15682
15687
  prev = pid;
15683
15688
  pid = parent;
15684
15689
  }
@@ -15770,7 +15775,7 @@ var init_current_sim = __esm({
15770
15775
  "VSCODE_INJECTION"
15771
15776
  // vscode integrated terminal
15772
15777
  ];
15773
- IMMORTAL_HOST_COMM_RE = /^(tmux|screen|agentbus)/i;
15778
+ IMMORTAL_HOST_COMM_RE = /^(?:tmux|screen)|^(?:agentbus|tm)$/i;
15774
15779
  }
15775
15780
  });
15776
15781
 
@@ -16221,7 +16226,8 @@ function getFramedScreenshotLayout(model) {
16221
16226
  const logicalOuterHeight = logicalFrameHeight + FRAME_OUTLINE_BLEED * 2;
16222
16227
  const logicalScreenLeft = logicalFrameLeft + (isLegacyHardware ? import_chrome_metrics.LEGACY_SIDE_BEZEL : spec.bezelWidth);
16223
16228
  const logicalScreenTop = isLegacyHardware ? import_chrome_metrics.LEGACY_TOP_BEZEL : spec.bezelWidth;
16224
- const logicalFrameRadius = isLegacyHardware ? import_chrome_metrics.LEGACY_FRAME_RADIUS : spec.cornerRadius + spec.bezelWidth;
16229
+ const corners = (0, import_settings.resolveDeviceFrameCorners)(spec);
16230
+ const logicalFrameRadius = isLegacyHardware ? import_chrome_metrics.LEGACY_FRAME_RADIUS : corners.frameRadius;
16225
16231
  const buttons = [
16226
16232
  {
16227
16233
  side: "right",
@@ -16263,7 +16269,7 @@ function getFramedScreenshotLayout(model) {
16263
16269
  logicalScreenHeight,
16264
16270
  logicalScreenLeft,
16265
16271
  logicalScreenTop,
16266
- logicalScreenRadius: isLegacyHardware ? 0 : spec.cornerRadius,
16272
+ logicalScreenRadius: isLegacyHardware ? 0 : corners.screenRadius,
16267
16273
  logicalFrameRadius,
16268
16274
  frameBackground: isLegacyHardware ? "linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)" : "#000000",
16269
16275
  frameOutline: isLegacyHardware ? "0 0 0 1px #1f2125" : "0 0 0 1px #333",
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.259 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.261 | (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": "sootsim",
3
- "version": "0.1.259",
3
+ "version": "0.1.261",
4
4
  "description": "sootsim CLI + vite/metro plugins + skills registry. bridge client for driving the proprietary sootsim-engine over WebSocket.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "MIT",
@@ -7,7 +7,11 @@ import {
7
7
  LEGACY_TOP_BEZEL,
8
8
  SIDE_BUTTON_RESERVE,
9
9
  } from 'sootsim-engine/ios/chrome-metrics'
10
- import { getDevice, type DeviceModel } from 'sootsim-engine/settings'
10
+ import {
11
+ getDevice,
12
+ resolveDeviceFrameCorners,
13
+ type DeviceModel,
14
+ } from 'sootsim-engine/settings'
11
15
  import { launchReapedChrome } from '../../../../scripts/lib/reap-browser'
12
16
 
13
17
  const METALLIC_RING_SHADOW =
@@ -85,9 +89,8 @@ export function getFramedScreenshotLayout(model: DeviceModel): FramedScreenshotL
85
89
  const logicalScreenLeft =
86
90
  logicalFrameLeft + (isLegacyHardware ? LEGACY_SIDE_BEZEL : spec.bezelWidth)
87
91
  const logicalScreenTop = isLegacyHardware ? LEGACY_TOP_BEZEL : spec.bezelWidth
88
- const logicalFrameRadius = isLegacyHardware
89
- ? LEGACY_FRAME_RADIUS
90
- : spec.cornerRadius + spec.bezelWidth
92
+ const corners = resolveDeviceFrameCorners(spec)
93
+ const logicalFrameRadius = isLegacyHardware ? LEGACY_FRAME_RADIUS : corners.frameRadius
91
94
  const buttons: FrameButtonLayout[] = [
92
95
  {
93
96
  side: 'right',
@@ -130,7 +133,7 @@ export function getFramedScreenshotLayout(model: DeviceModel): FramedScreenshotL
130
133
  logicalScreenHeight,
131
134
  logicalScreenLeft,
132
135
  logicalScreenTop,
133
- logicalScreenRadius: isLegacyHardware ? 0 : spec.cornerRadius,
136
+ logicalScreenRadius: isLegacyHardware ? 0 : corners.screenRadius,
134
137
  logicalFrameRadius,
135
138
  frameBackground: isLegacyHardware
136
139
  ? 'linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)'
@@ -13,6 +13,7 @@ import { createRequire } from 'module'
13
13
  import path from 'path'
14
14
  import { fileURLToPath } from 'url'
15
15
  import { type Plugin, transformWithOxc } from 'vite'
16
+ import { resolveExportsHiddenSubpath } from '../../compat/src/resolve-hidden-subpath.ts'
16
17
  import {
17
18
  SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES,
18
19
  SOOTSIM_HAPTIC_FEEDBACK_TOUCHABLE_SOURCE,
@@ -187,27 +188,13 @@ const compatWrapperRealPackageAliases: Array<{
187
188
  for (const { specifier, packageName } of Object.values(
188
189
  SOOTSIM_COMPAT_WRAPPER_REAL_PACKAGES,
189
190
  )) {
190
- let replacement: string | undefined
191
- try {
192
- replacement = sootsimPluginRequire.resolve(packageName)
193
- } catch {
194
- // expo sdk 57 added `exports` maps that do not expose `./src/*`, so a deep
195
- // specifier like `expo-contacts/src/index.ts` throws
196
- // ERR_PACKAGE_PATH_NOT_EXPORTED even though the file exists. package.json is
197
- // always exported — resolve through it and rejoin the remainder.
198
- const scoped = packageName.startsWith('@')
199
- const cut = packageName.indexOf('/', scoped ? packageName.indexOf('/') + 1 : 0)
200
- if (cut > 0) {
201
- const pkg = packageName.slice(0, cut)
202
- const rest = packageName.slice(cut + 1)
203
- try {
204
- const joined = path.join(
205
- path.dirname(sootsimPluginRequire.resolve(`${pkg}/package.json`)),
206
- rest,
207
- )
208
- if (fs.existsSync(joined)) replacement = joined
209
- } catch {}
210
- }
191
+ let replacement = resolveExportsHiddenSubpath(packageName, (specifier) =>
192
+ sootsimPluginRequire.resolve(specifier),
193
+ )
194
+ if (!replacement) {
195
+ try {
196
+ replacement = sootsimPluginRequire.resolve(packageName)
197
+ } catch {}
211
198
  }
212
199
  if (!replacement) {
213
200
  // a dropped alias only surfaces much later as an opaque
@@ -706,6 +693,16 @@ function sootsimConfigPlugin(appDir: string, extraSources: string[]): Plugin {
706
693
  'process.env.NODE_ENV': JSON.stringify(mode),
707
694
  'process.env.TEST_NATIVE_PLATFORM': JSON.stringify(''),
708
695
  'process.env.TAMAGUI_TARGET': JSON.stringify('native'),
696
+ // expo sdk 57's winter runtime (expo/src/winter/runtime.native.ts)
697
+ // replaces globalThis.fetch with a native implementation whose
698
+ // Response class extends ExpoFetchModule.NativeResponse. that native
699
+ // module does not exist in a browser, so constructing any response
700
+ // throws `this.addListener is not a function` and every request the
701
+ // app makes fails. upstream's own web build keeps the platform fetch
702
+ // (src/winter/fetch/fetch.web.ts is `globalThis.fetch`), and this is
703
+ // upstream's supported switch for that — it removes the native fetch
704
+ // install, leaving the browser's streaming fetch in place.
705
+ 'process.env.EXPO_PUBLIC_USE_RN_FETCH': JSON.stringify('1'),
709
706
  global: 'globalThis',
710
707
  },
711
708
  optimizeDeps: {
@@ -1,86 +0,0 @@
1
- // custom Jest environment for running detox tests against sootsim
2
- // provides global device, element, by, expect (detox globals)
3
- // auto-launches sootsim browser in setup, tears down in teardown
4
-
5
- import * as fs from 'fs'
6
- import * as path from 'path'
7
- import { fileURLToPath } from 'url'
8
- import NodeEnvironment from 'jest-environment-node'
9
- import type { JestEnvironmentConfig, EnvironmentContext } from '@jest/environment'
10
-
11
- const __dirname = path.dirname(fileURLToPath(import.meta.url))
12
-
13
- interface DetoxDevice {
14
- terminateApp?(): Promise<void>
15
- takeScreenshot?(name: string): Promise<string>
16
- }
17
-
18
- export default class SootSimDetoxEnvironment extends NodeEnvironment {
19
- private screenshotDir: string
20
-
21
- constructor(config: JestEnvironmentConfig, context: EnvironmentContext) {
22
- super(config, context)
23
- this.screenshotDir =
24
- process.env.SOOTSIM_SCREENSHOT_DIR ||
25
- path.join(process.cwd(), 'test', 'detox-driver', 'screenshots')
26
- }
27
-
28
- async setup() {
29
- await super.setup()
30
-
31
- // dynamically import the detox driver — it manages browser lifecycle
32
- const driverPath = path.resolve(__dirname, 'index.ts')
33
- const driver = await import(driverPath)
34
-
35
- // expose detox globals
36
- this.global.by = driver.by
37
- this.global.element = driver.element
38
- this.global.expect = driver.expect
39
- this.global.waitFor = driver.waitFor
40
- this.global.device = driver.device
41
-
42
- // ensure screenshot dir exists
43
- fs.mkdirSync(this.screenshotDir, { recursive: true })
44
- }
45
-
46
- async teardown() {
47
- // device.terminateApp will close the browser
48
- try {
49
- const device = this.global.device as DetoxDevice | undefined
50
- if (device?.terminateApp) {
51
- await device.terminateApp()
52
- }
53
- } catch {}
54
-
55
- await super.teardown()
56
- }
57
-
58
- async handleTestEvent(event: any, state: any) {
59
- // capture screenshot on test failure
60
- if (event.name === 'test_fn_failure' || event.name === 'test_done') {
61
- const testFailed =
62
- event.name === 'test_fn_failure' ||
63
- (event.test && event.test.errors && event.test.errors.length > 0)
64
-
65
- if (testFailed) {
66
- try {
67
- const testName =
68
- state?.currentlyRunningTest?.name || event.test?.name || 'unknown'
69
- const safeName = testName.replace(/[^a-zA-Z0-9-_]/g, '_').slice(0, 80)
70
- const screenshotPath = path.join(this.screenshotDir, `failure-${safeName}.png`)
71
-
72
- const device = this.global.device as DetoxDevice | undefined
73
- if (device?.takeScreenshot) {
74
- const capturedPath = await device.takeScreenshot(`failure-${safeName}`)
75
- if (capturedPath !== screenshotPath) {
76
- fs.copyFileSync(capturedPath, screenshotPath)
77
- }
78
- console.log(` failure screenshot: ${screenshotPath}`)
79
- }
80
- } catch {
81
- // screenshot capture failed, non-fatal
82
- }
83
- }
84
- }
85
- }
86
- }