react-native-ai-debugger 2.12.3 → 2.13.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 (266) hide show
  1. package/README.md +15 -1
  2. package/build/__tests__/unit/autoReconnectOptOut.test.js +3 -0
  3. package/build/__tests__/unit/autoReconnectOptOut.test.js.map +1 -1
  4. package/build/__tests__/unit/cdpCommand.test.d.ts +2 -0
  5. package/build/__tests__/unit/cdpCommand.test.d.ts.map +1 -0
  6. package/build/__tests__/unit/cdpCommand.test.js +84 -0
  7. package/build/__tests__/unit/cdpCommand.test.js.map +1 -0
  8. package/build/__tests__/unit/chromium.test.d.ts +2 -0
  9. package/build/__tests__/unit/chromium.test.d.ts.map +1 -0
  10. package/build/__tests__/unit/chromium.test.js +118 -0
  11. package/build/__tests__/unit/chromium.test.js.map +1 -0
  12. package/build/__tests__/unit/chromiumDevice.test.d.ts +2 -0
  13. package/build/__tests__/unit/chromiumDevice.test.d.ts.map +1 -0
  14. package/build/__tests__/unit/chromiumDevice.test.js +115 -0
  15. package/build/__tests__/unit/chromiumDevice.test.js.map +1 -0
  16. package/build/__tests__/unit/chromiumDialogAnswer.test.d.ts +2 -0
  17. package/build/__tests__/unit/chromiumDialogAnswer.test.d.ts.map +1 -0
  18. package/build/__tests__/unit/chromiumDialogAnswer.test.js +71 -0
  19. package/build/__tests__/unit/chromiumDialogAnswer.test.js.map +1 -0
  20. package/build/__tests__/unit/chromiumDialogRaces.test.d.ts +2 -0
  21. package/build/__tests__/unit/chromiumDialogRaces.test.d.ts.map +1 -0
  22. package/build/__tests__/unit/chromiumDialogRaces.test.js +100 -0
  23. package/build/__tests__/unit/chromiumDialogRaces.test.js.map +1 -0
  24. package/build/__tests__/unit/chromiumDialogs.test.d.ts +2 -0
  25. package/build/__tests__/unit/chromiumDialogs.test.d.ts.map +1 -0
  26. package/build/__tests__/unit/chromiumDialogs.test.js +167 -0
  27. package/build/__tests__/unit/chromiumDialogs.test.js.map +1 -0
  28. package/build/__tests__/unit/chromiumDiscovery.test.d.ts +2 -0
  29. package/build/__tests__/unit/chromiumDiscovery.test.d.ts.map +1 -0
  30. package/build/__tests__/unit/chromiumDiscovery.test.js +302 -0
  31. package/build/__tests__/unit/chromiumDiscovery.test.js.map +1 -0
  32. package/build/__tests__/unit/chromiumDom.test.d.ts +2 -0
  33. package/build/__tests__/unit/chromiumDom.test.d.ts.map +1 -0
  34. package/build/__tests__/unit/chromiumDom.test.js +119 -0
  35. package/build/__tests__/unit/chromiumDom.test.js.map +1 -0
  36. package/build/__tests__/unit/chromiumGate.test.d.ts +2 -0
  37. package/build/__tests__/unit/chromiumGate.test.d.ts.map +1 -0
  38. package/build/__tests__/unit/chromiumGate.test.js +149 -0
  39. package/build/__tests__/unit/chromiumGate.test.js.map +1 -0
  40. package/build/__tests__/unit/chromiumInput.test.d.ts +2 -0
  41. package/build/__tests__/unit/chromiumInput.test.d.ts.map +1 -0
  42. package/build/__tests__/unit/chromiumInput.test.js +113 -0
  43. package/build/__tests__/unit/chromiumInput.test.js.map +1 -0
  44. package/build/__tests__/unit/chromiumKeys.test.d.ts +2 -0
  45. package/build/__tests__/unit/chromiumKeys.test.d.ts.map +1 -0
  46. package/build/__tests__/unit/chromiumKeys.test.js +26 -0
  47. package/build/__tests__/unit/chromiumKeys.test.js.map +1 -0
  48. package/build/__tests__/unit/chromiumScreen.test.d.ts +2 -0
  49. package/build/__tests__/unit/chromiumScreen.test.d.ts.map +1 -0
  50. package/build/__tests__/unit/chromiumScreen.test.js +390 -0
  51. package/build/__tests__/unit/chromiumScreen.test.js.map +1 -0
  52. package/build/__tests__/unit/chromiumStaleTarget.test.d.ts +2 -0
  53. package/build/__tests__/unit/chromiumStaleTarget.test.d.ts.map +1 -0
  54. package/build/__tests__/unit/chromiumStaleTarget.test.js +26 -0
  55. package/build/__tests__/unit/chromiumStaleTarget.test.js.map +1 -0
  56. package/build/__tests__/unit/connectionGaps.test.d.ts +2 -0
  57. package/build/__tests__/unit/connectionGaps.test.d.ts.map +1 -0
  58. package/build/__tests__/unit/connectionGaps.test.js +14 -0
  59. package/build/__tests__/unit/connectionGaps.test.js.map +1 -0
  60. package/build/__tests__/unit/contextPreambleGlobals.test.d.ts +2 -0
  61. package/build/__tests__/unit/contextPreambleGlobals.test.d.ts.map +1 -0
  62. package/build/__tests__/unit/contextPreambleGlobals.test.js +25 -0
  63. package/build/__tests__/unit/contextPreambleGlobals.test.js.map +1 -0
  64. package/build/__tests__/unit/deviceResolver.test.js +9 -0
  65. package/build/__tests__/unit/deviceResolver.test.js.map +1 -1
  66. package/build/__tests__/unit/electronLaunch.test.d.ts +2 -0
  67. package/build/__tests__/unit/electronLaunch.test.d.ts.map +1 -0
  68. package/build/__tests__/unit/electronLaunch.test.js +165 -0
  69. package/build/__tests__/unit/electronLaunch.test.js.map +1 -0
  70. package/build/__tests__/unit/fiberRoots.test.d.ts +2 -0
  71. package/build/__tests__/unit/fiberRoots.test.d.ts.map +1 -0
  72. package/build/__tests__/unit/fiberRoots.test.js +95 -0
  73. package/build/__tests__/unit/fiberRoots.test.js.map +1 -0
  74. package/build/__tests__/unit/fiberRootsDrift.test.d.ts +2 -0
  75. package/build/__tests__/unit/fiberRootsDrift.test.d.ts.map +1 -0
  76. package/build/__tests__/unit/fiberRootsDrift.test.js +23 -0
  77. package/build/__tests__/unit/fiberRootsDrift.test.js.map +1 -0
  78. package/build/__tests__/unit/hostAddress.test.d.ts +2 -0
  79. package/build/__tests__/unit/hostAddress.test.d.ts.map +1 -0
  80. package/build/__tests__/unit/hostAddress.test.js +38 -0
  81. package/build/__tests__/unit/hostAddress.test.js.map +1 -0
  82. package/build/__tests__/unit/measureComponent.test.js +1 -1
  83. package/build/__tests__/unit/measureComponent.test.js.map +1 -1
  84. package/build/__tests__/unit/networkInterceptorFetchMock.test.d.ts +2 -0
  85. package/build/__tests__/unit/networkInterceptorFetchMock.test.d.ts.map +1 -0
  86. package/build/__tests__/unit/networkInterceptorFetchMock.test.js +90 -0
  87. package/build/__tests__/unit/networkInterceptorFetchMock.test.js.map +1 -0
  88. package/build/__tests__/unit/networkMockTool.test.js +12 -1
  89. package/build/__tests__/unit/networkMockTool.test.js.map +1 -1
  90. package/build/__tests__/unit/pressKeyMobile.test.d.ts +2 -0
  91. package/build/__tests__/unit/pressKeyMobile.test.d.ts.map +1 -0
  92. package/build/__tests__/unit/pressKeyMobile.test.js +63 -0
  93. package/build/__tests__/unit/pressKeyMobile.test.js.map +1 -0
  94. package/build/__tests__/unit/reloadAppAutoConnect.test.js +4 -1
  95. package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -1
  96. package/build/__tests__/unit/tapAndroidSerial.test.js +16 -0
  97. package/build/__tests__/unit/tapAndroidSerial.test.js.map +1 -1
  98. package/build/core/android.d.ts +10 -0
  99. package/build/core/android.d.ts.map +1 -1
  100. package/build/core/android.js +17 -0
  101. package/build/core/android.js.map +1 -1
  102. package/build/core/appContext.d.ts.map +1 -1
  103. package/build/core/appContext.js +11 -13
  104. package/build/core/appContext.js.map +1 -1
  105. package/build/core/appDetection.d.ts.map +1 -1
  106. package/build/core/appDetection.js +7 -4
  107. package/build/core/appDetection.js.map +1 -1
  108. package/build/core/cdpCommand.d.ts +4 -0
  109. package/build/core/cdpCommand.d.ts.map +1 -0
  110. package/build/core/cdpCommand.js +58 -0
  111. package/build/core/cdpCommand.js.map +1 -0
  112. package/build/core/chromium.d.ts +157 -0
  113. package/build/core/chromium.d.ts.map +1 -0
  114. package/build/core/chromium.js +480 -0
  115. package/build/core/chromium.js.map +1 -0
  116. package/build/core/chromiumCapabilities.d.ts +11 -0
  117. package/build/core/chromiumCapabilities.d.ts.map +1 -0
  118. package/build/core/chromiumCapabilities.js +35 -0
  119. package/build/core/chromiumCapabilities.js.map +1 -0
  120. package/build/core/chromiumDialogAnswer.d.ts +11 -0
  121. package/build/core/chromiumDialogAnswer.d.ts.map +1 -0
  122. package/build/core/chromiumDialogAnswer.js +61 -0
  123. package/build/core/chromiumDialogAnswer.js.map +1 -0
  124. package/build/core/chromiumDialogs.d.ts +46 -0
  125. package/build/core/chromiumDialogs.d.ts.map +1 -0
  126. package/build/core/chromiumDialogs.js +88 -0
  127. package/build/core/chromiumDialogs.js.map +1 -0
  128. package/build/core/chromiumScreen.d.ts +97 -0
  129. package/build/core/chromiumScreen.d.ts.map +1 -0
  130. package/build/core/chromiumScreen.js +498 -0
  131. package/build/core/chromiumScreen.js.map +1 -0
  132. package/build/core/componentSearch.d.ts.map +1 -1
  133. package/build/core/componentSearch.js +7 -26
  134. package/build/core/componentSearch.js.map +1 -1
  135. package/build/core/componentSource.d.ts.map +1 -1
  136. package/build/core/componentSource.js +3 -11
  137. package/build/core/componentSource.js.map +1 -1
  138. package/build/core/componentTree.d.ts.map +1 -1
  139. package/build/core/componentTree.js +4 -18
  140. package/build/core/componentTree.js.map +1 -1
  141. package/build/core/connection.d.ts +13 -0
  142. package/build/core/connection.d.ts.map +1 -1
  143. package/build/core/connection.js +99 -18
  144. package/build/core/connection.js.map +1 -1
  145. package/build/core/connectionState.d.ts +2 -1
  146. package/build/core/connectionState.d.ts.map +1 -1
  147. package/build/core/connectionState.js +3 -0
  148. package/build/core/connectionState.js.map +1 -1
  149. package/build/core/deviceResolver.d.ts.map +1 -1
  150. package/build/core/deviceResolver.js +8 -5
  151. package/build/core/deviceResolver.js.map +1 -1
  152. package/build/core/electronLaunch.d.ts +25 -0
  153. package/build/core/electronLaunch.d.ts.map +1 -0
  154. package/build/core/electronLaunch.js +113 -0
  155. package/build/core/electronLaunch.js.map +1 -0
  156. package/build/core/errors.d.ts +1 -1
  157. package/build/core/errors.d.ts.map +1 -1
  158. package/build/core/errors.js.map +1 -1
  159. package/build/core/guides.d.ts.map +1 -1
  160. package/build/core/guides.js +9 -6
  161. package/build/core/guides.js.map +1 -1
  162. package/build/core/hostAddress.d.ts +6 -0
  163. package/build/core/hostAddress.d.ts.map +1 -0
  164. package/build/core/hostAddress.js +32 -0
  165. package/build/core/hostAddress.js.map +1 -0
  166. package/build/core/injected/fiberRoots.d.ts +2 -0
  167. package/build/core/injected/fiberRoots.d.ts.map +1 -0
  168. package/build/core/injected/fiberRoots.js +60 -0
  169. package/build/core/injected/fiberRoots.js.map +1 -0
  170. package/build/core/inputTarget.d.ts.map +1 -1
  171. package/build/core/inputTarget.js +4 -9
  172. package/build/core/inputTarget.js.map +1 -1
  173. package/build/core/inspector.d.ts.map +1 -1
  174. package/build/core/inspector.js +6 -22
  175. package/build/core/inspector.js.map +1 -1
  176. package/build/core/ios.d.ts +12 -0
  177. package/build/core/ios.d.ts.map +1 -1
  178. package/build/core/ios.js +32 -0
  179. package/build/core/ios.js.map +1 -1
  180. package/build/core/jsExecute.d.ts.map +1 -1
  181. package/build/core/jsExecute.js +20 -1
  182. package/build/core/jsExecute.js.map +1 -1
  183. package/build/core/measureComponent.d.ts.map +1 -1
  184. package/build/core/measureComponent.js +4 -8
  185. package/build/core/measureComponent.js.map +1 -1
  186. package/build/core/metro.d.ts +20 -1
  187. package/build/core/metro.d.ts.map +1 -1
  188. package/build/core/metro.js +146 -9
  189. package/build/core/metro.js.map +1 -1
  190. package/build/core/mockRules.d.ts +1 -0
  191. package/build/core/mockRules.d.ts.map +1 -1
  192. package/build/core/mockRules.js +8 -0
  193. package/build/core/mockRules.js.map +1 -1
  194. package/build/core/nativeLogs.js +1 -1
  195. package/build/core/nativeLogs.js.map +1 -1
  196. package/build/core/navigation.d.ts.map +1 -1
  197. package/build/core/navigation.js +4 -18
  198. package/build/core/navigation.js.map +1 -1
  199. package/build/core/networkInterceptor.d.ts +2 -2
  200. package/build/core/networkInterceptor.d.ts.map +1 -1
  201. package/build/core/networkInterceptor.js +90 -3
  202. package/build/core/networkInterceptor.js.map +1 -1
  203. package/build/core/pressables.d.ts.map +1 -1
  204. package/build/core/pressables.js +6 -13
  205. package/build/core/pressables.js.map +1 -1
  206. package/build/core/redux.d.ts.map +1 -1
  207. package/build/core/redux.js +6 -10
  208. package/build/core/redux.js.map +1 -1
  209. package/build/core/register.d.ts.map +1 -1
  210. package/build/core/register.js +5 -2
  211. package/build/core/register.js.map +1 -1
  212. package/build/core/rnGlobalsBootstrap.d.ts.map +1 -1
  213. package/build/core/rnGlobalsBootstrap.js +3 -1
  214. package/build/core/rnGlobalsBootstrap.js.map +1 -1
  215. package/build/core/screenLayout.d.ts.map +1 -1
  216. package/build/core/screenLayout.js +4 -13
  217. package/build/core/screenLayout.js.map +1 -1
  218. package/build/core/screenStaleness.d.ts.map +1 -1
  219. package/build/core/screenStaleness.js +2 -0
  220. package/build/core/screenStaleness.js.map +1 -1
  221. package/build/core/screenState.d.ts.map +1 -1
  222. package/build/core/screenState.js +4 -11
  223. package/build/core/screenState.js.map +1 -1
  224. package/build/core/swipeDiagnosis.d.ts.map +1 -1
  225. package/build/core/swipeDiagnosis.js +3 -10
  226. package/build/core/swipeDiagnosis.js.map +1 -1
  227. package/build/core/textEntry.d.ts +1 -1
  228. package/build/core/textEntry.d.ts.map +1 -1
  229. package/build/core/types.d.ts +4 -2
  230. package/build/core/types.d.ts.map +1 -1
  231. package/build/pro/chromiumKeys.d.ts +19 -0
  232. package/build/pro/chromiumKeys.d.ts.map +1 -0
  233. package/build/pro/chromiumKeys.js +68 -0
  234. package/build/pro/chromiumKeys.js.map +1 -0
  235. package/build/pro/chromiumSwipe.d.ts +35 -0
  236. package/build/pro/chromiumSwipe.d.ts.map +1 -0
  237. package/build/pro/chromiumSwipe.js +105 -0
  238. package/build/pro/chromiumSwipe.js.map +1 -0
  239. package/build/pro/chromiumTap.d.ts +12 -0
  240. package/build/pro/chromiumTap.d.ts.map +1 -0
  241. package/build/pro/chromiumTap.js +155 -0
  242. package/build/pro/chromiumTap.js.map +1 -0
  243. package/build/pro/tap.d.ts +1 -0
  244. package/build/pro/tap.d.ts.map +1 -1
  245. package/build/pro/tap.js +7 -1
  246. package/build/pro/tap.js.map +1 -1
  247. package/build/tools/componentTools.d.ts.map +1 -1
  248. package/build/tools/componentTools.js +31 -3
  249. package/build/tools/componentTools.js.map +1 -1
  250. package/build/tools/connectionTools.d.ts.map +1 -1
  251. package/build/tools/connectionTools.js +66 -28
  252. package/build/tools/connectionTools.js.map +1 -1
  253. package/build/tools/deviceTools.d.ts.map +1 -1
  254. package/build/tools/deviceTools.js +42 -1
  255. package/build/tools/deviceTools.js.map +1 -1
  256. package/build/tools/interactionTools.d.ts.map +1 -1
  257. package/build/tools/interactionTools.js +132 -7
  258. package/build/tools/interactionTools.js.map +1 -1
  259. package/build/tools/networkTools.d.ts.map +1 -1
  260. package/build/tools/networkTools.js +20 -5
  261. package/build/tools/networkTools.js.map +1 -1
  262. package/build/tools/screenshotTools.d.ts.map +1 -1
  263. package/build/tools/screenshotTools.js +452 -373
  264. package/build/tools/screenshotTools.js.map +1 -1
  265. package/package.json +1 -1
  266. package/tools.json +27 -1
