execbro 1.11.1 → 2.1.0

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 (302) hide show
  1. package/README.md +4 -4
  2. package/build/__tests__/unit/appContext.test.d.ts +2 -0
  3. package/build/__tests__/unit/appContext.test.d.ts.map +1 -0
  4. package/build/__tests__/unit/appContext.test.js +70 -0
  5. package/build/__tests__/unit/appContext.test.js.map +1 -0
  6. package/build/__tests__/unit/appRequest.test.d.ts +2 -0
  7. package/build/__tests__/unit/appRequest.test.d.ts.map +1 -0
  8. package/build/__tests__/unit/appRequest.test.js +179 -0
  9. package/build/__tests__/unit/appRequest.test.js.map +1 -0
  10. package/build/__tests__/unit/contextWiring.test.d.ts +2 -0
  11. package/build/__tests__/unit/contextWiring.test.d.ts.map +1 -0
  12. package/build/__tests__/unit/contextWiring.test.js +28 -0
  13. package/build/__tests__/unit/contextWiring.test.js.map +1 -0
  14. package/build/__tests__/unit/coordinateMiss.test.d.ts +2 -0
  15. package/build/__tests__/unit/coordinateMiss.test.d.ts.map +1 -0
  16. package/build/__tests__/unit/coordinateMiss.test.js +111 -0
  17. package/build/__tests__/unit/coordinateMiss.test.js.map +1 -0
  18. package/build/__tests__/unit/deviceResolverStaleRetry.test.d.ts +2 -0
  19. package/build/__tests__/unit/deviceResolverStaleRetry.test.d.ts.map +1 -0
  20. package/build/__tests__/unit/deviceResolverStaleRetry.test.js +69 -0
  21. package/build/__tests__/unit/deviceResolverStaleRetry.test.js.map +1 -0
  22. package/build/__tests__/unit/epochRender.test.d.ts +2 -0
  23. package/build/__tests__/unit/epochRender.test.d.ts.map +1 -0
  24. package/build/__tests__/unit/epochRender.test.js +60 -0
  25. package/build/__tests__/unit/epochRender.test.js.map +1 -0
  26. package/build/__tests__/unit/executeBudget.test.d.ts +2 -0
  27. package/build/__tests__/unit/executeBudget.test.d.ts.map +1 -0
  28. package/build/__tests__/unit/executeBudget.test.js +27 -0
  29. package/build/__tests__/unit/executeBudget.test.js.map +1 -0
  30. package/build/__tests__/unit/executor.test.js +48 -6
  31. package/build/__tests__/unit/executor.test.js.map +1 -1
  32. package/build/__tests__/unit/findElementTreeReuse.test.d.ts +2 -0
  33. package/build/__tests__/unit/findElementTreeReuse.test.d.ts.map +1 -0
  34. package/build/__tests__/unit/findElementTreeReuse.test.js +77 -0
  35. package/build/__tests__/unit/findElementTreeReuse.test.js.map +1 -0
  36. package/build/__tests__/unit/getLogsEmptyContract.test.js +4 -3
  37. package/build/__tests__/unit/getLogsEmptyContract.test.js.map +1 -1
  38. package/build/__tests__/unit/getLogsNativeSource.test.js +7 -8
  39. package/build/__tests__/unit/getLogsNativeSource.test.js.map +1 -1
  40. package/build/__tests__/unit/inspectorHarvest.test.js +1 -21
  41. package/build/__tests__/unit/inspectorHarvest.test.js.map +1 -1
  42. package/build/__tests__/unit/inspectorSource.test.js +1 -38
  43. package/build/__tests__/unit/inspectorSource.test.js.map +1 -1
  44. package/build/__tests__/unit/jsLogEvents.test.js +1 -0
  45. package/build/__tests__/unit/jsLogEvents.test.js.map +1 -1
  46. package/build/__tests__/unit/logBufferEpoch.test.d.ts +2 -0
  47. package/build/__tests__/unit/logBufferEpoch.test.d.ts.map +1 -0
  48. package/build/__tests__/unit/logBufferEpoch.test.js +63 -0
  49. package/build/__tests__/unit/logBufferEpoch.test.js.map +1 -0
  50. package/build/__tests__/unit/metro.test.js +18 -1
  51. package/build/__tests__/unit/metro.test.js.map +1 -1
  52. package/build/__tests__/unit/moduleRegistry.test.d.ts +2 -0
  53. package/build/__tests__/unit/moduleRegistry.test.d.ts.map +1 -0
  54. package/build/__tests__/unit/moduleRegistry.test.js +62 -0
  55. package/build/__tests__/unit/moduleRegistry.test.js.map +1 -0
  56. package/build/__tests__/unit/navigateVerify.test.d.ts +2 -0
  57. package/build/__tests__/unit/navigateVerify.test.d.ts.map +1 -0
  58. package/build/__tests__/unit/navigateVerify.test.js +30 -0
  59. package/build/__tests__/unit/navigateVerify.test.js.map +1 -0
  60. package/build/__tests__/unit/navigation.test.d.ts +2 -0
  61. package/build/__tests__/unit/navigation.test.d.ts.map +1 -0
  62. package/build/__tests__/unit/navigation.test.js +254 -0
  63. package/build/__tests__/unit/navigation.test.js.map +1 -0
  64. package/build/__tests__/unit/network.test.js +1 -0
  65. package/build/__tests__/unit/network.test.js.map +1 -1
  66. package/build/__tests__/unit/networkBufferEpoch.test.d.ts +2 -0
  67. package/build/__tests__/unit/networkBufferEpoch.test.d.ts.map +1 -0
  68. package/build/__tests__/unit/networkBufferEpoch.test.js +52 -0
  69. package/build/__tests__/unit/networkBufferEpoch.test.js.map +1 -0
  70. package/build/__tests__/unit/networkInterceptor.test.js +7 -7
  71. package/build/__tests__/unit/networkInterceptor.test.js.map +1 -1
  72. package/build/__tests__/unit/promiseHandles.test.d.ts +2 -0
  73. package/build/__tests__/unit/promiseHandles.test.d.ts.map +1 -0
  74. package/build/__tests__/unit/promiseHandles.test.js +61 -0
  75. package/build/__tests__/unit/promiseHandles.test.js.map +1 -0
  76. package/build/__tests__/unit/resolveBufferOffline.test.d.ts +2 -0
  77. package/build/__tests__/unit/resolveBufferOffline.test.d.ts.map +1 -0
  78. package/build/__tests__/unit/resolveBufferOffline.test.js +25 -0
  79. package/build/__tests__/unit/resolveBufferOffline.test.js.map +1 -0
  80. package/build/__tests__/unit/sdkMirrorPoller.test.d.ts +2 -0
  81. package/build/__tests__/unit/sdkMirrorPoller.test.d.ts.map +1 -0
  82. package/build/__tests__/unit/sdkMirrorPoller.test.js +118 -0
  83. package/build/__tests__/unit/sdkMirrorPoller.test.js.map +1 -0
  84. package/build/__tests__/unit/sessionEpoch.test.d.ts +2 -0
  85. package/build/__tests__/unit/sessionEpoch.test.d.ts.map +1 -0
  86. package/build/__tests__/unit/sessionEpoch.test.js +41 -0
  87. package/build/__tests__/unit/sessionEpoch.test.js.map +1 -0
  88. package/build/__tests__/unit/settleAndDiff.test.d.ts +2 -0
  89. package/build/__tests__/unit/settleAndDiff.test.d.ts.map +1 -0
  90. package/build/__tests__/unit/settleAndDiff.test.js +110 -0
  91. package/build/__tests__/unit/settleAndDiff.test.js.map +1 -0
  92. package/build/__tests__/unit/truncate.test.d.ts +2 -0
  93. package/build/__tests__/unit/truncate.test.d.ts.map +1 -0
  94. package/build/__tests__/unit/truncate.test.js +58 -0
  95. package/build/__tests__/unit/truncate.test.js.map +1 -0
  96. package/build/__tests__/unit/verifyAction.test.js +2 -1
  97. package/build/__tests__/unit/verifyAction.test.js.map +1 -1
  98. package/build/__tests__/unit/waitForMeasurements.test.d.ts +2 -0
  99. package/build/__tests__/unit/waitForMeasurements.test.d.ts.map +1 -0
  100. package/build/__tests__/unit/waitForMeasurements.test.js +69 -0
  101. package/build/__tests__/unit/waitForMeasurements.test.js.map +1 -0
  102. package/build/core/android.d.ts +3 -1
  103. package/build/core/android.d.ts.map +1 -1
  104. package/build/core/android.js +5 -5
  105. package/build/core/android.js.map +1 -1
  106. package/build/core/appContext.d.ts +53 -0
  107. package/build/core/appContext.d.ts.map +1 -0
  108. package/build/core/appContext.js +172 -0
  109. package/build/core/appContext.js.map +1 -0
  110. package/build/core/appRequest.d.ts +21 -0
  111. package/build/core/appRequest.d.ts.map +1 -0
  112. package/build/core/appRequest.js +95 -0
  113. package/build/core/appRequest.js.map +1 -0
  114. package/build/core/bufferConfig.d.ts +5 -0
  115. package/build/core/bufferConfig.d.ts.map +1 -0
  116. package/build/core/bufferConfig.js +20 -0
  117. package/build/core/bufferConfig.js.map +1 -0
  118. package/build/core/connection.d.ts.map +1 -1
  119. package/build/core/connection.js +29 -9
  120. package/build/core/connection.js.map +1 -1
  121. package/build/core/debugGlobals.d.ts.map +1 -1
  122. package/build/core/debugGlobals.js +13 -0
  123. package/build/core/debugGlobals.js.map +1 -1
  124. package/build/core/deviceDiscovery.d.ts +5 -1
  125. package/build/core/deviceDiscovery.d.ts.map +1 -1
  126. package/build/core/deviceDiscovery.js +13 -2
  127. package/build/core/deviceDiscovery.js.map +1 -1
  128. package/build/core/deviceResolver.d.ts.map +1 -1
  129. package/build/core/deviceResolver.js +17 -2
  130. package/build/core/deviceResolver.js.map +1 -1
  131. package/build/core/epochRender.d.ts +19 -0
  132. package/build/core/epochRender.d.ts.map +1 -0
  133. package/build/core/epochRender.js +38 -0
  134. package/build/core/epochRender.js.map +1 -0
  135. package/build/core/guides.d.ts.map +1 -1
  136. package/build/core/guides.js +36 -91
  137. package/build/core/guides.js.map +1 -1
  138. package/build/core/index.d.ts +2 -3
  139. package/build/core/index.d.ts.map +1 -1
  140. package/build/core/index.js +4 -4
  141. package/build/core/index.js.map +1 -1
  142. package/build/core/inspector.d.ts +0 -39
  143. package/build/core/inspector.d.ts.map +1 -1
  144. package/build/core/inspector.js +1 -358
  145. package/build/core/inspector.js.map +1 -1
  146. package/build/core/ios.d.ts +14 -3
  147. package/build/core/ios.d.ts.map +1 -1
  148. package/build/core/ios.js +41 -17
  149. package/build/core/ios.js.map +1 -1
  150. package/build/core/jsExecute.d.ts +15 -0
  151. package/build/core/jsExecute.d.ts.map +1 -1
  152. package/build/core/jsExecute.js +136 -29
  153. package/build/core/jsExecute.js.map +1 -1
  154. package/build/core/logs.d.ts +12 -3
  155. package/build/core/logs.d.ts.map +1 -1
  156. package/build/core/logs.js +28 -5
  157. package/build/core/logs.js.map +1 -1
  158. package/build/core/metro.d.ts +2 -0
  159. package/build/core/metro.d.ts.map +1 -1
  160. package/build/core/metro.js +16 -8
  161. package/build/core/metro.js.map +1 -1
  162. package/build/core/moduleRegistry.d.ts +19 -0
  163. package/build/core/moduleRegistry.d.ts.map +1 -0
  164. package/build/core/moduleRegistry.js +67 -0
  165. package/build/core/moduleRegistry.js.map +1 -0
  166. package/build/core/nativeOnlyHints.d.ts.map +1 -1
  167. package/build/core/nativeOnlyHints.js +0 -2
  168. package/build/core/nativeOnlyHints.js.map +1 -1
  169. package/build/core/navigate.d.ts +46 -0
  170. package/build/core/navigate.d.ts.map +1 -0
  171. package/build/core/navigate.js +119 -0
  172. package/build/core/navigate.js.map +1 -0
  173. package/build/core/navigation.d.ts +66 -0
  174. package/build/core/navigation.d.ts.map +1 -0
  175. package/build/core/navigation.js +269 -0
  176. package/build/core/navigation.js.map +1 -0
  177. package/build/core/network.d.ts +12 -2
  178. package/build/core/network.d.ts.map +1 -1
  179. package/build/core/network.js +52 -12
  180. package/build/core/network.js.map +1 -1
  181. package/build/core/networkInterceptor.d.ts +1 -1
  182. package/build/core/networkInterceptor.d.ts.map +1 -1
  183. package/build/core/networkInterceptor.js +3 -2
  184. package/build/core/networkInterceptor.js.map +1 -1
  185. package/build/core/pressables.d.ts +33 -0
  186. package/build/core/pressables.d.ts.map +1 -1
  187. package/build/core/pressables.js +73 -4
  188. package/build/core/pressables.js.map +1 -1
  189. package/build/core/promiseHandles.d.ts +19 -0
  190. package/build/core/promiseHandles.d.ts.map +1 -0
  191. package/build/core/promiseHandles.js +58 -0
  192. package/build/core/promiseHandles.js.map +1 -0
  193. package/build/core/register.d.ts.map +1 -1
  194. package/build/core/register.js +1 -4
  195. package/build/core/register.js.map +1 -1
  196. package/build/core/sdkMirrorPoller.d.ts +31 -0
  197. package/build/core/sdkMirrorPoller.d.ts.map +1 -0
  198. package/build/core/sdkMirrorPoller.js +210 -0
  199. package/build/core/sdkMirrorPoller.js.map +1 -0
  200. package/build/core/state.d.ts +14 -0
  201. package/build/core/state.d.ts.map +1 -1
  202. package/build/core/state.js +48 -2
  203. package/build/core/state.js.map +1 -1
  204. package/build/core/toolHelpers.d.ts.map +1 -1
  205. package/build/core/toolHelpers.js +42 -10
  206. package/build/core/toolHelpers.js.map +1 -1
  207. package/build/core/truncate.d.ts +42 -0
  208. package/build/core/truncate.d.ts.map +1 -0
  209. package/build/core/truncate.js +169 -0
  210. package/build/core/truncate.js.map +1 -0
  211. package/build/core/types.d.ts +3 -0
  212. package/build/core/types.d.ts.map +1 -1
  213. package/build/index.d.ts.map +1 -1
  214. package/build/index.js +4 -2
  215. package/build/index.js.map +1 -1
  216. package/build/pro/coordinateMiss.d.ts +55 -0
  217. package/build/pro/coordinateMiss.d.ts.map +1 -0
  218. package/build/pro/coordinateMiss.js +122 -0
  219. package/build/pro/coordinateMiss.js.map +1 -0
  220. package/build/pro/tap.d.ts +8 -0
  221. package/build/pro/tap.d.ts.map +1 -1
  222. package/build/pro/tap.js +99 -11
  223. package/build/pro/tap.js.map +1 -1
  224. package/build/pro/verifyAction.d.ts +43 -2
  225. package/build/pro/verifyAction.d.ts.map +1 -1
  226. package/build/pro/verifyAction.js +95 -36
  227. package/build/pro/verifyAction.js.map +1 -1
  228. package/build/tools/_deviceArg.d.ts +17 -1
  229. package/build/tools/_deviceArg.d.ts.map +1 -1
  230. package/build/tools/_deviceArg.js +17 -1
  231. package/build/tools/_deviceArg.js.map +1 -1
  232. package/build/tools/bundleTools.d.ts.map +1 -1
  233. package/build/tools/bundleTools.js +20 -33
  234. package/build/tools/bundleTools.js.map +1 -1
  235. package/build/tools/componentTools.d.ts.map +1 -1
  236. package/build/tools/componentTools.js +41 -219
  237. package/build/tools/componentTools.js.map +1 -1
  238. package/build/tools/connectionTools.d.ts.map +1 -1
  239. package/build/tools/connectionTools.js +17 -22
  240. package/build/tools/connectionTools.js.map +1 -1
  241. package/build/tools/deviceTools.d.ts.map +1 -1
  242. package/build/tools/deviceTools.js +13 -167
  243. package/build/tools/deviceTools.js.map +1 -1
  244. package/build/tools/executionTools.d.ts.map +1 -1
  245. package/build/tools/executionTools.js +63 -18
  246. package/build/tools/executionTools.js.map +1 -1
  247. package/build/tools/interactionTools.d.ts +6 -0
  248. package/build/tools/interactionTools.d.ts.map +1 -1
  249. package/build/tools/interactionTools.js +41 -56
  250. package/build/tools/interactionTools.js.map +1 -1
  251. package/build/tools/logTools.d.ts.map +1 -1
  252. package/build/tools/logTools.js +61 -80
  253. package/build/tools/logTools.js.map +1 -1
  254. package/build/tools/metaTools.js +1 -1
  255. package/build/tools/metaTools.js.map +1 -1
  256. package/build/tools/navigationTools.d.ts +3 -0
  257. package/build/tools/navigationTools.d.ts.map +1 -0
  258. package/build/tools/navigationTools.js +60 -0
  259. package/build/tools/navigationTools.js.map +1 -0
  260. package/build/tools/networkTools.d.ts.map +1 -1
  261. package/build/tools/networkTools.js +44 -202
  262. package/build/tools/networkTools.js.map +1 -1
  263. package/build/tools/reduxTools.d.ts.map +1 -1
  264. package/build/tools/reduxTools.js +3 -2
  265. package/build/tools/reduxTools.js.map +1 -1
  266. package/build/tools/requestTools.d.ts +3 -0
  267. package/build/tools/requestTools.d.ts.map +1 -0
  268. package/build/tools/requestTools.js +79 -0
  269. package/build/tools/requestTools.js.map +1 -0
  270. package/build/tools/screenshotTools.d.ts.map +1 -1
  271. package/build/tools/screenshotTools.js +42 -25
  272. package/build/tools/screenshotTools.js.map +1 -1
  273. package/package.json +1 -1
  274. package/tools.json +22 -78
  275. package/build/__tests__/unit/flowpoints.test.d.ts +0 -2
  276. package/build/__tests__/unit/flowpoints.test.d.ts.map +0 -1
  277. package/build/__tests__/unit/flowpoints.test.js +0 -126
  278. package/build/__tests__/unit/flowpoints.test.js.map +0 -1
  279. package/build/__tests__/unit/flowpointsQuery.test.d.ts +0 -2
  280. package/build/__tests__/unit/flowpointsQuery.test.d.ts.map +0 -1
  281. package/build/__tests__/unit/flowpointsQuery.test.js +0 -91
  282. package/build/__tests__/unit/flowpointsQuery.test.js.map +0 -1
  283. package/build/__tests__/unit/selectionPoller.test.d.ts +0 -2
  284. package/build/__tests__/unit/selectionPoller.test.d.ts.map +0 -1
  285. package/build/__tests__/unit/selectionPoller.test.js +0 -109
  286. package/build/__tests__/unit/selectionPoller.test.js.map +0 -1
  287. package/build/__tests__/unit/verifyFlow.test.d.ts +0 -2
  288. package/build/__tests__/unit/verifyFlow.test.d.ts.map +0 -1
  289. package/build/__tests__/unit/verifyFlow.test.js +0 -45
  290. package/build/__tests__/unit/verifyFlow.test.js.map +0 -1
  291. package/build/core/selectionPoller.d.ts +0 -13
  292. package/build/core/selectionPoller.d.ts.map +0 -1
  293. package/build/core/selectionPoller.js +0 -102
  294. package/build/core/selectionPoller.js.map +0 -1
  295. package/build/pro/flowpointTools.d.ts +0 -4
  296. package/build/pro/flowpointTools.d.ts.map +0 -1
  297. package/build/pro/flowpointTools.js +0 -266
  298. package/build/pro/flowpointTools.js.map +0 -1
  299. package/build/pro/flowpoints.d.ts +0 -86
  300. package/build/pro/flowpoints.d.ts.map +0 -1
  301. package/build/pro/flowpoints.js +0 -283
  302. package/build/pro/flowpoints.js.map +0 -1
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # ExecBro
2
2
 
