browser-debugger-cli 0.6.0 → 0.6.2

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 (699) hide show
  1. package/README.md +65 -6
  2. package/dist/__tests__/smoke/error-handling.smoke.test.js +23 -52
  3. package/dist/__tests__/smoke/error-handling.smoke.test.js.map +1 -1
  4. package/dist/__tests__/smoke/session-lifecycle.smoke.test.js +27 -24
  5. package/dist/__tests__/smoke/session-lifecycle.smoke.test.js.map +1 -1
  6. package/dist/__testutils__/daemonHelpers.d.ts +13 -1
  7. package/dist/__testutils__/daemonHelpers.d.ts.map +1 -1
  8. package/dist/__testutils__/daemonHelpers.js +54 -5
  9. package/dist/__testutils__/daemonHelpers.js.map +1 -1
  10. package/dist/__testutils__/testCleanup.js +1 -1
  11. package/dist/__testutils__/testCleanup.js.map +1 -1
  12. package/dist/cdp/protocol.d.ts +0 -48
  13. package/dist/cdp/protocol.d.ts.map +1 -1
  14. package/dist/cdp/protocol.js +9 -101
  15. package/dist/cdp/protocol.js.map +1 -1
  16. package/dist/commands/__tests__/cdp.contract.test.js +2 -2
  17. package/dist/commands/__tests__/cdp.contract.test.js.map +1 -1
  18. package/dist/commands/__tests__/domEval.contract.test.js +8 -4
  19. package/dist/commands/__tests__/domEval.contract.test.js.map +1 -1
  20. package/dist/commands/cdp.d.ts.map +1 -1
  21. package/dist/commands/cdp.js +4 -37
  22. package/dist/commands/cdp.js.map +1 -1
  23. package/dist/commands/cleanup.d.ts.map +1 -1
  24. package/dist/commands/cleanup.js +25 -23
  25. package/dist/commands/cleanup.js.map +1 -1
  26. package/dist/commands/console.d.ts.map +1 -1
  27. package/dist/commands/console.js +3 -8
  28. package/dist/commands/console.js.map +1 -1
  29. package/dist/commands/details.d.ts.map +1 -1
  30. package/dist/commands/details.js +1 -1
  31. package/dist/commands/details.js.map +1 -1
  32. package/dist/commands/dom/a11y.d.ts +18 -0
  33. package/dist/commands/dom/a11y.d.ts.map +1 -0
  34. package/dist/commands/dom/a11y.js +134 -0
  35. package/dist/commands/dom/a11y.js.map +1 -0
  36. package/dist/commands/{domEvalHelpers.d.ts → dom/evalHelpers.d.ts} +8 -5
  37. package/dist/commands/dom/evalHelpers.d.ts.map +1 -0
  38. package/dist/commands/{domEvalHelpers.js → dom/evalHelpers.js} +14 -13
  39. package/dist/commands/dom/evalHelpers.js.map +1 -0
  40. package/dist/commands/dom/formFillHelpers.d.ts +47 -0
  41. package/dist/commands/dom/formFillHelpers.d.ts.map +1 -0
  42. package/dist/commands/dom/formFillHelpers.js +185 -0
  43. package/dist/commands/dom/formFillHelpers.js.map +1 -0
  44. package/dist/commands/dom/formInteraction.d.ts +17 -0
  45. package/dist/commands/dom/formInteraction.d.ts.map +1 -0
  46. package/dist/commands/dom/formInteraction.js +239 -0
  47. package/dist/commands/dom/formInteraction.js.map +1 -0
  48. package/dist/commands/dom/formSubmitHelpers.d.ts +58 -0
  49. package/dist/commands/dom/formSubmitHelpers.d.ts.map +1 -0
  50. package/dist/commands/dom/formSubmitHelpers.js +176 -0
  51. package/dist/commands/dom/formSubmitHelpers.js.map +1 -0
  52. package/dist/commands/dom/helpers.d.ts +34 -0
  53. package/dist/commands/dom/helpers.d.ts.map +1 -0
  54. package/dist/commands/dom/helpers.js +244 -0
  55. package/dist/commands/dom/helpers.js.map +1 -0
  56. package/dist/commands/{dom.d.ts → dom/index.d.ts} +1 -1
  57. package/dist/commands/dom/index.d.ts.map +1 -0
  58. package/dist/commands/dom/index.js +175 -0
  59. package/dist/commands/dom/index.js.map +1 -0
  60. package/dist/commands/dom/reactEventHelpers.d.ts +80 -0
  61. package/dist/commands/dom/reactEventHelpers.d.ts.map +1 -0
  62. package/dist/commands/dom/reactEventHelpers.js +274 -0
  63. package/dist/commands/dom/reactEventHelpers.js.map +1 -0
  64. package/dist/commands/network.js +1 -1
  65. package/dist/commands/network.js.map +1 -1
  66. package/dist/commands/peek.d.ts.map +1 -1
  67. package/dist/commands/peek.js +49 -52
  68. package/dist/commands/peek.js.map +1 -1
  69. package/dist/commands/shared/CommandRunner.d.ts.map +1 -1
  70. package/dist/commands/shared/CommandRunner.js +3 -2
  71. package/dist/commands/shared/CommandRunner.js.map +1 -1
  72. package/dist/commands/shared/commonOptions.d.ts.map +1 -1
  73. package/dist/commands/shared/commonOptions.js +3 -1
  74. package/dist/commands/shared/commonOptions.js.map +1 -1
  75. package/dist/commands/shared/daemonErrorHandler.d.ts +30 -0
  76. package/dist/commands/shared/daemonErrorHandler.d.ts.map +1 -0
  77. package/dist/commands/shared/daemonErrorHandler.js +32 -0
  78. package/dist/commands/shared/daemonErrorHandler.js.map +1 -0
  79. package/dist/commands/shared/{daemonSessionController.d.ts → startHelpers.d.ts} +7 -1
  80. package/dist/commands/shared/startHelpers.d.ts.map +1 -0
  81. package/dist/commands/shared/{daemonSessionController.js → startHelpers.js} +13 -5
  82. package/dist/commands/shared/startHelpers.js.map +1 -0
  83. package/dist/commands/shared/validation.d.ts +44 -0
  84. package/dist/commands/shared/validation.d.ts.map +1 -0
  85. package/dist/commands/shared/validation.js +68 -0
  86. package/dist/commands/shared/validation.js.map +1 -0
  87. package/dist/commands/start.d.ts.map +1 -1
  88. package/dist/commands/start.js +9 -25
  89. package/dist/commands/start.js.map +1 -1
  90. package/dist/commands/status.d.ts.map +1 -1
  91. package/dist/commands/status.js +6 -4
  92. package/dist/commands/status.js.map +1 -1
  93. package/dist/commands/stop.d.ts.map +1 -1
  94. package/dist/commands/stop.js +16 -19
  95. package/dist/commands/stop.js.map +1 -1
  96. package/dist/commands/tail.d.ts.map +1 -1
  97. package/dist/commands/tail.js +49 -44
  98. package/dist/commands/tail.js.map +1 -1
  99. package/dist/commands/types.d.ts +46 -0
  100. package/dist/commands/types.d.ts.map +1 -0
  101. package/dist/commands/types.js +8 -0
  102. package/dist/commands/types.js.map +1 -0
  103. package/dist/commands.d.ts.map +1 -1
  104. package/dist/commands.js +3 -1
  105. package/dist/commands.js.map +1 -1
  106. package/dist/connection/__tests__/cdp.contract.test.js +7 -7
  107. package/dist/connection/__tests__/cdp.contract.test.js.map +1 -1
  108. package/dist/connection/__tests__/handlers.unit.test.d.ts +11 -0
  109. package/dist/connection/__tests__/handlers.unit.test.d.ts.map +1 -0
  110. package/dist/connection/__tests__/handlers.unit.test.js +220 -0
  111. package/dist/connection/__tests__/handlers.unit.test.js.map +1 -0
  112. package/dist/connection/__tests__/pageReadiness.contract.test.d.ts +14 -0
  113. package/dist/connection/__tests__/pageReadiness.contract.test.d.ts.map +1 -0
  114. package/dist/connection/__tests__/pageReadiness.contract.test.js +382 -0
  115. package/dist/connection/__tests__/pageReadiness.contract.test.js.map +1 -0
  116. package/dist/connection/__tests__/portReservation.contract.test.d.ts +14 -0
  117. package/dist/connection/__tests__/portReservation.contract.test.d.ts.map +1 -0
  118. package/dist/connection/__tests__/portReservation.contract.test.js +250 -0
  119. package/dist/connection/__tests__/portReservation.contract.test.js.map +1 -0
  120. package/dist/connection/cdp.d.ts +34 -11
  121. package/dist/connection/cdp.d.ts.map +1 -1
  122. package/dist/connection/cdp.js +61 -45
  123. package/dist/connection/cdp.js.map +1 -1
  124. package/dist/connection/config.d.ts +63 -0
  125. package/dist/connection/config.d.ts.map +1 -0
  126. package/dist/connection/config.js +46 -0
  127. package/dist/connection/config.js.map +1 -0
  128. package/dist/connection/errors.d.ts +6 -21
  129. package/dist/connection/errors.d.ts.map +1 -1
  130. package/dist/connection/errors.js +7 -26
  131. package/dist/connection/errors.js.map +1 -1
  132. package/dist/connection/events.d.ts +30 -0
  133. package/dist/connection/events.d.ts.map +1 -0
  134. package/dist/connection/events.js +8 -0
  135. package/dist/connection/events.js.map +1 -0
  136. package/dist/connection/handlers.d.ts +3 -5
  137. package/dist/connection/handlers.d.ts.map +1 -1
  138. package/dist/connection/handlers.js +10 -12
  139. package/dist/connection/handlers.js.map +1 -1
  140. package/dist/connection/launcher/binaryResolver.d.ts +40 -0
  141. package/dist/connection/launcher/binaryResolver.d.ts.map +1 -0
  142. package/dist/connection/launcher/binaryResolver.js +78 -0
  143. package/dist/connection/launcher/binaryResolver.js.map +1 -0
  144. package/dist/connection/launcher/flagsBuilder.d.ts +64 -0
  145. package/dist/connection/launcher/flagsBuilder.d.ts.map +1 -0
  146. package/dist/connection/launcher/flagsBuilder.js +84 -0
  147. package/dist/connection/launcher/flagsBuilder.js.map +1 -0
  148. package/dist/connection/launcher/preferencesLoader.d.ts +74 -0
  149. package/dist/connection/launcher/preferencesLoader.d.ts.map +1 -0
  150. package/dist/connection/launcher/preferencesLoader.js +89 -0
  151. package/dist/connection/launcher/preferencesLoader.js.map +1 -0
  152. package/dist/connection/launcher.d.ts +24 -1
  153. package/dist/connection/launcher.d.ts.map +1 -1
  154. package/dist/connection/launcher.js +30 -205
  155. package/dist/connection/launcher.js.map +1 -1
  156. package/dist/connection/pageReadiness.d.ts +8 -8
  157. package/dist/connection/pageReadiness.d.ts.map +1 -1
  158. package/dist/connection/pageReadiness.js +36 -52
  159. package/dist/connection/pageReadiness.js.map +1 -1
  160. package/dist/connection/portReservation.d.ts +40 -0
  161. package/dist/connection/portReservation.d.ts.map +1 -0
  162. package/dist/connection/portReservation.js +55 -0
  163. package/dist/connection/portReservation.js.map +1 -0
  164. package/dist/connection/typed-cdp.d.ts +2 -1
  165. package/dist/connection/typed-cdp.d.ts.map +1 -1
  166. package/dist/connection/typed-cdp.js.map +1 -1
  167. package/dist/connection/types.d.ts +103 -0
  168. package/dist/connection/types.d.ts.map +1 -0
  169. package/dist/connection/types.js +8 -0
  170. package/dist/connection/types.js.map +1 -0
  171. package/dist/constants.d.ts +6 -83
  172. package/dist/constants.d.ts.map +1 -1
  173. package/dist/constants.js +6 -83
  174. package/dist/constants.js.map +1 -1
  175. package/dist/daemon/__tests__/JsonlParser.unit.test.d.ts +8 -0
  176. package/dist/daemon/__tests__/JsonlParser.unit.test.d.ts.map +1 -0
  177. package/dist/daemon/__tests__/JsonlParser.unit.test.js +140 -0
  178. package/dist/daemon/__tests__/JsonlParser.unit.test.js.map +1 -0
  179. package/dist/daemon/__tests__/PendingRequestManager.unit.test.d.ts +8 -0
  180. package/dist/daemon/__tests__/PendingRequestManager.unit.test.d.ts.map +1 -0
  181. package/dist/daemon/__tests__/PendingRequestManager.unit.test.js +276 -0
  182. package/dist/daemon/__tests__/PendingRequestManager.unit.test.js.map +1 -0
  183. package/dist/daemon/__tests__/TelemetryStore.unit.test.d.ts +8 -0
  184. package/dist/daemon/__tests__/TelemetryStore.unit.test.d.ts.map +1 -0
  185. package/dist/daemon/__tests__/TelemetryStore.unit.test.js +290 -0
  186. package/dist/daemon/__tests__/TelemetryStore.unit.test.js.map +1 -0
  187. package/dist/daemon/__tests__/commandRegistry.contract.test.d.ts +8 -0
  188. package/dist/daemon/__tests__/commandRegistry.contract.test.d.ts.map +1 -0
  189. package/dist/daemon/__tests__/commandRegistry.contract.test.js +384 -0
  190. package/dist/daemon/__tests__/commandRegistry.contract.test.js.map +1 -0
  191. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.d.ts +19 -0
  192. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.d.ts.map +1 -0
  193. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.js +212 -0
  194. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.js.map +1 -0
  195. package/dist/daemon/__tests__/ipcServer.contract.test.js +2 -1
  196. package/dist/daemon/__tests__/ipcServer.contract.test.js.map +1 -1
  197. package/dist/daemon/errors.d.ts +65 -0
  198. package/dist/daemon/errors.d.ts.map +1 -0
  199. package/dist/daemon/errors.js +82 -0
  200. package/dist/daemon/errors.js.map +1 -0
  201. package/dist/daemon/handlers/CommandHandlers.d.ts +32 -0
  202. package/dist/daemon/handlers/CommandHandlers.d.ts.map +1 -0
  203. package/dist/daemon/handlers/CommandHandlers.js +93 -0
  204. package/dist/daemon/handlers/CommandHandlers.js.map +1 -0
  205. package/dist/daemon/handlers/QueryHandlers.d.ts +35 -0
  206. package/dist/daemon/handlers/QueryHandlers.d.ts.map +1 -0
  207. package/dist/daemon/handlers/QueryHandlers.js +176 -0
  208. package/dist/daemon/handlers/QueryHandlers.js.map +1 -0
  209. package/dist/daemon/handlers/SessionHandlers.d.ts +32 -0
  210. package/dist/daemon/handlers/SessionHandlers.d.ts.map +1 -0
  211. package/dist/daemon/handlers/SessionHandlers.js +227 -0
  212. package/dist/daemon/handlers/SessionHandlers.js.map +1 -0
  213. package/dist/daemon/handlers/pendingRequests.d.ts +50 -0
  214. package/dist/daemon/handlers/pendingRequests.d.ts.map +1 -0
  215. package/dist/daemon/handlers/pendingRequests.js +57 -0
  216. package/dist/daemon/handlers/pendingRequests.js.map +1 -0
  217. package/dist/daemon/handlers/requestHandlers.d.ts +51 -0
  218. package/dist/daemon/handlers/requestHandlers.d.ts.map +1 -0
  219. package/dist/daemon/handlers/requestHandlers.js +61 -0
  220. package/dist/daemon/handlers/requestHandlers.js.map +1 -0
  221. package/dist/daemon/handlers/responseHandler.d.ts +42 -0
  222. package/dist/daemon/handlers/responseHandler.d.ts.map +1 -0
  223. package/dist/daemon/handlers/responseHandler.js +195 -0
  224. package/dist/daemon/handlers/responseHandler.js.map +1 -0
  225. package/dist/daemon/ipcServer.d.ts +19 -41
  226. package/dist/daemon/ipcServer.d.ts.map +1 -1
  227. package/dist/daemon/ipcServer.js +83 -655
  228. package/dist/daemon/ipcServer.js.map +1 -1
  229. package/dist/daemon/launcher.d.ts.map +1 -1
  230. package/dist/daemon/launcher.js +10 -6
  231. package/dist/daemon/launcher.js.map +1 -1
  232. package/dist/daemon/lifecycle/cdpSetup.d.ts +24 -0
  233. package/dist/daemon/lifecycle/cdpSetup.d.ts.map +1 -0
  234. package/dist/daemon/lifecycle/cdpSetup.js +59 -0
  235. package/dist/daemon/lifecycle/cdpSetup.js.map +1 -0
  236. package/dist/daemon/lifecycle/chromeConnection.d.ts +17 -0
  237. package/dist/daemon/lifecycle/chromeConnection.d.ts.map +1 -0
  238. package/dist/daemon/lifecycle/chromeConnection.js +80 -0
  239. package/dist/daemon/lifecycle/chromeConnection.js.map +1 -0
  240. package/dist/daemon/lifecycle/signalHandlers.d.ts +14 -0
  241. package/dist/daemon/lifecycle/signalHandlers.d.ts.map +1 -0
  242. package/dist/daemon/lifecycle/signalHandlers.js +35 -0
  243. package/dist/daemon/lifecycle/signalHandlers.js.map +1 -0
  244. package/dist/daemon/lifecycle/workerCleanup.d.ts +27 -0
  245. package/dist/daemon/lifecycle/workerCleanup.d.ts.map +1 -0
  246. package/dist/daemon/lifecycle/workerCleanup.js +144 -0
  247. package/dist/daemon/lifecycle/workerCleanup.js.map +1 -0
  248. package/dist/daemon/lifecycle/workerConfig.d.ts +14 -0
  249. package/dist/daemon/lifecycle/workerConfig.d.ts.map +1 -0
  250. package/dist/daemon/lifecycle/workerConfig.js +66 -0
  251. package/dist/daemon/lifecycle/workerConfig.js.map +1 -0
  252. package/dist/daemon/lifecycle/workerIpc.d.ts +14 -0
  253. package/dist/daemon/lifecycle/workerIpc.d.ts.map +1 -0
  254. package/dist/daemon/lifecycle/workerIpc.js +87 -0
  255. package/dist/daemon/lifecycle/workerIpc.js.map +1 -0
  256. package/dist/daemon/server/JsonlParser.d.ts +31 -0
  257. package/dist/daemon/server/JsonlParser.d.ts.map +1 -0
  258. package/dist/daemon/server/JsonlParser.js +57 -0
  259. package/dist/daemon/server/JsonlParser.js.map +1 -0
  260. package/dist/daemon/server/SocketServer.d.ts.map +1 -1
  261. package/dist/daemon/server/SocketServer.js +2 -2
  262. package/dist/daemon/server/SocketServer.js.map +1 -1
  263. package/dist/daemon/server/WorkerManager.d.ts +3 -3
  264. package/dist/daemon/server/WorkerManager.d.ts.map +1 -1
  265. package/dist/daemon/server/WorkerManager.js +10 -19
  266. package/dist/daemon/server/WorkerManager.js.map +1 -1
  267. package/dist/daemon/services/SessionService.d.ts +87 -0
  268. package/dist/daemon/services/SessionService.d.ts.map +1 -0
  269. package/dist/daemon/services/SessionService.js +45 -0
  270. package/dist/daemon/services/SessionService.js.map +1 -0
  271. package/dist/daemon/startSession.d.ts.map +1 -1
  272. package/dist/daemon/startSession.js +54 -31
  273. package/dist/daemon/startSession.js.map +1 -1
  274. package/dist/daemon/worker/commandRegistry.d.ts +1 -1
  275. package/dist/daemon/worker/commandRegistry.d.ts.map +1 -1
  276. package/dist/daemon/worker/commandRegistry.js +20 -215
  277. package/dist/daemon/worker/commandRegistry.js.map +1 -1
  278. package/dist/daemon/worker.d.ts +3 -12
  279. package/dist/daemon/worker.d.ts.map +1 -1
  280. package/dist/daemon/worker.js +47 -367
  281. package/dist/daemon/worker.js.map +1 -1
  282. package/dist/index.js +1 -1
  283. package/dist/index.js.map +1 -1
  284. package/dist/ipc/__tests__/client.contract.test.d.ts +0 -15
  285. package/dist/ipc/__tests__/client.contract.test.d.ts.map +1 -1
  286. package/dist/ipc/__tests__/client.contract.test.js +259 -42
  287. package/dist/ipc/__tests__/client.contract.test.js.map +1 -1
  288. package/dist/ipc/__tests__/errors.unit.test.d.ts +7 -0
  289. package/dist/ipc/__tests__/errors.unit.test.d.ts.map +1 -0
  290. package/dist/ipc/__tests__/errors.unit.test.js +77 -0
  291. package/dist/ipc/__tests__/errors.unit.test.js.map +1 -0
  292. package/dist/ipc/__tests__/guards.unit.test.d.ts +7 -0
  293. package/dist/ipc/__tests__/guards.unit.test.d.ts.map +1 -0
  294. package/dist/ipc/__tests__/guards.unit.test.js +73 -0
  295. package/dist/ipc/__tests__/guards.unit.test.js.map +1 -0
  296. package/dist/ipc/__tests__/jsonl.unit.test.d.ts +7 -0
  297. package/dist/ipc/__tests__/jsonl.unit.test.d.ts.map +1 -0
  298. package/dist/ipc/__tests__/jsonl.unit.test.js +103 -0
  299. package/dist/ipc/__tests__/jsonl.unit.test.js.map +1 -0
  300. package/dist/ipc/__tests__/validation.unit.test.d.ts +7 -0
  301. package/dist/ipc/__tests__/validation.unit.test.d.ts.map +1 -0
  302. package/dist/ipc/__tests__/validation.unit.test.js +60 -0
  303. package/dist/ipc/__tests__/validation.unit.test.js.map +1 -0
  304. package/dist/ipc/client.d.ts +93 -84
  305. package/dist/ipc/client.d.ts.map +1 -1
  306. package/dist/ipc/client.js +121 -192
  307. package/dist/ipc/client.js.map +1 -1
  308. package/dist/ipc/index.d.ts +17 -0
  309. package/dist/ipc/index.d.ts.map +1 -0
  310. package/dist/ipc/index.js +23 -0
  311. package/dist/ipc/index.js.map +1 -0
  312. package/dist/ipc/protocol/commands.d.ts +144 -0
  313. package/dist/ipc/protocol/commands.d.ts.map +1 -0
  314. package/dist/ipc/protocol/commands.js +23 -0
  315. package/dist/ipc/protocol/commands.js.map +1 -0
  316. package/dist/ipc/protocol/guards.d.ts +47 -0
  317. package/dist/ipc/protocol/guards.d.ts.map +1 -0
  318. package/dist/ipc/protocol/guards.js +62 -0
  319. package/dist/ipc/protocol/guards.js.map +1 -0
  320. package/dist/ipc/protocol/index.d.ts +9 -0
  321. package/dist/ipc/protocol/index.d.ts.map +1 -0
  322. package/dist/ipc/protocol/index.js +8 -0
  323. package/dist/ipc/protocol/index.js.map +1 -0
  324. package/dist/ipc/protocol/messages.d.ts +64 -0
  325. package/dist/ipc/protocol/messages.d.ts.map +1 -0
  326. package/dist/ipc/protocol/messages.js +8 -0
  327. package/dist/ipc/protocol/messages.js.map +1 -0
  328. package/dist/ipc/session/errors.d.ts +25 -0
  329. package/dist/ipc/session/errors.d.ts.map +1 -0
  330. package/dist/ipc/{types.js → session/errors.js} +11 -6
  331. package/dist/ipc/session/errors.js.map +1 -0
  332. package/dist/ipc/session/index.d.ts +16 -0
  333. package/dist/ipc/session/index.d.ts.map +1 -0
  334. package/dist/ipc/session/index.js +7 -0
  335. package/dist/ipc/session/index.js.map +1 -0
  336. package/dist/ipc/session/lifecycle.d.ts +125 -0
  337. package/dist/ipc/session/lifecycle.d.ts.map +1 -0
  338. package/dist/ipc/session/lifecycle.js +7 -0
  339. package/dist/ipc/session/lifecycle.js.map +1 -0
  340. package/dist/ipc/session/queries.d.ts +94 -0
  341. package/dist/ipc/session/queries.d.ts.map +1 -0
  342. package/dist/ipc/session/queries.js +7 -0
  343. package/dist/ipc/session/queries.js.map +1 -0
  344. package/dist/ipc/session/types.d.ts +28 -0
  345. package/dist/ipc/session/types.d.ts.map +1 -0
  346. package/dist/ipc/session/types.js +7 -0
  347. package/dist/ipc/session/types.js.map +1 -0
  348. package/dist/ipc/transport/IPCError.d.ts +82 -0
  349. package/dist/ipc/transport/IPCError.d.ts.map +1 -0
  350. package/dist/ipc/transport/IPCError.js +109 -0
  351. package/dist/ipc/transport/IPCError.js.map +1 -0
  352. package/dist/ipc/transport/errors.d.ts +11 -0
  353. package/dist/ipc/transport/errors.d.ts.map +1 -0
  354. package/dist/ipc/transport/errors.js +28 -0
  355. package/dist/ipc/transport/errors.js.map +1 -0
  356. package/dist/ipc/transport/index.d.ts +16 -0
  357. package/dist/ipc/transport/index.d.ts.map +1 -0
  358. package/dist/ipc/transport/index.js +77 -0
  359. package/dist/ipc/transport/index.js.map +1 -0
  360. package/dist/ipc/transport/jsonl.d.ts +39 -0
  361. package/dist/ipc/transport/jsonl.d.ts.map +1 -0
  362. package/dist/ipc/transport/jsonl.js +61 -0
  363. package/dist/ipc/transport/jsonl.js.map +1 -0
  364. package/dist/ipc/transport/socket.d.ts +27 -0
  365. package/dist/ipc/transport/socket.d.ts.map +1 -0
  366. package/dist/ipc/transport/socket.js +49 -0
  367. package/dist/ipc/transport/socket.js.map +1 -0
  368. package/dist/ipc/transport/validation.d.ts +21 -0
  369. package/dist/ipc/transport/validation.d.ts.map +1 -0
  370. package/dist/ipc/transport/validation.js +23 -0
  371. package/dist/ipc/transport/validation.js.map +1 -0
  372. package/dist/ipc/utils/errors.d.ts +25 -0
  373. package/dist/ipc/utils/errors.d.ts.map +1 -0
  374. package/dist/ipc/utils/errors.js +29 -0
  375. package/dist/ipc/utils/errors.js.map +1 -0
  376. package/dist/ipc/utils/index.d.ts +12 -0
  377. package/dist/ipc/utils/index.d.ts.map +1 -0
  378. package/dist/ipc/utils/index.js +11 -0
  379. package/dist/ipc/utils/index.js.map +1 -0
  380. package/dist/ipc/utils/requestId.d.ts +23 -0
  381. package/dist/ipc/utils/requestId.d.ts.map +1 -0
  382. package/dist/ipc/utils/requestId.js +27 -0
  383. package/dist/ipc/utils/requestId.js.map +1 -0
  384. package/dist/ipc/utils/responseValidator.d.ts.map +1 -0
  385. package/dist/ipc/{responseValidator.js → utils/responseValidator.js} +2 -1
  386. package/dist/ipc/utils/responseValidator.js.map +1 -0
  387. package/dist/ipc/utils/session.d.ts +36 -0
  388. package/dist/ipc/utils/session.d.ts.map +1 -0
  389. package/dist/ipc/utils/session.js +37 -0
  390. package/dist/ipc/utils/session.js.map +1 -0
  391. package/dist/ipc/utils/types.d.ts +17 -0
  392. package/dist/ipc/utils/types.d.ts.map +1 -0
  393. package/dist/ipc/utils/types.js +7 -0
  394. package/dist/ipc/utils/types.js.map +1 -0
  395. package/dist/session/__tests__/chrome-cache.contract.test.d.ts +7 -0
  396. package/dist/session/__tests__/chrome-cache.contract.test.d.ts.map +1 -0
  397. package/dist/session/__tests__/chrome-cache.contract.test.js +77 -0
  398. package/dist/session/__tests__/chrome-cache.contract.test.js.map +1 -0
  399. package/dist/session/__tests__/cleanup.contract.test.d.ts +7 -0
  400. package/dist/session/__tests__/cleanup.contract.test.d.ts.map +1 -0
  401. package/dist/session/__tests__/cleanup.contract.test.js +84 -0
  402. package/dist/session/__tests__/cleanup.contract.test.js.map +1 -0
  403. package/dist/session/__tests__/lock.contract.test.d.ts +7 -0
  404. package/dist/session/__tests__/lock.contract.test.d.ts.map +1 -0
  405. package/dist/session/__tests__/lock.contract.test.js +77 -0
  406. package/dist/session/__tests__/lock.contract.test.js.map +1 -0
  407. package/dist/session/__tests__/metadata.contract.test.d.ts +7 -0
  408. package/dist/session/__tests__/metadata.contract.test.d.ts.map +1 -0
  409. package/dist/session/__tests__/metadata.contract.test.js +87 -0
  410. package/dist/session/__tests__/metadata.contract.test.js.map +1 -0
  411. package/dist/session/chrome.d.ts +20 -0
  412. package/dist/session/chrome.d.ts.map +1 -1
  413. package/dist/session/chrome.js +81 -17
  414. package/dist/session/chrome.js.map +1 -1
  415. package/dist/session/cleanup.d.ts +36 -2
  416. package/dist/session/cleanup.d.ts.map +1 -1
  417. package/dist/session/cleanup.js +201 -73
  418. package/dist/session/cleanup.js.map +1 -1
  419. package/dist/session/lock.d.ts.map +1 -1
  420. package/dist/session/lock.js +102 -91
  421. package/dist/session/lock.js.map +1 -1
  422. package/dist/session/metadata.d.ts +10 -3
  423. package/dist/session/metadata.d.ts.map +1 -1
  424. package/dist/session/metadata.js +24 -6
  425. package/dist/session/metadata.js.map +1 -1
  426. package/dist/session/paths.d.ts +0 -9
  427. package/dist/session/paths.d.ts.map +1 -1
  428. package/dist/session/paths.js +0 -11
  429. package/dist/session/paths.js.map +1 -1
  430. package/dist/session/pid.d.ts +15 -0
  431. package/dist/session/pid.d.ts.map +1 -1
  432. package/dist/session/pid.js +39 -21
  433. package/dist/session/pid.js.map +1 -1
  434. package/dist/session/process.d.ts +4 -41
  435. package/dist/session/process.d.ts.map +1 -1
  436. package/dist/session/process.js +4 -85
  437. package/dist/session/process.js.map +1 -1
  438. package/dist/session/statusData.d.ts +50 -0
  439. package/dist/session/statusData.d.ts.map +1 -0
  440. package/dist/session/statusData.js +51 -0
  441. package/dist/session/statusData.js.map +1 -0
  442. package/dist/telemetry/__tests__/a11y.unit.test.d.ts +10 -0
  443. package/dist/telemetry/__tests__/a11y.unit.test.d.ts.map +1 -0
  444. package/dist/telemetry/__tests__/a11y.unit.test.js +265 -0
  445. package/dist/telemetry/__tests__/a11y.unit.test.js.map +1 -0
  446. package/dist/telemetry/__tests__/navigation.contract.test.d.ts +8 -0
  447. package/dist/telemetry/__tests__/navigation.contract.test.d.ts.map +1 -0
  448. package/dist/telemetry/__tests__/navigation.contract.test.js +211 -0
  449. package/dist/telemetry/__tests__/navigation.contract.test.js.map +1 -0
  450. package/dist/telemetry/__tests__/network.contract.test.d.ts +0 -20
  451. package/dist/telemetry/__tests__/network.contract.test.d.ts.map +1 -1
  452. package/dist/telemetry/__tests__/network.contract.test.js +2 -64
  453. package/dist/telemetry/__tests__/network.contract.test.js.map +1 -1
  454. package/dist/telemetry/__tests__/utils.unit.test.d.ts +7 -0
  455. package/dist/telemetry/__tests__/utils.unit.test.d.ts.map +1 -0
  456. package/dist/telemetry/__tests__/utils.unit.test.js +91 -0
  457. package/dist/telemetry/__tests__/utils.unit.test.js.map +1 -0
  458. package/dist/telemetry/a11y.d.ts +78 -0
  459. package/dist/telemetry/a11y.d.ts.map +1 -0
  460. package/dist/telemetry/a11y.js +280 -0
  461. package/dist/telemetry/a11y.js.map +1 -0
  462. package/dist/telemetry/console.d.ts.map +1 -1
  463. package/dist/telemetry/console.js +19 -28
  464. package/dist/telemetry/console.js.map +1 -1
  465. package/dist/telemetry/dialogs.d.ts.map +1 -1
  466. package/dist/telemetry/dialogs.js +4 -8
  467. package/dist/telemetry/dialogs.js.map +1 -1
  468. package/dist/telemetry/dom.d.ts +1 -1
  469. package/dist/telemetry/dom.d.ts.map +1 -1
  470. package/dist/telemetry/dom.js +83 -60
  471. package/dist/telemetry/dom.js.map +1 -1
  472. package/dist/telemetry/filters.d.ts +5 -18
  473. package/dist/telemetry/filters.d.ts.map +1 -1
  474. package/dist/telemetry/filters.js +36 -56
  475. package/dist/telemetry/filters.js.map +1 -1
  476. package/dist/telemetry/navigation.d.ts.map +1 -1
  477. package/dist/telemetry/navigation.js +5 -8
  478. package/dist/telemetry/navigation.js.map +1 -1
  479. package/dist/telemetry/network.d.ts.map +1 -1
  480. package/dist/telemetry/network.js +105 -104
  481. package/dist/telemetry/network.js.map +1 -1
  482. package/dist/telemetry/utils.d.ts +85 -0
  483. package/dist/telemetry/utils.d.ts.map +1 -0
  484. package/dist/telemetry/utils.js +138 -0
  485. package/dist/telemetry/utils.js.map +1 -0
  486. package/dist/types/dom.d.ts +66 -0
  487. package/dist/types/dom.d.ts.map +1 -0
  488. package/dist/types/dom.js +8 -0
  489. package/dist/types/dom.js.map +1 -0
  490. package/dist/types.d.ts +86 -77
  491. package/dist/types.d.ts.map +1 -1
  492. package/dist/{commands/shared → ui}/OutputBuilder.d.ts +10 -2
  493. package/dist/ui/OutputBuilder.d.ts.map +1 -0
  494. package/dist/{commands/shared → ui}/OutputBuilder.js +8 -2
  495. package/dist/ui/OutputBuilder.js.map +1 -0
  496. package/dist/ui/errors/CommandError.d.ts +16 -2
  497. package/dist/ui/errors/CommandError.d.ts.map +1 -1
  498. package/dist/ui/errors/CommandError.js +2 -1
  499. package/dist/ui/errors/CommandError.js.map +1 -1
  500. package/dist/ui/errors/index.d.ts +2 -3
  501. package/dist/ui/errors/index.d.ts.map +1 -1
  502. package/dist/ui/errors/index.js +1 -3
  503. package/dist/ui/errors/index.js.map +1 -1
  504. package/dist/ui/errors/utils.d.ts +6 -0
  505. package/dist/ui/errors/utils.d.ts.map +1 -1
  506. package/dist/ui/errors/utils.js +8 -3
  507. package/dist/ui/errors/utils.js.map +1 -1
  508. package/dist/ui/formatters/__tests__/semantic.unit.test.d.ts +2 -0
  509. package/dist/ui/formatters/__tests__/semantic.unit.test.d.ts.map +1 -0
  510. package/dist/ui/formatters/__tests__/semantic.unit.test.js +111 -0
  511. package/dist/ui/formatters/__tests__/semantic.unit.test.js.map +1 -0
  512. package/dist/ui/formatters/a11y.d.ts +30 -0
  513. package/dist/ui/formatters/a11y.d.ts.map +1 -0
  514. package/dist/ui/formatters/a11y.js +178 -0
  515. package/dist/ui/formatters/a11y.js.map +1 -0
  516. package/dist/ui/formatters/dom.d.ts +3 -18
  517. package/dist/ui/formatters/dom.d.ts.map +1 -1
  518. package/dist/ui/formatters/dom.js +4 -27
  519. package/dist/ui/formatters/dom.js.map +1 -1
  520. package/dist/ui/formatters/preview.d.ts +10 -8
  521. package/dist/ui/formatters/preview.d.ts.map +1 -1
  522. package/dist/ui/formatters/preview.js +45 -17
  523. package/dist/ui/formatters/preview.js.map +1 -1
  524. package/dist/ui/formatters/semantic.d.ts +36 -0
  525. package/dist/ui/formatters/semantic.d.ts.map +1 -0
  526. package/dist/ui/formatters/semantic.js +98 -0
  527. package/dist/ui/formatters/semantic.js.map +1 -0
  528. package/dist/ui/formatters/status.d.ts +1 -1
  529. package/dist/ui/formatters/status.d.ts.map +1 -1
  530. package/dist/ui/formatters/status.js +9 -31
  531. package/dist/ui/formatters/status.js.map +1 -1
  532. package/dist/ui/formatting.d.ts +2 -270
  533. package/dist/ui/formatting.d.ts.map +1 -1
  534. package/dist/ui/formatting.js +8 -331
  535. package/dist/ui/formatting.js.map +1 -1
  536. package/dist/ui/logging/index.d.ts +1 -1
  537. package/dist/ui/logging/index.d.ts.map +1 -1
  538. package/dist/ui/logging/index.js +1 -1
  539. package/dist/ui/logging/index.js.map +1 -1
  540. package/dist/ui/logging/logger.d.ts +3 -23
  541. package/dist/ui/logging/logger.d.ts.map +1 -1
  542. package/dist/ui/logging/logger.js +2 -27
  543. package/dist/ui/logging/logger.js.map +1 -1
  544. package/dist/ui/messages/chrome.d.ts +15 -7
  545. package/dist/ui/messages/chrome.d.ts.map +1 -1
  546. package/dist/ui/messages/chrome.js +23 -32
  547. package/dist/ui/messages/chrome.js.map +1 -1
  548. package/dist/ui/messages/commands.d.ts +9 -19
  549. package/dist/ui/messages/commands.d.ts.map +1 -1
  550. package/dist/ui/messages/commands.js +14 -51
  551. package/dist/ui/messages/commands.js.map +1 -1
  552. package/dist/ui/messages/consoleMessages.d.ts +1 -1
  553. package/dist/ui/messages/consoleMessages.d.ts.map +1 -1
  554. package/dist/ui/messages/consoleMessages.js +3 -6
  555. package/dist/ui/messages/consoleMessages.js.map +1 -1
  556. package/dist/ui/messages/debug.d.ts +0 -14
  557. package/dist/ui/messages/debug.d.ts.map +1 -1
  558. package/dist/ui/messages/debug.js +0 -18
  559. package/dist/ui/messages/debug.js.map +1 -1
  560. package/dist/ui/messages/errors.d.ts +0 -34
  561. package/dist/ui/messages/errors.d.ts.map +1 -1
  562. package/dist/ui/messages/errors.js +3 -81
  563. package/dist/ui/messages/errors.js.map +1 -1
  564. package/dist/ui/messages/internal.d.ts +0 -7
  565. package/dist/ui/messages/internal.d.ts.map +1 -1
  566. package/dist/ui/messages/internal.js +0 -12
  567. package/dist/ui/messages/internal.js.map +1 -1
  568. package/dist/ui/messages/preview.d.ts +14 -1
  569. package/dist/ui/messages/preview.d.ts.map +1 -1
  570. package/dist/ui/messages/preview.js +24 -7
  571. package/dist/ui/messages/preview.js.map +1 -1
  572. package/dist/ui/messages/session.d.ts.map +1 -1
  573. package/dist/ui/messages/session.js +7 -23
  574. package/dist/ui/messages/session.js.map +1 -1
  575. package/dist/ui/messages/validation.d.ts.map +1 -1
  576. package/dist/ui/messages/validation.js +7 -8
  577. package/dist/ui/messages/validation.js.map +1 -1
  578. package/dist/utils/__tests__/atomicFile.test.d.ts +2 -0
  579. package/dist/utils/__tests__/atomicFile.test.d.ts.map +1 -0
  580. package/dist/utils/__tests__/atomicFile.test.js +43 -0
  581. package/dist/utils/__tests__/atomicFile.test.js.map +1 -0
  582. package/dist/utils/__tests__/errors.unit.test.d.ts +12 -0
  583. package/dist/utils/__tests__/errors.unit.test.d.ts.map +1 -0
  584. package/dist/utils/__tests__/errors.unit.test.js +255 -0
  585. package/dist/utils/__tests__/errors.unit.test.js.map +1 -0
  586. package/dist/utils/__tests__/http.unit.test.d.ts +12 -0
  587. package/dist/utils/__tests__/http.unit.test.d.ts.map +1 -0
  588. package/dist/utils/__tests__/http.unit.test.js +218 -0
  589. package/dist/utils/__tests__/http.unit.test.js.map +1 -0
  590. package/dist/utils/__tests__/objects.test.d.ts +2 -0
  591. package/dist/utils/__tests__/objects.test.d.ts.map +1 -0
  592. package/dist/utils/__tests__/objects.test.js +50 -0
  593. package/dist/utils/__tests__/objects.test.js.map +1 -0
  594. package/dist/utils/__tests__/process.unit.test.d.ts +14 -0
  595. package/dist/utils/__tests__/process.unit.test.d.ts.map +1 -0
  596. package/dist/utils/__tests__/process.unit.test.js +124 -0
  597. package/dist/utils/__tests__/process.unit.test.js.map +1 -0
  598. package/dist/utils/__tests__/session.contract.test.js +14 -4
  599. package/dist/utils/__tests__/session.contract.test.js.map +1 -1
  600. package/dist/utils/__tests__/url.test.d.ts +2 -0
  601. package/dist/utils/__tests__/url.test.d.ts.map +1 -0
  602. package/dist/utils/__tests__/url.test.js +42 -0
  603. package/dist/utils/__tests__/url.test.js.map +1 -0
  604. package/dist/utils/atomicFile.d.ts +31 -5
  605. package/dist/utils/atomicFile.d.ts.map +1 -1
  606. package/dist/utils/atomicFile.js +52 -13
  607. package/dist/utils/atomicFile.js.map +1 -1
  608. package/dist/utils/concurrency.d.ts +54 -0
  609. package/dist/utils/concurrency.d.ts.map +1 -0
  610. package/dist/utils/concurrency.js +78 -0
  611. package/dist/utils/concurrency.js.map +1 -0
  612. package/dist/utils/daemonErrors.d.ts +60 -0
  613. package/dist/utils/daemonErrors.d.ts.map +1 -0
  614. package/dist/utils/daemonErrors.js +58 -0
  615. package/dist/utils/daemonErrors.js.map +1 -0
  616. package/dist/utils/errors.d.ts +28 -0
  617. package/dist/utils/errors.d.ts.map +1 -0
  618. package/dist/utils/errors.js +33 -0
  619. package/dist/utils/errors.js.map +1 -0
  620. package/dist/utils/exitCodes.d.ts +41 -5
  621. package/dist/utils/exitCodes.d.ts.map +1 -1
  622. package/dist/utils/exitCodes.js +43 -9
  623. package/dist/utils/exitCodes.js.map +1 -1
  624. package/dist/utils/http.d.ts +9 -4
  625. package/dist/utils/http.d.ts.map +1 -1
  626. package/dist/utils/http.js +44 -10
  627. package/dist/utils/http.js.map +1 -1
  628. package/dist/utils/levenshtein.d.ts +45 -0
  629. package/dist/utils/levenshtein.d.ts.map +1 -0
  630. package/dist/utils/levenshtein.js +85 -0
  631. package/dist/utils/levenshtein.js.map +1 -0
  632. package/dist/utils/objects.d.ts +16 -1
  633. package/dist/utils/objects.d.ts.map +1 -1
  634. package/dist/utils/objects.js +16 -1
  635. package/dist/utils/objects.js.map +1 -1
  636. package/dist/utils/process.d.ts +45 -0
  637. package/dist/utils/process.d.ts.map +1 -0
  638. package/dist/utils/process.js +91 -0
  639. package/dist/utils/process.js.map +1 -0
  640. package/dist/utils/url.d.ts +10 -3
  641. package/dist/utils/url.d.ts.map +1 -1
  642. package/dist/utils/url.js +42 -29
  643. package/dist/utils/url.js.map +1 -1
  644. package/dist/utils/validation.d.ts +101 -0
  645. package/dist/utils/validation.d.ts.map +1 -0
  646. package/dist/utils/validation.js +131 -0
  647. package/dist/utils/validation.js.map +1 -0
  648. package/package.json +22 -1
  649. package/dist/commands/dom.d.ts.map +0 -1
  650. package/dist/commands/dom.js +0 -244
  651. package/dist/commands/dom.js.map +0 -1
  652. package/dist/commands/domEvalHelpers.d.ts.map +0 -1
  653. package/dist/commands/domEvalHelpers.js.map +0 -1
  654. package/dist/commands/domOptionsBuilder.d.ts +0 -67
  655. package/dist/commands/domOptionsBuilder.d.ts.map +0 -1
  656. package/dist/commands/domOptionsBuilder.js +0 -86
  657. package/dist/commands/domOptionsBuilder.js.map +0 -1
  658. package/dist/commands/domSelectorParser.d.ts +0 -20
  659. package/dist/commands/domSelectorParser.d.ts.map +0 -1
  660. package/dist/commands/domSelectorParser.js +0 -20
  661. package/dist/commands/domSelectorParser.js.map +0 -1
  662. package/dist/commands/shared/OutputBuilder.d.ts.map +0 -1
  663. package/dist/commands/shared/OutputBuilder.js.map +0 -1
  664. package/dist/commands/shared/daemonSessionController.d.ts.map +0 -1
  665. package/dist/commands/shared/daemonSessionController.js.map +0 -1
  666. package/dist/commands/shared/sessionController.d.ts +0 -21
  667. package/dist/commands/shared/sessionController.d.ts.map +0 -1
  668. package/dist/commands/shared/sessionController.js +0 -54
  669. package/dist/commands/shared/sessionController.js.map +0 -1
  670. package/dist/connection/__tests__/finder.contract.test.d.ts +0 -2
  671. package/dist/connection/__tests__/finder.contract.test.d.ts.map +0 -1
  672. package/dist/connection/__tests__/finder.contract.test.js +0 -239
  673. package/dist/connection/__tests__/finder.contract.test.js.map +0 -1
  674. package/dist/connection/domOperations.d.ts +0 -48
  675. package/dist/connection/domOperations.d.ts.map +0 -1
  676. package/dist/connection/domOperations.js +0 -106
  677. package/dist/connection/domOperations.js.map +0 -1
  678. package/dist/connection/finder.d.ts +0 -12
  679. package/dist/connection/finder.d.ts.map +0 -1
  680. package/dist/connection/finder.js +0 -17
  681. package/dist/connection/finder.js.map +0 -1
  682. package/dist/ipc/commands.d.ts +0 -260
  683. package/dist/ipc/commands.d.ts.map +0 -1
  684. package/dist/ipc/commands.js +0 -77
  685. package/dist/ipc/commands.js.map +0 -1
  686. package/dist/ipc/responseValidator.d.ts.map +0 -1
  687. package/dist/ipc/responseValidator.js.map +0 -1
  688. package/dist/ipc/types.d.ts +0 -226
  689. package/dist/ipc/types.d.ts.map +0 -1
  690. package/dist/ipc/types.js.map +0 -1
  691. package/dist/session/fileOps.d.ts +0 -25
  692. package/dist/session/fileOps.d.ts.map +0 -1
  693. package/dist/session/fileOps.js +0 -39
  694. package/dist/session/fileOps.js.map +0 -1
  695. package/dist/session/queryCache.d.ts +0 -36
  696. package/dist/session/queryCache.d.ts.map +0 -1
  697. package/dist/session/queryCache.js +0 -66
  698. package/dist/session/queryCache.js.map +0 -1
  699. /package/dist/ipc/{responseValidator.d.ts → utils/responseValidator.d.ts} +0 -0