package/README.md CHANGED
@@ -64,9 +64,23 @@ Linking is only for the dashboard: it attaches your installs to your account so
64
64
  - **Per-Device Buffers** - Logs and network requests are captured separately per device for clean debugging
65
65
  - **Cross-Platform Comparison** - Debug iOS and Android side-by-side, comparing logs, network traffic, and component trees
66
66
 
67
+ ### Electron & Chromium (experimental)
68
+
69
+ - **Desktop React apps over CDP** - An Electron window or a Chrome tab connects as a `chromium` target alongside your simulators, and every tool takes the same `device` argument
70
+ - **What works today** - Console logs, network capture, replay and mocking (`network_mock`, `network_condition`), `execute_in_app`, debug globals, Redux, `http_request` / `app_request`, React component inspection (`get_component_tree`, `find_components`, `inspect_component`), including on Vite apps whose DevTools hook has no renderers, plus `screenshot`, `tap`, `input_text`, `swipe` (mouse-wheel scroll, and a real drag with four coordinates) and `press_key` (Enter, Escape, Tab, arrows, shortcuts). JavaScript dialogs (`alert` / `confirm` / `prompt` / `beforeunload`) are reported by the tool that opened them instead of timing out, page tools refuse while one is open, and `handle_dialog` accepts or dismisses it. Taps find elements by `data-testid` / `id`, visible text or React component name and click with real CDP mouse events. Screen reading without a screenshot: `get_screen_state` (tap-ready elements, what an overlay blocks), `get_screen_layout`, `inspect_at_point` and `measure`
71
+ - **Not yet** - `pinch`, `navigate` and the other mobile-only tools refuse a chromium target with a message saying so, rather than acting on the wrong device. Native HTML5 drag and drop (`draggable`) and hover are not handled yet
72
+ - **Zero-config start** - `electron_launch_app({ projectPath: "path/to/app" })` starts an Electron project from its source folder with the debugging port open and connects its windows. It runs your project's own `electron` or `electron-vite`, never a packaged build
73
+ - **Or opt in** - Add one dev-only line to the Electron main process, then run `scan_metro`. Port 9222 is listed but not auto-connected, because connecting injects a network interceptor into the page. Attach with `connect_metro({ port: 9222, device: "<window title>" })`, or set `EXECBRO_CHROMIUM_PORTS=9222` to auto-connect
74
+
75
+ ```ts
76
+ if (!app.isPackaged) app.commandLine.appendSwitch('remote-debugging-port', '9222')
77
+ ```
78
+
79
+ Keep the `!app.isPackaged` guard: an open debugging port on a packaged build lets anything that can reach it run code in your renderer
80
+
67
81
  ### Under the Hood