3
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.igorzheludkov%2Fexecbro-6E56CF)](https://registry.modelcontextprotocol.io/?q=io.github.igorzheludkov%2Fexecbro)
4
+
3
5
  **Give your AI assistant eyes and hands into your running React Native app.** Like Chrome DevTools — but for AI agents.
4
6
 
5
7
  Build, debug, and verify features end-to-end — without leaving the chat.
@@ -42,7 +44,7 @@ Linking your installation here is also **required to unlock [ExecBro Pro](#prici
42
44
  - **Android Devices** - Screenshots, app install/launch, package management (via ADB)
43
45
  - **Unified Tap** - Single `tap` tool with automatic fallback chain: fiber tree → accessibility → OCR → coordinates. Auto-detects platform, accepts pixels from screenshots. Returns post-tap screenshot and verifies visual change by default
44
46
  - **Unified Swipe** - Single `swipe` tool that auto-routes to iOS or Android based on the connected device. Accepts screenshot pixel coordinates, handles per-platform conversion, and returns a `verification.meaningful` signal so agents detect end-of-list, non-scrollable surfaces, and missed coordinates. Essential for scrolling virtualized lists (FlatList/SectionList) where off-screen items aren't in the fiber tree
45
- - **UI Automation** - Swipe, long press, key events, and text input on both platforms. On Bridgeless/Fabric apps, `clear_focused_input` and `dismiss_keyboard` operate on whatever has focus, and `ios_input_text` / `android_input_text` accept `replace:true` to overwrite pre-filled values — all three update React state through `onChangeText` so controlled components (Formik, react-hook-form, useState) stay consistent
47
+ - **UI Automation** - Swipe, long press, key events, and text input on both platforms. On Bridgeless/Fabric apps, `dismiss_keyboard` operates on whatever has focus, and `ios_input_text` / `android_input_text` accept `replace:true` to overwrite pre-filled values — updating React state through `onChangeText` so controlled components (Formik, react-hook-form, useState) stay consistent
46
48
  - **Accessibility Inspection** - Query UI hierarchy to find elements by text, label, or resource ID
47
49
  - **OCR Text Extraction** - Extract visible text with tap-ready coordinates via Google Cloud Vision (works on any screen content)
48
50
 
@@ -108,11 +110,9 @@ See the [full tool reference](docs/tools.md) for all tools with descriptions. Ke
108
110
  | `scan_metro` | **Start here** — scan for Metro servers and auto-connect |
109
111
  | `get_logs` / `search_logs` | Capture and search console logs with filtering and summaries |
110
112
  | `get_network_requests` | Monitor HTTP requests with method/status filtering |
111
- | `get_flowpoints` / `verify_flow` | Flow tracing + factual verification: query, wait on, and assert `flowpoint()` breadcrumbs (SDK) |
112
113
  | `get_screen_layout` | Screen map of visible components with positions, sizes, and text content |
113
114
  | `tap` | **Unified tap** — auto-detects platform, tries fiber → accessibility → OCR → coordinates |
114
115
  | `ios_input_text` / `android_input_text` | Type text into the focused field. `replace:true` clears pre-filled values first (Fabric) |
115
- | `clear_focused_input` | Clear the focused TextInput via React `onChangeText`, keeping controlled state in sync |
116
116
  | `dismiss_keyboard` | Blur the focused input and close the on-screen keyboard |
117
117
  | `execute_in_app` | Run JS expressions in the app runtime (REPL-style) |
118
118
  | `ios_screenshot` / `android_screenshot` | Take device screenshots |
@@ -145,7 +145,7 @@ See the [full tool reference](docs/tools.md) for all tools with descriptions. Ke
145
145
  The list won't scroll — scroll it down and check what's going on
146
146
  ```
147
147
  ```
148
- Instrument the checkout flow with flowpoints, run it, and verify the steps fire in order
148
+ Why does this button look wrong — what component renders it and where?
149
149
  ```
150
150
 
151
151
  The agent connects to Metro, reads logs and network, inspects the screen, and drives the UI as needed to answer.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=appContext.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appContext.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/appContext.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { buildContextPreamble, CONTEXT_BINDINGS } from "../../core/appContext.js";
3
+ describe("buildContextPreamble", () => {
4
+ const source = buildContextPreamble();
5
+ function evaluateWith(globalStub, expr) {
6
+ const run = new Function("globalThis", source + "; return (" + expr + ");");
7
+ return run(globalStub);
8
+ }
9
+ it("emits Hermes-compatible ES5 only", () => {
10
+ expect(source).not.toMatch(/\bconst\b|\blet\b/);
11
+ expect(source).not.toMatch(/=>/);
12
+ expect(source).not.toMatch(/\basync\b/);
13
+ expect(source).not.toContain("`");
14
+ });
15
+ it("declares every advertised binding", () => {
16
+ for (const name of CONTEXT_BINDINGS) {
17
+ expect(source).toContain(name);
18
+ }
19
+ });
20
+ it("defers the expensive bindings behind functions", () => {
21
+ // cache() must not run extract() at preamble time — it costs 17ms and
22
+ // can materialise 1.6MB.
23
+ expect(source).toMatch(/function cache\(/);
24
+ });
25
+ it("resolves everything to null when nothing is available", () => {
26
+ const out = evaluateWith({}, "{ store: store, state: state, router: router, apollo: apollo }");
27
+ expect(out.store).toBeNull();
28
+ expect(out.state).toBeNull();
29
+ expect(out.router).toBeNull();
30
+ expect(out.apollo).toBeNull();
31
+ });
32
+ it("resolves a redux store from a known global when the fiber walk finds nothing", () => {
33
+ const store = {
34
+ getState: () => ({ auth: { id: 1 } }),
35
+ dispatch: () => undefined,
36
+ subscribe: () => undefined
37
+ };
38
+ const out = evaluateWith({ __REDUX_STORE__: store }, "{ store: store, state: state }");
39
+ expect(out.store).toBe(store);
40
+ expect(out.state.auth.id).toBe(1);
41
+ });
42
+ it("falls back to the SDK store registry", () => {
43
+ const store = { getState: () => ({ ok: true }), dispatch: () => undefined, subscribe: () => undefined };
44
+ const out = evaluateWith({ __RN_AI_DEVTOOLS__: { stores: { redux: store } } }, "{ store: store, state: state }");
45
+ expect(out.store).toBe(store);
46
+ expect(out.state.ok).toBe(true);
47
+ });
48
+ it("derefs an Apollo normalized reference and passes plain values through", () => {
49
+ const cacheObj = { "Entity:1": { id: "1", name: "Acme" } };
50
+ const deref = evaluateWith({}, "deref");
51
+ expect(deref({ __ref: "Entity:1" }, cacheObj)).toEqual({ id: "1", name: "Acme" });
52
+ expect(deref({ plain: true }, cacheObj)).toEqual({ plain: true });
53
+ expect(deref(null, cacheObj)).toBeNull();
54
+ });
55
+ it("summary reports per-key type and byte size, heaviest first", () => {
56
+ const summary = evaluateWith({}, "summary");
57
+ const rows = summary({ small: { a: 1 }, big: { pad: "x".repeat(500) } });
58
+ expect(rows[0].key).toBe("big");
59
+ expect(rows[0].type).toBe("object");
60
+ expect(rows[0].bytes).toBeGreaterThan(rows[1].bytes);
61
+ });
62
+ it("summary survives a non-serialisable value instead of throwing", () => {
63
+ const summary = evaluateWith({}, "summary");
64
+ const cyclic = {};
65
+ cyclic.self = cyclic;
66
+ const rows = summary({ cyclic, fine: 1 });
67
+ expect(rows.find((r) => r.key === "cyclic")?.bytes).toBe(-1);
68
+ });
69
+ });
70
+ //# sourceMappingURL=appContext.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appContext.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/appContext.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=appRequest.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appRequest.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/appRequest.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,179 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { buildRequestExpression } from "../../core/appRequest.js";
3
+ describe("buildRequestExpression", () => {
4
+ it("emits Hermes-compatible ES5 only", () => {
5
+ const src = buildRequestExpression({ method: "GET", url: "https://example.com/x" });
6
+ expect(src).not.toMatch(/=>|\bconst\b|\blet\b|\basync\b/);
7
+ });
8
+ it("embeds method and url safely as JSON literals", () => {
9
+ const src = buildRequestExpression({ method: "DELETE", url: "https://api.test/user/17?q=a&b=c" });
10
+ expect(src).toContain('"DELETE"');
11
+ expect(src).toContain('"https://api.test/user/17?q=a&b=c"');
12
+ });
13
+ it("upper-cases the method", () => {
14
+ const src = buildRequestExpression({ method: "post", url: "https://api.test/x" });
15
+ expect(src).toContain('"POST"');
16
+ });
17
+ it("never embeds a token — auth resolves in-app", () => {
18
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
19
+ expect(src).toContain("accessToken");
20
+ expect(src).not.toMatch(/eyJ[A-Za-z0-9_-]{10,}/);
21
+ });
22
+ it("omits the Authorization header when auth is none", () => {
23
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/public", auth: "none" });
24
+ // The response still reports an `authorized` flag, so assert on the
25
+ // header actually being set rather than on the word appearing at all.
26
+ expect(src).not.toContain("'Bearer '");
27
+ expect(src).not.toContain("accessToken");
28
+ });
29
+ it("serialises a JSON body and sets the content type", () => {
30
+ const src = buildRequestExpression({ method: "POST", url: "https://api.test/x", body: { name: "Test" } });
31
+ expect(src).toContain('"application/json"');
32
+ expect(src).toContain('{\\"name\\":\\"Test\\"}');
33
+ });
34
+ it("escapes a url containing a quote rather than breaking the expression", () => {
35
+ const src = buildRequestExpression({ method: "GET", url: 'https://api.test/a"b' });
36
+ expect(src).toContain('\\"');
37
+ // The generated source must still be parseable.
38
+ expect(() => new Function("return " + src.replace(/^\(function/, "(function"))).not.toThrow();
39
+ });
40
+ it("passes explicit headers through", () => {
41
+ const src = buildRequestExpression({
42
+ method: "GET",
43
+ url: "https://api.test/x",
44
+ headers: { "x-lang": "en" }
45
+ });
46
+ expect(src).toContain('"x-lang"');
47
+ expect(src).toContain('"en"');
48
+ });
49
+ });
50
+ describe("buildRequestExpression — unresolved auth", () => {
51
+ it("warns when auth=auto is requested (the note is emitted, gated at runtime)", () => {
52
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
53
+ expect(src).toContain("UNAUTHENTICATED");
54
+ expect(src).toContain("no captured request carried an Authorization header");
55
+ });
56
+ it("does not emit the warning when auth is explicitly none", () => {
57
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/x", auth: "none" });
58
+ expect(src).toContain("var authNote = null;");
59
+ expect(src).not.toContain("UNAUTHENTICATED");
60
+ });
61
+ });
62
+ describe("buildRequestExpression — generated source behaviour", () => {
63
+ function runGenerated(src, stateStub, globalStub = {}) {
64
+ let captured;
65
+ const fetchStub = (url, init) => {
66
+ captured = { url, init };
67
+ return Promise.resolve({
68
+ status: 200,
69
+ ok: true,
70
+ text: () => Promise.resolve(JSON.stringify({ hello: "world" }))
71
+ });
72
+ };
73
+ const run = new Function("state", "fetch", "globalThis", "return " + src + ";");
74
+ return run(stateStub, fetchStub, globalStub).then((result) => ({
75
+ captured: captured,
76
+ result
77
+ }));
78
+ }
79
+ it("sets a bearer header from state.user.accessToken", async () => {
80
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
81
+ const { captured, result } = await runGenerated(src, { user: { accessToken: "tok-123" } });
82
+ expect(captured.init.headers.Authorization).toBe("Bearer tok-123");
83
+ expect(result.authorized).toBe(true);
84
+ expect(result.authNote).toBeUndefined();
85
+ });
86
+ it("falls back to state.auth.accessToken", async () => {
87
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
88
+ const { captured } = await runGenerated(src, { auth: { accessToken: "tok-abc" } });
89
+ expect(captured.init.headers.Authorization).toBe("Bearer tok-abc");
90
+ });
91
+ it("warns and sends unauthenticated when no token is present", async () => {
92
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
93
+ const { captured, result } = await runGenerated(src, { auth: { isAuthenticated: true } });
94
+ expect(captured.init.headers.Authorization).toBeUndefined();
95
+ expect(result.authorized).toBe(false);
96
+ expect(String(result.authNote)).toContain("UNAUTHENTICATED");
97
+ });
98
+ it("lets an explicit Authorization header win over auth=auto", async () => {
99
+ const src = buildRequestExpression({
100
+ method: "GET",
101
+ url: "https://api.test/me",
102
+ auth: "auto",
103
+ headers: { Authorization: "Bearer explicit" }
104
+ });
105
+ const { captured, result } = await runGenerated(src, { user: { accessToken: "tok-123" } });
106
+ expect(captured.init.headers.Authorization).toBe("Bearer explicit");
107
+ expect(result.authNote).toBeUndefined();
108
+ });
109
+ it("sends the body and parses a JSON response", async () => {
110
+ const src = buildRequestExpression({ method: "POST", url: "https://api.test/x", body: { a: 1 }, auth: "none" });
111
+ const { captured, result } = await runGenerated(src, null);
112
+ expect(captured.init.method).toBe("POST");
113
+ expect(captured.init.body).toBe('{"a":1}');
114
+ expect(captured.init.headers["Content-Type"]).toBe("application/json");
115
+ expect(result.body).toEqual({ hello: "world" });
116
+ });
117
+ });
118
+ describe("buildRequestExpression — token from captured requests (Apollo apps)", () => {
119
+ function runWith(src, stateStub, globalStub) {
120
+ let captured;
121
+ const fetchStub = (url, init) => {
122
+ captured = { url, init };
123
+ return Promise.resolve({ status: 200, ok: true, text: () => Promise.resolve("{}") });
124
+ };
125
+ const run = new Function("state", "fetch", "globalThis", "return " + src + ";");
126
+ return run(stateStub, fetchStub, globalStub).then((result) => ({
127
+ captured: captured,
128
+ result
129
+ }));
130
+ }
131
+ const sdkWith = (headers) => ({
132
+ __RN_AI_DEVTOOLS__: {
133
+ getNetworkEntries: () => headers.map((h) => ({ requestHeaders: h }))
134
+ }
135
+ });
136
+ it("reuses the Authorization header from the most recent captured request", async () => {
137
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
138
+ const { captured, result } = await runWith(src, { auth: { isAuthenticated: true } }, sdkWith([
139
+ { Authorization: "Bearer old-token" },
140
+ { "content-type": "application/json" },
141
+ { authorization: "Bearer newest-token" }
142
+ ]));
143
+ expect(captured.init.headers.Authorization).toBe("Bearer newest-token");
144
+ expect(result.authSource).toBe("captured-request");
145
+ expect(result.authNote).toBeUndefined();
146
+ });
147
+ it("prefers redux over a captured header when both exist", async () => {
148
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
149
+ const { captured, result } = await runWith(src, { user: { accessToken: "redux-tok" } }, sdkWith([
150
+ { Authorization: "Bearer captured-tok" }
151
+ ]));
152
+ expect(captured.init.headers.Authorization).toBe("Bearer redux-tok");
153
+ expect(result.authSource).toBe("redux");
154
+ });
155
+ it("still warns when neither redux nor any captured request has a token", async () => {
156
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
157
+ const { result } = await runWith(src, null, sdkWith([{ "content-type": "application/json" }]));
158
+ expect(result.authorized).toBe(false);
159
+ expect(String(result.authNote)).toContain("UNAUTHENTICATED");
160
+ });
161
+ it("degrades quietly when the SDK is absent", async () => {
162
+ const src = buildRequestExpression({ method: "GET", url: "https://api.test/me", auth: "auto" });
163
+ const { result } = await runWith(src, null, {});
164
+ expect(result.authorized).toBe(false);
165
+ expect(String(result.authNote)).toContain("UNAUTHENTICATED");
166
+ });
167
+ it("reports an explicitly-passed header as the source", async () => {
168
+ const src = buildRequestExpression({
169
+ method: "GET",
170
+ url: "https://api.test/me",
171
+ auth: "auto",
172
+ headers: { Authorization: "Bearer explicit" }
173
+ });
174
+ const { captured, result } = await runWith(src, { user: { accessToken: "redux-tok" } }, sdkWith([]));
175
+ expect(captured.init.headers.Authorization).toBe("Bearer explicit");
176
+ expect(result.authSource).toBe("explicit");
177
+ });
178
+ });
179
+ //# sourceMappingURL=appRequest.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appRequest.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/appRequest.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=contextWiring.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextWiring.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/contextWiring.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { buildEvaluationSource } from "../../core/executor.js";
3
+ describe("buildEvaluationSource", () => {
4
+ it("puts the polyfill first, then the context, then the caller's expression", () => {
5
+ const src = buildEvaluationSource("state.auth");
6
+ expect(src.indexOf("var global =")).toBeLessThan(src.indexOf("var store ="));
7
+ expect(src.indexOf("var store =")).toBeLessThan(src.lastIndexOf("state.auth"));
8
+ expect(src.endsWith("state.auth")).toBe(true);
9
+ });
10
+ it("declares context bindings with var so the caller's expression can see them", () => {
11
+ const src = buildEvaluationSource("1");
12
+ expect(src).toContain("var store =");
13
+ expect(src).toContain("var state =");
14
+ expect(src).not.toContain("const store");
15
+ });
16
+ it("does not wrap the caller's expression", () => {
17
+ // PR #5 (merged 2026-03-02) reverted blanket IIFE wrapping: it wrapped
18
+ // without a `return`, so every result came back undefined, and tools
19
+ // building their own IIFE were double-wrapped.
20
+ const src = buildEvaluationSource("2 + 2");
21
+ expect(src).not.toContain("(function(){ 2 + 2 })()");
22
+ expect(src.endsWith("2 + 2")).toBe(true);
23
+ });
24
+ it("is stable across calls so the preamble is built once", () => {
25
+ expect(buildEvaluationSource("1")).toBe(buildEvaluationSource("1"));
26
+ });
27
+ });
28
+ //# sourceMappingURL=contextWiring.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextWiring.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/contextWiring.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QAC/E,MAAM,GAAG,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;QAC7E,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC;QAC/E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QAClF,MAAM,GAAG,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC7C,uEAAuE;QACvE,qEAAqE;QACrE,+CAA+C;QAC/C,MAAM,GAAG,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=coordinateMiss.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinateMiss.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/coordinateMiss.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,111 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { explainCoordinateMiss } from "../../pro/coordinateMiss.js";
3
+ const pressable = (over = {}) => ({
4
+ label: null,
5
+ component: null,
6
+ testID: null,
7
+ center: { x: 0, y: 0 },
8
+ bounds: { x: 0, y: 0, width: 0, height: 0 },
9
+ ...over,
10
+ });
11
+ /**
12
+ * Modelled on the real repro: an "Insufficient Balance" bottom sheet with an OK
13
+ * button, over a screen whose own buttons are covered by the sheet.
14
+ */
15
+ const sheetState = {
16
+ route: { name: "OneGiftAtATime", params: null, stack: [] },
17
+ overlays: [
18
+ {
19
+ type: "BottomSheet",
20
+ title: null,
21
+ pressables: [
22
+ pressable({
23
+ label: "OK",
24
+ component: "Button",
25
+ center: { x: 210, y: 834 },
26
+ bounds: { x: 20, y: 806, width: 380, height: 56 },
27
+ }),
28
+ ],
29
+ texts: [
30
+ {
31
+ text: "It looks like there aren't enough funds to add this gift.",
32
+ center: { x: 210, y: 734 },
33
+ bounds: { x: 41, y: 700, width: 338, height: 70 },
34
+ },
35
+ ],
36
+ },
37
+ ],
38
+ pressables: [
39
+ // Sits directly under the sheet's OK button (same band) — a tap there
40
+ // reaches OK, not this.
41
+ pressable({
42
+ label: "Proceed to Checkout",
43
+ component: "Button",
44
+ center: { x: 210, y: 838 },
45
+ bounds: { x: 20, y: 810, width: 380, height: 56 },
46
+ blockedByOverlay: true,
47
+ }),
48
+ // Higher up the screen, covered by the sheet but overlapping nothing
49
+ // reachable — the pure "you targeted something behind an overlay" case.
50
+ pressable({
51
+ label: "Clear Cart and Add New Item",
52
+ component: "Button",
53
+ center: { x: 210, y: 774 },
54
+ bounds: { x: 20, y: 746, width: 380, height: 56 },
55
+ blockedByOverlay: true,
56
+ }),
57
+ ],
58
+ texts: [],
59
+ images: [],
60
+ };
61
+ describe("explainCoordinateMiss", () => {
62
+ it("names the text it hit and points at the nearest reachable pressable", () => {
63
+ // The exact miss from the live session: 100pt above the OK button.
64
+ const d = explainCoordinateMiss({ x: 210, y: 734 }, sheetState);
65
+ expect(d).not.toBeNull();
66
+ expect(d.hit).toContain("It looks like there aren't enough funds");
67
+ expect(d.nearest?.label).toBe("OK");
68
+ expect(d.nearest?.center).toEqual({ x: 210, y: 834 });
69
+ expect(d.nearest?.direction).toBe("below");
70
+ expect(d.suggestion).toContain("(210, 834)");
71
+ });
72
+ it("says so when the point landed on something an overlay covers", () => {
73
+ // "Clear Cart and Add New Item" is visible in the screenshot but unreachable.
74
+ const d = explainCoordinateMiss({ x: 210, y: 774 }, sheetState);
75
+ expect(d.blockedByOverlay).toBe(true);
76
+ expect(d.hit).toContain("Clear Cart and Add New Item");
77
+ expect(d.hit).toContain("BottomSheet");
78
+ expect(d.suggestion).toMatch(/Dismiss the BottomSheet/);
79
+ // It must still offer the reachable alternative.
80
+ expect(d.suggestion).toContain("(210, 834)");
81
+ });
82
+ it("prefers the reachable overlay button when it overlaps a covered element", () => {
83
+ // (210,834) is inside BOTH the sheet's OK button and the covered
84
+ // "Proceed to Checkout" beneath it. The touch reaches OK, so the
85
+ // diagnosis must describe OK — not the element behind it.
86
+ const d = explainCoordinateMiss({ x: 210, y: 834 }, sheetState);
87
+ expect(d.hit).toContain("OK");
88
+ expect(d.hit).not.toContain("Proceed to Checkout");
89
+ expect(d.blockedByOverlay).toBe(false);
90
+ expect(d.suggestion).toContain("coordinates were correct");
91
+ expect(d.suggestion).toMatch(/onPress handler/);
92
+ // No "nearest" steer — the aim was fine.
93
+ expect(d.nearest).toBeUndefined();
94
+ });
95
+ it("reports empty space when the point hit nothing at all", () => {
96
+ const d = explainCoordinateMiss({ x: 5, y: 20 }, sheetState);
97
+ expect(d.hit).toBe("no element (empty space)");
98
+ expect(d.nearest?.label).toBe("OK");
99
+ });
100
+ it("converts suggested coordinates into the caller's space", () => {
101
+ // Caller works in screenshot pixels at ~2.19 px per point.
102
+ const d = explainCoordinateMiss({ x: 210, y: 734 }, sheetState, (v) => Math.round(v * 2.19));
103
+ expect(d.nearest?.center).toEqual({ x: 460, y: 1826 });
104
+ expect(d.suggestion).toContain("(460, 1826)");
105
+ });
106
+ it("returns null when the screen state carries nothing to reason about", () => {
107
+ const empty = { route: null, overlays: [], pressables: [], texts: [], images: [] };
108
+ expect(explainCoordinateMiss({ x: 1, y: 1 }, empty)).toBeNull();
109
+ });
110
+ });
111
+ //# sourceMappingURL=coordinateMiss.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinateMiss.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/coordinateMiss.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=deviceResolverStaleRetry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceResolverStaleRetry.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/deviceResolverStaleRetry.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import { describe, it, expect, jest, beforeEach } from "@jest/globals";
2
+ /**
3
+ * The device inventory cache was raised from 5s to 30s so back-to-back taps stop
4
+ * re-shelling `simctl list` / `adb devices`. That is only safe because a failed
5
+ * resolution retries once against a freshly queried inventory — these tests pin
6
+ * that contract.
7
+ */
8
+ const listAllDevices = jest.fn();
9
+ const resetDeviceDiscoveryCache = jest.fn();
10
+ jest.unstable_mockModule("../../core/deviceDiscovery.js", () => ({
11
+ listAllDevices,
12
+ resetDeviceDiscoveryCache,
13
+ }));
14
+ jest.unstable_mockModule("../../core/connection.js", () => ({
15
+ getConnectedApps: () => [],
16
+ }));
17
+ jest.unstable_mockModule("../../core/projectMemory.js", () => ({
18
+ listDevices: () => [],
19
+ recordDevice: () => undefined,
20
+ }));
21
+ const empty = {
22
+ ios: { available: true, simulators: [] },
23
+ android: { available: true, emulators: [], physical: [] },
24
+ summary: { booted: 0, total: 0 },
25
+ };
26
+ const withBootedSim = {
27
+ ios: {
28
+ available: true,
29
+ simulators: [
30
+ { name: "iPhone Air", udid: "F93612A3-0042-4BDC-855F-8CAB1BDD76C6", state: "booted", runtime: "iOS 26.0" },
31
+ ],
32
+ },
33
+ android: { available: true, emulators: [], physical: [] },
34
+ summary: { booted: 1, total: 1 },
35
+ };
36
+ const { resolveDeviceTarget } = await import("../../core/deviceResolver.js");
37
+ describe("resolveDeviceTarget stale-inventory retry", () => {
38
+ beforeEach(() => {
39
+ listAllDevices.mockReset();
40
+ resetDeviceDiscoveryCache.mockReset();
41
+ });
42
+ it("re-queries a fresh inventory when the device wasn't found", async () => {
43
+ // First pass: cached inventory is stale and has nothing. Second pass:
44
+ // the simulator that was booted moments ago shows up.
45
+ listAllDevices
46
+ .mockResolvedValueOnce(empty)
47
+ .mockResolvedValue(withBootedSim);
48
+ const result = await resolveDeviceTarget("F93612A3-0042-4BDC-855F-8CAB1BDD76C6");
49
+ expect(resetDeviceDiscoveryCache).toHaveBeenCalledTimes(1);
50
+ expect(result.ok).toBe(true);
51
+ if (result.ok)
52
+ expect(result.target.deviceName).toBe("iPhone Air");
53
+ });
54
+ it("does not pay for a refresh when resolution succeeds first time", async () => {
55
+ listAllDevices.mockResolvedValue(withBootedSim);
56
+ const result = await resolveDeviceTarget("F93612A3-0042-4BDC-855F-8CAB1BDD76C6");
57
+ expect(result.ok).toBe(true);
58
+ expect(resetDeviceDiscoveryCache).not.toHaveBeenCalled();
59
+ });
60
+ it("still reports the failure when a fresh inventory also has no match", async () => {
61
+ listAllDevices.mockResolvedValue(empty);
62
+ const result = await resolveDeviceTarget("F93612A3-0042-4BDC-855F-8CAB1BDD76C6");
63
+ expect(result.ok).toBe(false);
64
+ expect(resetDeviceDiscoveryCache).toHaveBeenCalledTimes(1);
65
+ if (!result.ok)
66
+ expect(result.error.code).toBe("DEVICE_NOT_FOUND");
67
+ });
68
+ });
69
+ //# sourceMappingURL=deviceResolverStaleRetry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceResolverStaleRetry.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/deviceResolverStaleRetry.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=epochRender.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"epochRender.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/epochRender.test.ts"],"names":[],"mappings":""}