@@ -0,0 +1,382 @@
1
+ /**
2
+ * Contract tests for page readiness detection
3
+ *
4
+ * Tests the contract: wait for load → network stable → DOM stable OR timeout
5
+ *
6
+ * Philosophy: Test the state machine behavior using a mock CDP connection.
7
+ * We don't test timing-sensitive behavior (exact ms), we test the sequence
8
+ * of operations and state transitions.
9
+ *
10
+ * These are contract tests because they validate the multi-phase readiness
11
+ * detection contract without caring about internal implementation.
12
+ */
13
+ import assert from 'node:assert/strict';
14
+ import { describe, test } from 'node:test';
15
+ import { waitForPageReady } from '../../connection/pageReadiness.js';
16
+ describe('Page Readiness - Happy Path', () => {
17
+ test('waits through all three phases (load → network → DOM)', async () => {
18
+ const phases = [];
19
+ const mockCDP = createMockCDP({
20
+ onSend: (method) => {
21
+ phases.push(method);
22
+ },
23
+ loadEventAlreadyFired: false,
24
+ networkQuiet: true,
25
+ domStable: true,
26
+ });
27
+ await waitForPageReady(mockCDP);
28
+ // Contract: should enable Page and Network domains
29
+ assert.ok(phases.includes('Page.enable'), 'Should enable Page domain');
30
+ assert.ok(phases.includes('Network.enable'), 'Should enable Network domain');
31
+ // Contract: should check document.readyState
32
+ assert.ok(phases.some((p) => p.includes('Runtime.evaluate')), 'Should check document readiness');
33
+ });
34
+ test('handles page where load event already fired', async () => {
35
+ const mockCDP = createMockCDP({
36
+ loadEventAlreadyFired: true,
37
+ networkQuiet: true,
38
+ domStable: true,
39
+ });
40
+ // Contract: should not wait for load event if already complete
41
+ await waitForPageReady(mockCDP);
42
+ // Should complete without error
43
+ assert.ok(true, 'Should handle already-loaded page');
44
+ });
45
+ test('proceeds when network stabilizes', async () => {
46
+ const mockCDP = createMockCDP({
47
+ loadEventAlreadyFired: true,
48
+ networkQuiet: true,
49
+ domStable: true,
50
+ });
51
+ await waitForPageReady(mockCDP);
52
+ // Should complete network phase
53
+ assert.ok(true, 'Should proceed when network is stable');
54
+ });
55
+ test('proceeds when DOM stabilizes', async () => {
56
+ const mockCDP = createMockCDP({
57
+ loadEventAlreadyFired: true,
58
+ networkQuiet: true,
59
+ domStable: true,
60
+ });
61
+ await waitForPageReady(mockCDP);
62
+ // Should complete DOM phase
63
+ assert.ok(true, 'Should proceed when DOM is stable');
64
+ });
65
+ });
66
+ describe('Page Readiness - Timeout Behavior', () => {
67
+ test('proceeds on timeout without throwing', async () => {
68
+ const mockCDP = createMockCDP({
69
+ loadEventAlreadyFired: false,
70
+ networkQuiet: false, // Never becomes quiet
71
+ domStable: false, // Never stabilizes
72
+ delayLoadEvent: true, // Delay to trigger timeout
73
+ });
74
+ // Contract: should NOT throw on timeout, should proceed anyway
75
+ await assert.doesNotReject(async () => {
76
+ await waitForPageReady(mockCDP, { maxWaitMs: 100 });
77
+ }, 'Should not throw on timeout');
78
+ });
79
+ test('respects custom maxWaitMs option', async () => {
80
+ const mockCDP = createMockCDP({
81
+ loadEventAlreadyFired: false,
82
+ networkQuiet: false,
83
+ domStable: false,
84
+ delayLoadEvent: true,
85
+ });
86
+ const start = Date.now();
87
+ await waitForPageReady(mockCDP, { maxWaitMs: 200 });
88
+ const duration = Date.now() - start;
89
+ // Should timeout around 200ms (with some tolerance for scheduling)
90
+ assert.ok(duration >= 150 && duration < 400, 'Should respect custom timeout');
91
+ });
92
+ test('uses default 5000ms timeout when not specified', async () => {
93
+ const mockCDP = createMockCDP({
94
+ loadEventAlreadyFired: true,
95
+ networkQuiet: true,
96
+ domStable: true,
97
+ });
98
+ const start = Date.now();
99
+ await waitForPageReady(mockCDP); // No options
100
+ const duration = Date.now() - start;
101
+ // Should complete quickly when stable (not wait full 5s)
102
+ assert.ok(duration < 1000, 'Should not wait unnecessarily when page is ready');
103
+ });
104
+ });
105
+ describe('Page Readiness - Load Event Phase', () => {
106
+ test('waits for Page.loadEventFired when not already loaded', async () => {
107
+ let loadEventFired = false;
108
+ const mockCDP = createMockCDP({
109
+ loadEventAlreadyFired: false,
110
+ networkQuiet: true,
111
+ domStable: true,
112
+ onEventRegistered: (event) => {
113
+ if (event === 'Page.loadEventFired') {
114
+ // Simulate load event firing after a delay
115
+ setTimeout(() => {
116
+ loadEventFired = true;
117
+ mockCDP.emit('Page.loadEventFired', {});
118
+ }, 50);
119
+ }
120
+ },
121
+ });
122
+ await waitForPageReady(mockCDP, { maxWaitMs: 500 });
123
+ assert.ok(loadEventFired, 'Should wait for and receive load event');
124
+ });
125
+ test('skips waiting for load event when document.readyState is complete', async () => {
126
+ const events = [];
127
+ const mockCDP = createMockCDP({
128
+ loadEventAlreadyFired: true,
129
+ networkQuiet: true,
130
+ domStable: true,
131
+ onEventRegistered: (event) => {
132
+ events.push(event);
133
+ },
134
+ });
135
+ await waitForPageReady(mockCDP);
136
+ // Contract: should not register for Page.loadEventFired if already complete
137
+ // (though it's okay if it does register and immediately continues)
138
+ assert.ok(true, 'Should handle pre-loaded page');
139
+ });
140
+ test('handles Runtime.evaluate errors gracefully', async () => {
141
+ const mockCDP = createMockCDP({
142
+ loadEventAlreadyFired: false,
143
+ networkQuiet: true,
144
+ domStable: true,
145
+ evaluateThrows: true,
146
+ });
147
+ // Contract: should proceed even if readyState check fails
148
+ await assert.doesNotReject(async () => {
149
+ await waitForPageReady(mockCDP, { maxWaitMs: 200 });
150
+ }, 'Should handle evaluate errors gracefully');
151
+ });
152
+ });
153
+ describe('Page Readiness - Network Stability Phase', () => {
154
+ test('detects network activity via requestWillBeSent events', async () => {
155
+ const events = [];
156
+ const mockCDP = createMockCDP({
157
+ loadEventAlreadyFired: true,
158
+ networkQuiet: false,
159
+ domStable: true,
160
+ onEventRegistered: (event) => {
161
+ events.push(event);
162
+ },
163
+ });
164
+ await waitForPageReady(mockCDP, { maxWaitMs: 200 });
165
+ // Contract: should listen for network events
166
+ assert.ok(events.includes('Network.requestWillBeSent'), 'Should listen for network requests');
167
+ assert.ok(events.includes('Network.loadingFinished'), 'Should listen for loading finished');
168
+ assert.ok(events.includes('Network.loadingFailed'), 'Should listen for loading failed');
169
+ });
170
+ test('tracks active requests (requestWillBeSent increases, responses decrease)', async () => {
171
+ const mockCDP = createMockCDP({
172
+ loadEventAlreadyFired: true,
173
+ networkQuiet: false,
174
+ domStable: true,
175
+ onEventRegistered: (event) => {
176
+ if (event === 'Network.requestWillBeSent') {
177
+ // Simulate request/response cycle
178
+ setTimeout(() => {
179
+ mockCDP.emit('Network.requestWillBeSent', {});
180
+ setTimeout(() => {
181
+ mockCDP.emit('Network.loadingFinished', {});
182
+ }, 50);
183
+ }, 30);
184
+ }
185
+ },
186
+ });
187
+ await waitForPageReady(mockCDP, { maxWaitMs: 500 });
188
+ // Network phase should have completed
189
+ assert.ok(true, 'Should track network request lifecycle');
190
+ });
191
+ test('waits for 200ms of network idle before proceeding', async () => {
192
+ // This test verifies the threshold concept but not exact timing
193
+ const mockCDP = createMockCDP({
194
+ loadEventAlreadyFired: true,
195
+ networkQuiet: true,
196
+ domStable: true,
197
+ });
198
+ await waitForPageReady(mockCDP);
199
+ // Contract: should wait for network stability (implementation uses 200ms threshold)
200
+ assert.ok(true, 'Should wait for network stability threshold');
201
+ });
202
+ });
203
+ describe('Page Readiness - DOM Stability Phase', () => {
204
+ test('injects MutationObserver into page', async () => {
205
+ const evaluations = [];
206
+ const mockCDP = createMockCDP({
207
+ loadEventAlreadyFired: true,
208
+ networkQuiet: true,
209
+ domStable: true,
210
+ onSend: (method, params) => {
211
+ if (method === 'Runtime.evaluate' && params?.['expression']) {
212
+ evaluations.push(params['expression']);
213
+ }
214
+ },
215
+ });
216
+ await waitForPageReady(mockCDP);
217
+ // Contract: should inject MutationObserver
218
+ const hasObserver = evaluations.some((expr) => expr.includes('MutationObserver'));
219
+ assert.ok(hasObserver, 'Should inject MutationObserver for DOM tracking');
220
+ });
221
+ test('cleans up MutationObserver after detection', async () => {
222
+ const evaluations = [];
223
+ const mockCDP = createMockCDP({
224
+ loadEventAlreadyFired: true,
225
+ networkQuiet: true,
226
+ domStable: true,
227
+ onSend: (method, params) => {
228
+ if (method === 'Runtime.evaluate' && params?.['expression']) {
229
+ evaluations.push(params['expression']);
230
+ }
231
+ },
232
+ });
233
+ await waitForPageReady(mockCDP);
234
+ // Contract: should clean up observer
235
+ const hasCleanup = evaluations.some((expr) => expr.includes('disconnect') || expr.includes('delete window.__bdg'));
236
+ assert.ok(hasCleanup, 'Should clean up MutationObserver after detection');
237
+ });
238
+ test('waits for 300ms of DOM stability before proceeding', async () => {
239
+ // This test verifies the threshold concept but not exact timing
240
+ const mockCDP = createMockCDP({
241
+ loadEventAlreadyFired: true,
242
+ networkQuiet: true,
243
+ domStable: true,
244
+ });
245
+ await waitForPageReady(mockCDP);
246
+ // Contract: should wait for DOM stability threshold (implementation uses 300ms)
247
+ assert.ok(true, 'Should wait for DOM stability threshold');
248
+ });
249
+ test('handles missing document.body gracefully', async () => {
250
+ const mockCDP = createMockCDP({
251
+ loadEventAlreadyFired: true,
252
+ networkQuiet: true,
253
+ domStable: true,
254
+ evaluateThrows: true, // Simulate errors injecting observer
255
+ });
256
+ // Contract: should handle observer injection failures
257
+ await assert.doesNotReject(async () => {
258
+ await waitForPageReady(mockCDP, { maxWaitMs: 200 });
259
+ }, 'Should handle missing document.body');
260
+ });
261
+ });
262
+ describe('Page Readiness - Event Handler Cleanup', () => {
263
+ test('removes load event listener after phase completes', async () => {
264
+ const offCalls = [];
265
+ const mockCDP = createMockCDP({
266
+ loadEventAlreadyFired: false,
267
+ networkQuiet: true,
268
+ domStable: true,
269
+ onOff: (event) => {
270
+ offCalls.push(event);
271
+ },
272
+ });
273
+ // Fire load event to complete phase
274
+ setTimeout(() => mockCDP.emit('Page.loadEventFired', {}), 50);
275
+ await waitForPageReady(mockCDP, { maxWaitMs: 500 });
276
+ // Contract: should clean up load event listener
277
+ assert.ok(offCalls.includes('Page.loadEventFired'), 'Should remove Page.loadEventFired listener');
278
+ });
279
+ test('removes network event listeners after phase completes', async () => {
280
+ const offCalls = [];
281
+ const mockCDP = createMockCDP({
282
+ loadEventAlreadyFired: true,
283
+ networkQuiet: true,
284
+ domStable: true,
285
+ onOff: (event) => {
286
+ offCalls.push(event);
287
+ },
288
+ });
289
+ await waitForPageReady(mockCDP);
290
+ // Contract: should clean up all network listeners
291
+ assert.ok(offCalls.includes('Network.requestWillBeSent'), 'Should remove requestWillBeSent listener');
292
+ assert.ok(offCalls.includes('Network.loadingFinished'), 'Should remove loadingFinished listener');
293
+ assert.ok(offCalls.includes('Network.loadingFailed'), 'Should remove loadingFailed listener');
294
+ });
295
+ test('cleans up even when timeout occurs', async () => {
296
+ const offCalls = [];
297
+ const mockCDP = createMockCDP({
298
+ loadEventAlreadyFired: false,
299
+ networkQuiet: false,
300
+ domStable: false,
301
+ delayLoadEvent: true,
302
+ onOff: (event) => {
303
+ offCalls.push(event);
304
+ },
305
+ });
306
+ await waitForPageReady(mockCDP, { maxWaitMs: 100 });
307
+ // Contract: should clean up even on timeout
308
+ assert.ok(offCalls.length > 0, 'Should clean up listeners even on timeout');
309
+ });
310
+ });
311
+ /**
312
+ * Create a mock CDPConnection for testing page readiness
313
+ */
314
+ function createMockCDP(options = {}) {
315
+ const { loadEventAlreadyFired = false, domStable = true, delayLoadEvent = false, evaluateThrows = false, onSend, onEventRegistered, onOff, } = options;
316
+ const handlers = new Map();
317
+ let handlerId = 0;
318
+ const mock = {
319
+ send(method, params) {
320
+ onSend?.(method, params);
321
+ if (method === 'Page.enable' || method === 'Network.enable') {
322
+ return Promise.resolve({});
323
+ }
324
+ if (method === 'Runtime.evaluate') {
325
+ if (evaluateThrows) {
326
+ throw new Error('Evaluation failed');
327
+ }
328
+ const expression = params?.['expression'];
329
+ // Mock document.readyState check
330
+ if (expression?.includes('document.readyState')) {
331
+ return Promise.resolve({
332
+ result: {
333
+ value: loadEventAlreadyFired ? 'complete' : 'loading',
334
+ },
335
+ });
336
+ }
337
+ // Mock MutationObserver injection
338
+ if (expression?.includes('MutationObserver')) {
339
+ return Promise.resolve({ result: {} });
340
+ }
341
+ // Mock DOM stability check
342
+ if (expression?.includes('__bdg_lastMutation')) {
343
+ const timeSinceLastMutation = domStable ? 500 : 0; // 500ms > 300ms threshold
344
+ return Promise.resolve({
345
+ result: {
346
+ value: timeSinceLastMutation,
347
+ },
348
+ });
349
+ }
350
+ return Promise.resolve({ result: {} });
351
+ }
352
+ return Promise.resolve({});
353
+ },
354
+ on(event, handler) {
355
+ onEventRegistered?.(event);
356
+ if (!handlers.has(event)) {
357
+ handlers.set(event, new Map());
358
+ }
359
+ const id = handlerId++;
360
+ handlers.get(event)?.set(id, handler);
361
+ // Auto-fire load event if configured
362
+ if (event === 'Page.loadEventFired' && !delayLoadEvent) {
363
+ setTimeout(() => {
364
+ handler({});
365
+ }, 10);
366
+ }
367
+ return () => this.off(event, id);
368
+ },
369
+ off(event, id) {
370
+ onOff?.(event);
371
+ handlers.get(event)?.delete(id);
372
+ },
373
+ emit(event, params) {
374
+ const eventHandlers = handlers.get(event);
375
+ if (eventHandlers) {
376
+ eventHandlers.forEach((handler) => handler(params));
377
+ }
378
+ },
379
+ };
380
+ return mock;
381
+ }
382
+ //# sourceMappingURL=pageReadiness.contract.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageReadiness.contract.test.js","sourceRoot":"","sources":["../../../src/connection/__tests__/pageReadiness.contract.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Contract tests for port reservation
3
+ *
4
+ * Tests the contract: reserve port atomically OR throw ChromeLaunchError
5
+ *
6
+ * Philosophy: Test with real network sockets to validate actual behavior.
7
+ * Port reservation is an I/O operation that must work correctly in production,
8
+ * so we use real sockets rather than mocks.
9
+ *
10
+ * These are contract tests (not unit tests) because they test the contract
11
+ * between reservePort() and the Node.js net module.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=portReservation.contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portReservation.contract.test.d.ts","sourceRoot":"","sources":["../../../src/connection/__tests__/portReservation.contract.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Contract tests for port reservation
3
+ *
4
+ * Tests the contract: reserve port atomically OR throw ChromeLaunchError
5
+ *
6
+ * Philosophy: Test with real network sockets to validate actual behavior.
7
+ * Port reservation is an I/O operation that must work correctly in production,
8
+ * so we use real sockets rather than mocks.
9
+ *
10
+ * These are contract tests (not unit tests) because they test the contract
11
+ * between reservePort() and the Node.js net module.
12
+ */
13
+ import * as net from 'net';
14
+ import assert from 'node:assert/strict';
15
+ import { describe, test } from 'node:test';
16
+ import { ChromeLaunchError } from '../../connection/errors.js';
17
+ import { reservePort } from '../../connection/portReservation.js';
18
+ describe('Port Reservation - Success Cases', () => {
19
+ test('successfully reserves an available port', async () => {
20
+ const port = await findAvailablePort();
21
+ const reservation = await reservePort(port);
22
+ try {
23
+ // Contract: reservation should have release function
24
+ assert.ok(typeof reservation.release === 'function', 'Should return reservation with release()');
25
+ }
26
+ finally {
27
+ reservation.release();
28
+ }
29
+ });
30
+ test('release() frees the port for reuse', async () => {
31
+ const port = await findAvailablePort();
32
+ const reservation1 = await reservePort(port);
33
+ reservation1.release();
34
+ // Contract: after release, port should be available again
35
+ const reservation2 = await reservePort(port);
36
+ reservation2.release();
37
+ // If we got here without error, port was successfully reused
38
+ assert.ok(true, 'Port should be available after release');
39
+ });
40
+ test('can reserve multiple different ports simultaneously', async () => {
41
+ const port1 = await findAvailablePort();
42
+ const port2 = await findAvailablePort(port1 + 1);
43
+ const reservation1 = await reservePort(port1);
44
+ const reservation2 = await reservePort(port2);
45
+ try {
46
+ assert.ok(reservation1, 'First reservation should succeed');
47
+ assert.ok(reservation2, 'Second reservation should succeed');
48
+ }
49
+ finally {
50
+ reservation1.release();
51
+ reservation2.release();
52
+ }
53
+ });
54
+ test('release() can be called immediately after reservation', async () => {
55
+ const port = await findAvailablePort();
56
+ const reservation = await reservePort(port);
57
+ reservation.release(); // Immediate release
58
+ // Should not throw
59
+ assert.ok(true, 'Immediate release should be safe');
60
+ });
61
+ });
62
+ describe('Port Reservation - Failure Cases', () => {
63
+ test('throws ChromeLaunchError when port is already in use', async () => {
64
+ const port = await findAvailablePort();
65
+ // Occupy the port with a real server
66
+ const server = await createTestServer(port);
67
+ try {
68
+ // Contract: should throw ChromeLaunchError (not generic Error)
69
+ await assert.rejects(async () => {
70
+ await reservePort(port);
71
+ }, (error) => {
72
+ assert.ok(error instanceof ChromeLaunchError, 'Should throw ChromeLaunchError');
73
+ assert.ok(error.message.includes(`${port}`), 'Error message should mention port number');
74
+ assert.ok(error.message.includes('already in use'), 'Error message should indicate port is in use');
75
+ return true;
76
+ }, 'Should throw ChromeLaunchError when port is in use');
77
+ }
78
+ finally {
79
+ await closeServer(server);
80
+ }
81
+ });
82
+ test('fails when attempting to reserve same port twice', async () => {
83
+ const port = await findAvailablePort();
84
+ const reservation = await reservePort(port);
85
+ try {
86
+ // Contract: second reservation should fail with ChromeLaunchError
87
+ await assert.rejects(async () => {
88
+ await reservePort(port);
89
+ }, ChromeLaunchError, 'Should fail when port already reserved');
90
+ }
91
+ finally {
92
+ reservation.release();
93
+ }
94
+ });
95
+ test('error message includes helpful troubleshooting steps', async () => {
96
+ const port = await findAvailablePort();
97
+ const server = await createTestServer(port);
98
+ try {
99
+ await assert.rejects(async () => {
100
+ await reservePort(port);
101
+ }, (error) => {
102
+ // Contract: error message should help user troubleshoot
103
+ assert.ok(error.message.includes('bdg cleanup'), 'Should suggest cleanup command');
104
+ assert.ok(error.message.includes('lsof'), 'Should suggest checking processes');
105
+ assert.ok(error.message.includes(`--port ${port + 1}`), 'Should suggest alternative port');
106
+ return true;
107
+ }, 'Error message should include troubleshooting steps');
108
+ }
109
+ finally {
110
+ await closeServer(server);
111
+ }
112
+ });
113
+ });
114
+ describe('Port Reservation - Release Behavior', () => {
115
+ test('release() closes the server immediately', async () => {
116
+ const port = await findAvailablePort();
117
+ const reservation = await reservePort(port);
118
+ reservation.release();
119
+ // Port should be immediately available (not waiting for async cleanup)
120
+ const testServer = net.createServer();
121
+ const canBind = await new Promise((resolve) => {
122
+ testServer.once('error', () => resolve(false));
123
+ testServer.listen(port, '127.0.0.1', () => {
124
+ testServer.close();
125
+ resolve(true);
126
+ });
127
+ });
128
+ assert.ok(canBind, 'Port should be immediately available after release');
129
+ });
130
+ test('release() can be called multiple times safely', async () => {
131
+ const port = await findAvailablePort();
132
+ const reservation = await reservePort(port);
133
+ // Multiple releases should not throw
134
+ reservation.release();
135
+ reservation.release();
136
+ reservation.release();
137
+ assert.ok(true, 'Multiple release() calls should be safe');
138
+ });
139
+ });
140
+ describe('Port Reservation - Edge Cases', () => {
141
+ test('handles port number at lower boundary (1024)', async () => {
142
+ // Ports < 1024 require root, so we test 1024 (first non-privileged port)
143
+ // This may fail in environments where 1024 is in use - that's expected
144
+ try {
145
+ const reservation = await reservePort(1024);
146
+ reservation.release();
147
+ assert.ok(true, 'Should handle port 1024');
148
+ }
149
+ catch (error) {
150
+ // If port is in use, verify it's the expected error type
151
+ assert.ok(error instanceof ChromeLaunchError, 'Should throw ChromeLaunchError for in-use port 1024');
152
+ }
153
+ });
154
+ test('handles port number at upper boundary (65535)', async () => {
155
+ try {
156
+ const reservation = await reservePort(65535);
157
+ reservation.release();
158
+ assert.ok(true, 'Should handle port 65535');
159
+ }
160
+ catch (error) {
161
+ // If port is in use, verify it's the expected error type
162
+ assert.ok(error instanceof ChromeLaunchError, 'Should throw ChromeLaunchError for in-use port 65535');
163
+ }
164
+ });
165
+ test('binds to localhost (127.0.0.1) only, not all interfaces', async () => {
166
+ const port = await findAvailablePort();
167
+ const reservation = await reservePort(port);
168
+ try {
169
+ // Contract: should bind to 127.0.0.1, not 0.0.0.0
170
+ // This means we can still bind to the same port on other interfaces
171
+ // We verify by checking we can't bind to 127.0.0.1 but this is implicit
172
+ // in the reservation working at all
173
+ assert.ok(true, 'Reservation binds to localhost interface');
174
+ }
175
+ finally {
176
+ reservation.release();
177
+ }
178
+ });
179
+ });
180
+ describe('Port Reservation - Atomicity', () => {
181
+ test('reservation is atomic (prevents race conditions)', async () => {
182
+ const port = await findAvailablePort();
183
+ // Attempt two simultaneous reservations
184
+ const results = await Promise.allSettled([reservePort(port), reservePort(port)]);
185
+ // Contract: exactly one should succeed, one should fail
186
+ const successes = results.filter((r) => r.status === 'fulfilled');
187
+ const failures = results.filter((r) => r.status === 'rejected');
188
+ assert.equal(successes.length, 1, 'Exactly one reservation should succeed');
189
+ assert.equal(failures.length, 1, 'Exactly one reservation should fail');
190
+ // Cleanup successful reservation
191
+ const success = successes[0];
192
+ if (success?.status === 'fulfilled') {
193
+ success.value.release();
194
+ }
195
+ // Verify failure is ChromeLaunchError
196
+ const failure = failures[0];
197
+ if (failure?.status === 'rejected') {
198
+ assert.ok(failure.reason instanceof ChromeLaunchError, 'Failed reservation should throw ChromeLaunchError');
199
+ }
200
+ });
201
+ });
202
+ // Test Helpers
203
+ /**
204
+ * Find an available port starting from a base port
205
+ *
206
+ * @param startPort - Port to start searching from (default: 9000)
207
+ * @returns Available port number
208
+ */
209
+ async function findAvailablePort(startPort = 9000) {
210
+ for (let port = startPort; port < 65535; port++) {
211
+ const server = net.createServer();
212
+ const available = await new Promise((resolve) => {
213
+ server.once('error', () => resolve(false));
214
+ server.listen(port, '127.0.0.1', () => {
215
+ server.close();
216
+ resolve(true);
217
+ });
218
+ });
219
+ if (available) {
220
+ return port;
221
+ }
222
+ }
223
+ throw new Error('No available ports found');
224
+ }
225
+ /**
226
+ * Create a test server on a specific port
227
+ *
228
+ * @param port - Port to bind to
229
+ * @returns Server instance
230
+ */
231
+ async function createTestServer(port) {
232
+ const server = net.createServer();
233
+ return new Promise((resolve, reject) => {
234
+ server.once('error', reject);
235
+ server.listen(port, '127.0.0.1', () => {
236
+ resolve(server);
237
+ });
238
+ });
239
+ }
240
+ /**
241
+ * Close a server gracefully
242
+ *
243
+ * @param server - Server to close
244
+ */
245
+ async function closeServer(server) {
246
+ return new Promise((resolve) => {
247
+ server.close(() => resolve());
248
+ });
249
+ }
250
+ //# sourceMappingURL=portReservation.contract.test.js.map