68
82
 
69
- - **Auto-Discovery** - Scans Metro on ports 8081, 8082, 19000-19002 automatically
83
+ - **Auto-Discovery** - Scans Metro on ports 8081-8090 automatically, and lists Chromium/Electron targets on 9222 (plus any ports in `EXECBRO_CHROMIUM_PORTS`)
70
84
  - **Multi-Device Support** - Connects to all Bridgeless targets simultaneously, with per-device log and network buffers
71
85
  - **Auto-Reconnection** - Exponential backoff (up to 8 attempts) when connection drops
72
86
  - **Efficient Buffering** - Circular buffers: 500 logs, 200 network requests, 100 inspector selections
@@ -8,6 +8,9 @@ jest.unstable_mockModule("../../core/metro.js", () => ({
8
8
  fetchDevices,
9
9
  selectMainDevice,
10
10
  filterDebuggableDevices,
11
+ isChromiumTarget: () => false,
12
+ pickReconnectTarget: jest.fn(),
13
+ pinChromiumName: (d) => d.deviceName,
11
14
  }));
12
15
  const { executeInApp, markConnectionEstablished } = await import("../../core/jsExecute.js");
13
16
  const { connectedApps } = await import("../../core/state.js");
@@ -1 +1 @@
1
- {"version":3,"file":"autoReconnectOptOut.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/autoReconnectOptOut.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgBrC,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAGxD,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAClD,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AAClD,MAAM,uBAAuB,GAAG,IAAI,CAAC,EAAE,CAAM,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;AAExE,IAAI,CAAC,mBAAmB,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnD,cAAc;IACd,YAAY;IACZ,gBAAgB;IAChB,uBAAuB;CAC1B,CAAC,CAAC,CAAC;AAEJ,MAAM,EAAE,YAAY,EAAE,yBAAyB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAC5F,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAE9D,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACpD,UAAU,CAAC,GAAG,EAAE;QACZ,cAAc,CAAC,SAAS,EAAE,CAAC;QAC3B,aAAa,CAAC,KAAK,EAAE,CAAC;QAItB,yBAAyB,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE;YAC1C,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,KAAK;YACpB,mBAAmB,EAAE,aAAa;SACrC,CAAC,CAAC;QAEH,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAGH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,CAAC;QAE7F,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"autoReconnectOptOut.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/autoReconnectOptOut.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgBrC,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAGxD,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAClD,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AAClD,MAAM,uBAAuB,GAAG,IAAI,CAAC,EAAE,CAAM,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;AAExE,IAAI,CAAC,mBAAmB,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnD,cAAc;IACd,YAAY;IACZ,gBAAgB;IAChB,uBAAuB;IACvB,gBAAgB,EAAE,GAAG,EAAE,CAAC,KAAK;IAC7B,mBAAmB,EAAE,IAAI,CAAC,EAAE,EAAE;IAC9B,eAAe,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;CAC5C,CAAC,CAAC,CAAC;AAEJ,MAAM,EAAE,YAAY,EAAE,yBAAyB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAC5F,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAE9D,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACpD,UAAU,CAAC,GAAG,EAAE;QACZ,cAAc,CAAC,SAAS,EAAE,CAAC;QAC3B,aAAa,CAAC,KAAK,EAAE,CAAC;QAItB,yBAAyB,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE;YAC1C,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,KAAK;YACpB,mBAAmB,EAAE,aAAa;SACrC,CAAC,CAAC;QAEH,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAGH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,CAAC;QAE7F,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cdpCommand.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdpCommand.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/cdpCommand.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,84 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { EventEmitter } from "node:events";
3
+ import { sendCdpCommand, evaluateJson } from "../../core/cdpCommand.js";
4
+ import { noteDialogOpened } from "../../core/chromiumDialogs.js";
5
+ class FakeWs extends EventEmitter {
6
+ sent = [];
7
+ send(s) { this.sent.push(JSON.parse(s)); }
8
+ reply(msg) { this.emit("message", Buffer.from(JSON.stringify(msg))); }
9
+ }
10
+ const asWs = (f) => f;
11
+ describe("sendCdpCommand", () => {
12
+ it("resolves with the result of the response carrying its own id, ignoring others", async () => {
13
+ const ws = new FakeWs();
14
+ const p = sendCdpCommand(asWs(ws), "Page.captureScreenshot", { format: "png" });
15
+ const { id, method, params } = ws.sent[0];
16
+ expect(method).toBe("Page.captureScreenshot");
17
+ expect(params).toEqual({ format: "png" });
18
+ ws.reply({ id: id + 1000, result: { data: "wrong" } });
19
+ ws.reply({ method: "Runtime.consoleAPICalled", params: {} });
20
+ ws.reply({ id, result: { data: "abc" } });
21
+ await expect(p).resolves.toEqual({ data: "abc" });
22
+ expect(ws.listenerCount("message")).toBe(0);
23
+ });
24
+ it("rejects with the CDP error message, naming the method", async () => {
25
+ const ws = new FakeWs();
26
+ const p = sendCdpCommand(asWs(ws), "Input.insertText", { text: "x" });
27
+ ws.reply({ id: ws.sent[0].id, error: { code: -32000, message: "No focused element" } });
28
+ await expect(p).rejects.toThrow("Input.insertText: No focused element");
29
+ expect(ws.listenerCount("message")).toBe(0);
30
+ });
31
+ it("times out, and detaches its listener so a late reply is harmless", async () => {
32
+ const ws = new FakeWs();
33
+ const p = sendCdpCommand(asWs(ws), "Page.captureScreenshot", {}, 20);
34
+ await expect(p).rejects.toThrow("Page.captureScreenshot timed out after 20ms");
35
+ expect(ws.listenerCount("message")).toBe(0);
36
+ ws.reply({ id: ws.sent[0].id, result: {} });
37
+ });
38
+ it("rejects when send throws (socket already closed)", async () => {
39
+ const ws = new FakeWs();
40
+ ws.send = () => { throw new Error("WebSocket is not open"); };
41
+ await expect(sendCdpCommand(asWs(ws), "Page.captureScreenshot")).rejects.toThrow("WebSocket is not open");
42
+ expect(ws.listenerCount("message")).toBe(0);
43
+ });
44
+ });
45
+ describe("evaluateJson", () => {
46
+ it("parses the JSON string the expression returns", async () => {
47
+ const ws = new FakeWs();
48
+ const p = evaluateJson(asWs(ws), "JSON.stringify({ w: 380 })");
49
+ expect(ws.sent[0].params).toEqual({ expression: "JSON.stringify({ w: 380 })", returnByValue: true });
50
+ ws.reply({ id: ws.sent[0].id, result: { result: { type: "string", value: "{\"w\":380}" } } });
51
+ await expect(p).resolves.toEqual({ w: 380 });
52
+ });
53
+ it("throws the page exception's description", async () => {
54
+ const ws = new FakeWs();
55
+ const p = evaluateJson(asWs(ws), "boom()");
56
+ ws.reply({ id: ws.sent[0].id, result: { result: { type: "object" }, exceptionDetails: { text: "Uncaught", exception: { description: "ReferenceError: boom is not defined" } } } });
57
+ await expect(p).rejects.toThrow("ReferenceError: boom is not defined");
58
+ });
59
+ });
60
+ describe("sendCdpCommand on a closing socket", () => {
61
+ it("rejects at once on a closed socket instead of waiting out its timeout", async () => {
62
+ const ws = Object.assign(new FakeWs(), { readyState: 3 });
63
+ await expect(sendCdpCommand(asWs(ws), "Page.captureScreenshot", {}, 60_000)).rejects.toThrow("socket is closed");
64
+ expect(ws.sent).toEqual([]);
65
+ });
66
+ it("rejects at once when the socket closes mid-wait, and detaches", async () => {
67
+ const ws = new FakeWs();
68
+ const p = sendCdpCommand(asWs(ws), "Page.captureScreenshot", {}, 60_000);
69
+ ws.emit("close");
70
+ await expect(p).rejects.toThrow("socket is closed");
71
+ expect(ws.listenerCount("message")).toBe(0);
72
+ expect(ws.listenerCount("close")).toBe(0);
73
+ });
74
+ });
75
+ describe("evaluateJson and a dialog", () => {
76
+ it("reports a dialog that opens during the read instead of timing out", async () => {
77
+ const ws = new FakeWs();
78
+ const p = evaluateJson(asWs(ws), "1", 60_000);
79
+ noteDialogOpened(ws, { type: "alert", message: "Saved", url: "http://x/" });
80
+ await expect(p).rejects.toThrow(/alert dialog: "Saved".*handle_dialog/s);
81
+ ws.emit("close");
82
+ });
83
+ });
84
+ //# sourceMappingURL=cdpCommand.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdpCommand.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/cdpCommand.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chromium.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromium.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromium.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,118 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { pxPerCss, CHROMIUM_MAX_DIMENSION, pickDomTarget, normText, buildDomCollectJs, buildDomPrepareJs, judgeTextEntry, maskPasswordEntry, buildDomFocusJs, buildDomReadJs } from "../../core/chromium.js";
3
+ describe("pxPerCss", () => {
4
+ it("is devicePixelRatio when the raw capture fits the cap (FluentTalk popover, 380x600 @2)", () => {
5
+ expect(pxPerCss({ w: 380, h: 600, dpr: 2 })).toBe(2);
6
+ });
7
+ it("is 1 on a non-retina window under the cap", () => {
8
+ expect(pxPerCss({ w: 1280, h: 800, dpr: 1 })).toBe(1);
9
+ });
10
+ it("drops below dpr so the longest side lands exactly on the cap (1440x900 @2 = 2880 raw)", () => {
11
+ const k = pxPerCss({ w: 1440, h: 900, dpr: 2 });
12
+ expect(k).toBeCloseTo(CHROMIUM_MAX_DIMENSION / 1440);
13
+ expect(Math.round(1440 * k)).toBe(CHROMIUM_MAX_DIMENSION);
14
+ });
15
+ it("uses the longest side for a portrait window", () => {
16
+ expect(Math.round(1200 * pxPerCss({ w: 700, h: 1200, dpr: 2 }))).toBe(CHROMIUM_MAX_DIMENSION);
17
+ });
18
+ it("round-trips a delivered pixel to CSS and back within half a pixel", () => {
19
+ const vp = { w: 1440, h: 900, dpr: 2 };
20
+ const k = pxPerCss(vp);
21
+ const px = { x: 1234, y: 567 };
22
+ const css = { x: px.x / k, y: px.y / k };
23
+ expect(Math.abs(Math.round(css.x * k) - px.x)).toBeLessThanOrEqual(0.5);
24
+ expect(Math.abs(Math.round(css.y * k) - px.y)).toBeLessThanOrEqual(0.5);
25
+ });
26
+ });
27
+ const cand = (i, text, extra = {}) => ({
28
+ i, tag: "button", text, testID: null, label: null, placeholder: null, value: null,
29
+ rect: { x: 0, y: 0, w: 10, h: 10 }, ...extra,
30
+ });
31
+ describe("pickDomTarget", () => {
32
+ it("prefers an exact text match over case-insensitive and substring matches", () => {
33
+ const cs = [cand(0, "Save draft"), cand(1, "save"), cand(2, "Save")];
34
+ expect(pickDomTarget(cs, "Save", undefined)).toEqual({ kind: "ok", cand: cs[2] });
35
+ });
36
+ it("falls back to case-insensitive exact, then to substring", () => {
37
+ expect(pickDomTarget([cand(0, "Save draft"), cand(1, "SAVE")], "save", undefined)).toEqual({ kind: "ok", cand: cand(1, "SAVE") });
38
+ expect(pickDomTarget([cand(0, "Save draft")], "save", undefined)).toEqual({ kind: "ok", cand: cand(0, "Save draft") });
39
+ });
40
+ it("compares whitespace-collapsed text", () => {
41
+ expect(pickDomTarget([cand(0, "Sign in")], " Sign in ", undefined).kind).toBe("ok");
42
+ });
43
+ it("refuses to guess between several equally good matches", () => {
44
+ const cs = [cand(0, "Copy"), cand(1, "Copy")];
45
+ expect(pickDomTarget(cs, "Copy", undefined)).toEqual({ kind: "ambiguous", matches: cs });
46
+ });
47
+ it("index picks within the winning tier; out of range is none", () => {
48
+ const cs = [cand(0, "Copy"), cand(1, "Copy"), cand(2, "Copy link")];
49
+ expect(pickDomTarget(cs, "Copy", 1)).toEqual({ kind: "ok", cand: cs[1] });
50
+ expect(pickDomTarget(cs, "Copy", 5)).toEqual({ kind: "none" });
51
+ });
52
+ it("with no text (testID / component), every candidate is equally good", () => {
53
+ expect(pickDomTarget([cand(0, "")], undefined, undefined).kind).toBe("ok");
54
+ expect(pickDomTarget([cand(0, ""), cand(1, "")], undefined, undefined).kind).toBe("ambiguous");
55
+ expect(pickDomTarget([], undefined, undefined)).toEqual({ kind: "none" });
56
+ });
57
+ });
58
+ describe("normText", () => {
59
+ it("collapses runs of whitespace, including newlines", () => {
60
+ expect(normText(" a \n\t b ")).toBe("a b");
61
+ });
62
+ });
63
+ describe("injected DOM scripts are valid JavaScript", () => {
64
+ const parses = (js) => () => new Function(`return ${js};`);
65
+ it.each([
66
+ ["tap/testID", { mode: "tap", testID: "save-btn" }],
67
+ ["tap/text with quotes", { mode: "tap", text: "Don't \"stop\"" }],
68
+ ["tap/component", { mode: "tap", component: "SpeakButton" }],
69
+ ["input/textMatch", { mode: "input", textMatch: "Email" }],
70
+ ["input/untargeted", { mode: "input" }],
71
+ ])("collector: %s", (_n, q) => {
72
+ expect(parses(buildDomCollectJs(q))).not.toThrow();
73
+ });
74
+ it("prepare", () => expect(parses(buildDomPrepareJs(3))).not.toThrow());
75
+ });
76
+ describe("maskPasswordEntry", () => {
77
+ it("keeps the verdict of a password write but none of its text", () => {
78
+ const ok = maskPasswordEntry({ success: true, verified: true, value: "hunter2x", path: "cdp" });
79
+ expect(ok).toEqual({ success: true, verified: true, value: "[password, 8 chars]", path: "cdp" });
80
+ const bad = maskPasswordEntry({ success: false, error: "e", sent: "hunter2x", landed: "hunter2" });
81
+ expect(JSON.stringify(bad)).not.toContain("hunter");
82
+ expect(bad).toMatchObject({ sent: "[password, 8 chars]", landed: "[password, 7 chars]" });
83
+ });
84
+ });
85
+ describe("judgeTextEntry", () => {
86
+ it("verifies an append against the prior value", () => {
87
+ expect(judgeTextEntry({ before: "Hello", sent: " world", replace: false, landed: "Hello world", maxLength: null }))
88
+ .toEqual({ success: true, verified: true, value: "Hello world", path: "cdp" });
89
+ });
90
+ it("verifies a replace against the sent text alone", () => {
91
+ expect(judgeTextEntry({ before: "old", sent: "new", replace: true, landed: "new", maxLength: null }).verified).toBe(true);
92
+ });
93
+ it("reports a controlled input that reverted the write, with sent and landed", () => {
94
+ const r = judgeTextEntry({ before: "", sent: "abc1", replace: true, landed: "abc", maxLength: null });
95
+ expect(r.success).toBe(false);
96
+ expect(r.sent).toBe("abc1");
97
+ expect(r.landed).toBe("abc");
98
+ expect(r.error).toContain("does not hold");
99
+ });
100
+ it("names a maxLength truncation instead of a generic mismatch", () => {
101
+ const r = judgeTextEntry({ before: "", sent: "123456", replace: true, landed: "1234", maxLength: 4 });
102
+ expect(r.success).toBe(false);
103
+ expect(r.error).toContain("maxLength (4)");
104
+ });
105
+ it("treats a field that vanished as a failure", () => {
106
+ expect(judgeTextEntry({ before: "", sent: "x", replace: true, landed: null, maxLength: null }).success).toBe(false);
107
+ });
108
+ });
109
+ describe("input scripts are valid JavaScript", () => {
110
+ const parses = (js) => () => new Function(`return ${js};`);
111
+ it("focus (append, replace, clear) and read", () => {
112
+ expect(parses(buildDomFocusJs(0, false, false))).not.toThrow();
113
+ expect(parses(buildDomFocusJs(1, true, false))).not.toThrow();
114
+ expect(parses(buildDomFocusJs(2, true, true))).not.toThrow();
115
+ expect(parses(buildDomReadJs(0))).not.toThrow();
116
+ });
117
+ });
118
+ //# sourceMappingURL=chromium.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromium.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/chromium.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chromiumDevice.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromiumDevice.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDevice.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,115 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { EventEmitter } from "node:events";
3
+ import sharp from "sharp";
4
+ import { chromiumCapture, chromiumInputText } from "../../core/chromium.js";
5
+ import { chromiumTap } from "../../pro/chromiumTap.js";
6
+ class ScriptedWs extends EventEmitter {
7
+ answer;
8
+ sent = [];
9
+ constructor(answer) {
10
+ super();
11
+ this.answer = answer;
12
+ }
13
+ send(s) {
14
+ const m = JSON.parse(s);
15
+ this.sent.push(m);
16
+ queueMicrotask(() => this.emit("message", Buffer.from(JSON.stringify({ id: m.id, result: this.answer(m) }))));
17
+ }
18
+ }
19
+ const value = (v) => ({ result: { type: "string", value: JSON.stringify(v) } });
20
+ const appOn = (ws) => ({ ws, deviceInfo: { deviceName: "FluentTalk" }, platform: "chromium" });
21
+ describe("chromiumCapture on a hidden window", () => {
22
+ it("fails immediately without asking Chromium for a frame it will never paint", async () => {
23
+ const ws = new ScriptedWs(() => value({ w: 380, h: 600, dpr: 1, hidden: true }));
24
+ await expect(chromiumCapture(appOn(ws))).rejects.toThrow(/hidden/);
25
+ expect(ws.sent.map((m) => m.method)).toEqual(["Runtime.evaluate"]);
26
+ });
27
+ });
28
+ describe("chromiumTap scroll note", () => {
29
+ it("says when the target was scrolled into view first", async () => {
30
+ const ws = new ScriptedWs((m) => {
31
+ if (m.method !== "Runtime.evaluate")
32
+ return {};
33
+ if (m.params.expression.includes("__eb_domTargets = els")) {
34
+ return value({
35
+ viewport: { w: 380, h: 600, dpr: 1 }, focused: false, total: 1,
36
+ candidates: [{ i: 0, tag: "p", text: "back to life", testID: null, label: null, placeholder: null, value: null, rect: { x: 10, y: 700, w: 100, h: 20 } }],
37
+ });
38
+ }
39
+ return value({ x: 60, y: 444, scrolled: true, covered: null });
40
+ });
41
+ const r = await chromiumTap(appOn(ws), { text: "back to life" }, { verify: false, screenshot: false });
42
+ expect(r.success).toBe(true);
43
+ expect(r.warning).toMatch(/scrolled into view/i);
44
+ });
45
+ });
46
+ describe("chromiumTap on a hidden window", () => {
47
+ it("refuses before clicking, with verify:false too", async () => {
48
+ const ws = new ScriptedWs((m) => {
49
+ if (m.method !== "Runtime.evaluate")
50
+ return {};
51
+ if (m.params.expression.includes("__eb_domTargets = els")) {
52
+ return value({
53
+ viewport: { w: 380, h: 600, dpr: 1, hidden: true }, focused: false, total: 1,
54
+ candidates: [{ i: 0, tag: "button", text: "Save", testID: null, label: null, placeholder: null, value: null, rect: { x: 10, y: 10, w: 100, h: 20 } }],
55
+ });
56
+ }
57
+ return value({ w: 380, h: 600, dpr: 1, hidden: true, x: 60, y: 20, scrolled: false, covered: null });
58
+ });
59
+ const r = await chromiumTap(appOn(ws), { text: "Save" }, { verify: false, screenshot: false });
60
+ expect(r.success).toBe(false);
61
+ expect(r.error).toMatch(/hidden/);
62
+ expect(ws.sent.some((m) => m.method === "Input.dispatchMouseEvent")).toBe(false);
63
+ const c = await chromiumTap(appOn(ws), { x: 10, y: 10 }, { verify: false, screenshot: false });
64
+ expect(c.success).toBe(false);
65
+ expect(ws.sent.some((m) => m.method === "Input.dispatchMouseEvent")).toBe(false);
66
+ });
67
+ });
68
+ describe("chromiumInputText into an empty rich-text editor", () => {
69
+ it("verifies an append when the editor's empty paragraph reads as a lone newline", async () => {
70
+ const ws = new ScriptedWs((m) => {
71
+ if (m.method === "Input.insertText")
72
+ return {};
73
+ const e = m.params.expression;
74
+ if (e.includes("__eb_domTargets = els")) {
75
+ return value({
76
+ viewport: { w: 380, h: 600, dpr: 1 }, focused: true, total: 1,
77
+ candidates: [{ i: 0, tag: "div", text: "", testID: null, label: null, placeholder: null, value: "\n", rect: { x: 0, y: 0, w: 300, h: 40 } }],
78
+ });
79
+ }
80
+ if (e.includes("el.focus()"))
81
+ return value({ before: "\n", field: false, focused: true, maxLength: null });
82
+ return value({ value: "hi\n" });
83
+ });
84
+ const r = await chromiumInputText(appOn(ws), { text: "hi" });
85
+ expect(r).toMatchObject({ success: true, verified: true, value: "hi" });
86
+ });
87
+ });
88
+ describe("chromiumTap when the click hides its own window", () => {
89
+ it("reports the delivered click as a success, not a failure an agent would retry", async () => {
90
+ const png = (await sharp({ create: { width: 4, height: 4, channels: 3, background: "#000" } }).png().toBuffer()).toString("base64");
91
+ let viewportReads = 0;
92
+ const ws = new ScriptedWs((m) => {
93
+ if (m.method === "Page.captureScreenshot")
94
+ return { data: png };
95
+ if (m.method !== "Runtime.evaluate")
96
+ return {};
97
+ const e = m.params.expression;
98
+ if (e.includes("__eb_domTargets = els")) {
99
+ return value({
100
+ viewport: { w: 4, h: 4, dpr: 1 }, focused: false, total: 1,
101
+ candidates: [{ i: 0, tag: "button", text: "Save & close", testID: null, label: null, placeholder: null, value: null, rect: { x: 0, y: 0, w: 4, h: 4 } }],
102
+ });
103
+ }
104
+ if (e.includes("elementFromPoint"))
105
+ return value({ x: 2, y: 2, scrolled: false, covered: null });
106
+ viewportReads++;
107
+ return value({ w: 4, h: 4, dpr: 1, hidden: viewportReads > 1 });
108
+ });
109
+ const r = await chromiumTap(appOn(ws), { text: "Save & close" }, {});
110
+ expect(r.success).toBe(true);
111
+ expect(ws.sent.filter((m) => m.params && m.params.type === "mousePressed")).toHaveLength(1);
112
+ expect(r.verification?.explanation).toMatch(/hid/);
113
+ });
114
+ });
115
+ //# sourceMappingURL=chromiumDevice.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromiumDevice.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDevice.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chromiumDialogAnswer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromiumDialogAnswer.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDialogAnswer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect, jest } from "@jest/globals";
2
+ const { noteDialogOpened, noteDialogClosed } = await import("../../core/chromiumDialogs.js");
3
+ const calls = [];
4
+ const sendCdpCommand = jest.fn(async (ws, method, params = {}) => {
5
+ calls.push({ method, ...params });
6
+ if (method === "Page.handleJavaScriptDialog" && ws.gone)
7
+ throw new Error("Page.handleJavaScriptDialog: No dialog is showing");
8
+ if (method === "Page.handleJavaScriptDialog")
9
+ setTimeout(() => noteDialogClosed(ws, { result: params.accept === true, userInput: params.promptText }), 5);
10
+ return {};
11
+ });
12
+ jest.unstable_mockModule("../../core/cdpCommand.js", () => ({ sendCdpCommand, evaluateJson: jest.fn() }));
13
+ const { answerDialog, pickDialogApp } = await import("../../core/chromiumDialogAnswer.js");
14
+ const { connectedApps } = await import("../../core/state.js");
15
+ const mk = () => ({ ws: {}, deviceInfo: { deviceName: "page" } });
16
+ describe("answerDialog", () => {
17
+ it("accepts a prompt with text and reports the result", async () => {
18
+ const app = mk();
19
+ noteDialogOpened(app.ws, { type: "prompt", message: "Name?", url: "http://x/" });
20
+ const r = await answerDialog(app, { action: "accept", promptText: "eb" });
21
+ expect(r.isError).toBe(false);
22
+ expect(calls.at(-1)).toMatchObject({ method: "Page.handleJavaScriptDialog", accept: true, promptText: "eb" });
23
+ expect(JSON.parse(r.text)).toMatchObject({ answered: 'accepted a prompt dialog: "Name?"', result: true, userInput: "eb" });
24
+ });
25
+ it("with nothing open says so and names the last closed dialog, without calling CDP", async () => {
26
+ const app = mk();
27
+ noteDialogOpened(app.ws, { type: "alert", message: "Saved", url: "http://x/" });
28
+ noteDialogClosed(app.ws, { result: true });
29
+ const before = calls.length;
30
+ const r = await answerDialog(app, { action: "dismiss" });
31
+ expect(r.isError).toBe(true);
32
+ expect(r.text).toMatch(/No dialog is open/);
33
+ expect(r.text).toMatch(/alert dialog: "Saved"/);
34
+ expect(calls.length).toBe(before);
35
+ });
36
+ it("refuses promptText on a non-prompt dialog", async () => {
37
+ const app = mk();
38
+ noteDialogOpened(app.ws, { type: "confirm", message: "Sure?", url: "http://x/" });
39
+ const r = await answerDialog(app, { action: "accept", promptText: "x" });
40
+ expect(r.isError).toBe(true);
41
+ expect(r.text).toMatch(/promptText/);
42
+ });
43
+ it("a dialog closed by hand just before the answer reads as no dialog open, not a CDP error", async () => {
44
+ const app = mk();
45
+ noteDialogOpened(app.ws, { type: "alert", message: "Hi", url: "http://x/" });
46
+ app.ws.gone = true;
47
+ const r = await answerDialog(app, { action: "accept" });
48
+ expect(r.isError).toBe(true);
49
+ expect(r.text).toMatch(/No dialog is open/);
50
+ expect(r.text).toMatch(/alert dialog: "Hi"/);
51
+ });
52
+ it("a bare call picks the window that has the dialog, not just the first chromium window", () => {
53
+ const first = { ws: {}, platform: "chromium", deviceInfo: { deviceName: "W1" } };
54
+ const second = { ws: {}, platform: "chromium", deviceInfo: { deviceName: "W2" } };
55
+ connectedApps.set("9997-W1", first);
56
+ connectedApps.set("9997-W2", second);
57
+ try {
58
+ noteDialogOpened(second.ws, { type: "alert", message: "in W2", url: "http://x/" });
59
+ expect(pickDialogApp(first, undefined)).toBe(second);
60
+ expect(pickDialogApp(first, "W1")).toBe(first);
61
+ expect(pickDialogApp(null, undefined)).toBe(second);
62
+ expect(pickDialogApp(null, "iPhone")).toBeNull();
63
+ }
64
+ finally {
65
+ connectedApps.delete("9997-W1");
66
+ connectedApps.delete("9997-W2");
67
+ noteDialogClosed(second.ws, { result: true });
68
+ }
69
+ });
70
+ });
71
+ //# sourceMappingURL=chromiumDialogAnswer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromiumDialogAnswer.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDialogAnswer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chromiumDialogRaces.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromiumDialogRaces.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDialogRaces.test.ts"],"names":[],"mappings":""}