tabwright 1.0.0 → 1.0.1

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 (562) hide show
  1. package/dist/aria-snapshot.d.ts +0 -1
  2. package/dist/aria-snapshot.js +9 -1
  3. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +0 -1
  4. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +0 -1
  5. package/dist/bippy.js +1 -1
  6. package/dist/browser-config.d.ts +0 -1
  7. package/dist/browser-config.js +0 -1
  8. package/dist/browser-install.d.ts +0 -1
  9. package/dist/browser-install.js +0 -1
  10. package/dist/browser-launch.d.ts +0 -1
  11. package/dist/browser-launch.js +0 -1
  12. package/dist/builtin-capabilities.d.ts +0 -1
  13. package/dist/builtin-capabilities.js +0 -1
  14. package/dist/capability-agent-skill.d.ts +0 -1
  15. package/dist/capability-agent-skill.js +0 -1
  16. package/dist/capability-auth-state.d.ts +0 -1
  17. package/dist/capability-auth-state.js +0 -1
  18. package/dist/capability-auth.d.ts +0 -1
  19. package/dist/capability-auth.js +0 -1
  20. package/dist/capability-options.d.ts +0 -1
  21. package/dist/capability-options.js +0 -1
  22. package/dist/capability-package.d.ts +0 -1
  23. package/dist/capability-package.js +0 -1
  24. package/dist/capability-registry.d.ts +0 -1
  25. package/dist/capability-registry.js +0 -1
  26. package/dist/capability-runner.d.ts +0 -1
  27. package/dist/capability-runner.js +0 -1
  28. package/dist/capability-studio.d.ts +0 -1
  29. package/dist/capability-studio.js +0 -1
  30. package/dist/cdp-log.d.ts +0 -1
  31. package/dist/cdp-log.js +0 -1
  32. package/dist/cdp-relay.d.ts +0 -1
  33. package/dist/cdp-relay.js +0 -1
  34. package/dist/cdp-session.d.ts +0 -1
  35. package/dist/cdp-session.js +0 -1
  36. package/dist/cdp-types.d.ts +0 -1
  37. package/dist/cdp-types.js +0 -1
  38. package/dist/chrome-discovery.d.ts +0 -1
  39. package/dist/chrome-discovery.js +0 -1
  40. package/dist/clean-html.d.ts +0 -1
  41. package/dist/clean-html.js +0 -1
  42. package/dist/cli.d.ts +0 -1
  43. package/dist/cli.js +9 -2
  44. package/dist/cloud-client.d.ts +0 -1
  45. package/dist/cloud-client.js +0 -1
  46. package/dist/create-logger.d.ts +0 -1
  47. package/dist/create-logger.js +0 -1
  48. package/dist/debugger-examples-types.d.ts +0 -1
  49. package/dist/debugger-examples-types.js +0 -1
  50. package/dist/debugger-examples.d.ts +0 -1
  51. package/dist/debugger-examples.js +0 -1
  52. package/dist/debugger.d.ts +0 -1
  53. package/dist/debugger.js +0 -1
  54. package/dist/diff-utils.d.ts +0 -1
  55. package/dist/diff-utils.js +0 -1
  56. package/dist/doctor.d.ts +0 -1
  57. package/dist/doctor.js +5 -7
  58. package/dist/editor-examples.d.ts +0 -1
  59. package/dist/editor-examples.js +0 -1
  60. package/dist/editor.d.ts +0 -1
  61. package/dist/editor.js +0 -1
  62. package/dist/env-compat.d.ts +0 -1
  63. package/dist/env-compat.js +0 -1
  64. package/dist/executor.d.ts +0 -1
  65. package/dist/executor.js +1 -2
  66. package/dist/extension/background.js +7 -3
  67. package/dist/extension/manifest.json +1 -1
  68. package/dist/ghost-browser.d.ts +0 -1
  69. package/dist/ghost-browser.js +0 -1
  70. package/dist/ghost-cursor-controller.d.ts +0 -1
  71. package/dist/ghost-cursor-controller.js +0 -1
  72. package/dist/ghost-cursor.d.ts +0 -1
  73. package/dist/ghost-cursor.js +0 -1
  74. package/dist/htmlrewrite.d.ts +0 -1
  75. package/dist/htmlrewrite.js +0 -1
  76. package/dist/index.d.ts +0 -1
  77. package/dist/index.js +0 -1
  78. package/dist/kill-port.d.ts +0 -1
  79. package/dist/kill-port.js +0 -1
  80. package/dist/kitty-graphics.d.ts +0 -1
  81. package/dist/kitty-graphics.js +0 -1
  82. package/dist/mcp.d.ts +0 -1
  83. package/dist/mcp.js +0 -1
  84. package/dist/package-paths.d.ts +0 -1
  85. package/dist/package-paths.js +0 -1
  86. package/dist/page-markdown.d.ts +0 -1
  87. package/dist/page-markdown.js +0 -1
  88. package/dist/performance-examples.d.ts +0 -1
  89. package/dist/performance-examples.js +0 -1
  90. package/dist/playwright-import.d.ts +0 -1
  91. package/dist/playwright-import.js +0 -1
  92. package/dist/product-paths.d.ts +0 -1
  93. package/dist/product-paths.js +0 -1
  94. package/dist/protocol.d.ts +0 -1
  95. package/dist/protocol.js +0 -1
  96. package/dist/react-source.d.ts +0 -1
  97. package/dist/react-source.js +0 -1
  98. package/dist/readability.js +1 -1
  99. package/dist/relay-client.d.ts +0 -1
  100. package/dist/relay-client.js +0 -1
  101. package/dist/relay-state.d.ts +0 -1
  102. package/dist/relay-state.js +0 -1
  103. package/dist/replay-ai-index.d.ts +0 -1
  104. package/dist/replay-ai-index.js +0 -1
  105. package/dist/replay-eval.d.ts +0 -1
  106. package/dist/replay-eval.js +0 -1
  107. package/dist/replay-handoff.d.ts +0 -1
  108. package/dist/replay-handoff.js +0 -1
  109. package/dist/replay-workflow-compiler.d.ts +0 -1
  110. package/dist/replay-workflow-compiler.js +0 -1
  111. package/dist/rrweb-recording-relay.d.ts +0 -1
  112. package/dist/rrweb-recording-relay.js +0 -1
  113. package/dist/rrweb-recording.d.ts +0 -1
  114. package/dist/rrweb-recording.js +0 -1
  115. package/dist/scoped-fs.d.ts +0 -1
  116. package/dist/scoped-fs.js +0 -1
  117. package/dist/selector-generator.js +1 -1
  118. package/dist/start-relay-server.d.ts +0 -1
  119. package/dist/start-relay-server.js +0 -1
  120. package/dist/styles-examples.d.ts +0 -1
  121. package/dist/styles-examples.js +0 -1
  122. package/dist/styles.d.ts +0 -1
  123. package/dist/styles.js +0 -1
  124. package/dist/tabwright-agent-skill.d.ts +0 -1
  125. package/dist/tabwright-agent-skill.js +0 -1
  126. package/dist/test-declarations.d.ts +0 -1
  127. package/dist/test-declarations.js +0 -1
  128. package/dist/utils.d.ts +0 -1
  129. package/dist/utils.js +2 -2
  130. package/dist/wait-for-page-load.d.ts +0 -1
  131. package/dist/wait-for-page-load.js +0 -1
  132. package/dist/workflow-capability.d.ts +0 -1
  133. package/dist/workflow-capability.js +0 -1
  134. package/package.json +9 -4
  135. package/readme.md +35 -0
  136. package/dist/aria-snapshot.d.ts.map +0 -1
  137. package/dist/aria-snapshot.js.map +0 -1
  138. package/dist/aria-snapshot.test.d.ts +0 -2
  139. package/dist/aria-snapshot.test.d.ts.map +0 -1
  140. package/dist/aria-snapshot.test.js +0 -270
  141. package/dist/aria-snapshot.test.js.map +0 -1
  142. package/dist/aria-snapshot.unit.test.d.ts +0 -2
  143. package/dist/aria-snapshot.unit.test.d.ts.map +0 -1
  144. package/dist/aria-snapshot.unit.test.js +0 -542
  145. package/dist/aria-snapshot.unit.test.js.map +0 -1
  146. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +0 -1
  147. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +0 -1
  148. package/dist/browser-config.d.ts.map +0 -1
  149. package/dist/browser-config.js.map +0 -1
  150. package/dist/browser-install.d.ts.map +0 -1
  151. package/dist/browser-install.js.map +0 -1
  152. package/dist/browser-launch.d.ts.map +0 -1
  153. package/dist/browser-launch.js.map +0 -1
  154. package/dist/builtin-capabilities.d.ts.map +0 -1
  155. package/dist/builtin-capabilities.js.map +0 -1
  156. package/dist/capability-agent-skill.d.ts.map +0 -1
  157. package/dist/capability-agent-skill.js.map +0 -1
  158. package/dist/capability-auth-state.d.ts.map +0 -1
  159. package/dist/capability-auth-state.js.map +0 -1
  160. package/dist/capability-auth.d.ts.map +0 -1
  161. package/dist/capability-auth.js.map +0 -1
  162. package/dist/capability-cli-confirmation.test.d.ts +0 -2
  163. package/dist/capability-cli-confirmation.test.d.ts.map +0 -1
  164. package/dist/capability-cli-confirmation.test.js +0 -79
  165. package/dist/capability-cli-confirmation.test.js.map +0 -1
  166. package/dist/capability-options.d.ts.map +0 -1
  167. package/dist/capability-options.js.map +0 -1
  168. package/dist/capability-options.test.d.ts +0 -2
  169. package/dist/capability-options.test.d.ts.map +0 -1
  170. package/dist/capability-options.test.js +0 -81
  171. package/dist/capability-options.test.js.map +0 -1
  172. package/dist/capability-package.d.ts.map +0 -1
  173. package/dist/capability-package.js.map +0 -1
  174. package/dist/capability-package.test.d.ts +0 -2
  175. package/dist/capability-package.test.d.ts.map +0 -1
  176. package/dist/capability-package.test.js +0 -179
  177. package/dist/capability-package.test.js.map +0 -1
  178. package/dist/capability-registry.d.ts.map +0 -1
  179. package/dist/capability-registry.js.map +0 -1
  180. package/dist/capability-registry.test.d.ts +0 -2
  181. package/dist/capability-registry.test.d.ts.map +0 -1
  182. package/dist/capability-registry.test.js +0 -1683
  183. package/dist/capability-registry.test.js.map +0 -1
  184. package/dist/capability-runner.d.ts.map +0 -1
  185. package/dist/capability-runner.js.map +0 -1
  186. package/dist/capability-search-relevance.test.d.ts +0 -2
  187. package/dist/capability-search-relevance.test.d.ts.map +0 -1
  188. package/dist/capability-search-relevance.test.js +0 -67
  189. package/dist/capability-search-relevance.test.js.map +0 -1
  190. package/dist/capability-studio.d.ts.map +0 -1
  191. package/dist/capability-studio.js.map +0 -1
  192. package/dist/capability-studio.test.d.ts +0 -2
  193. package/dist/capability-studio.test.d.ts.map +0 -1
  194. package/dist/capability-studio.test.js +0 -41
  195. package/dist/capability-studio.test.js.map +0 -1
  196. package/dist/cdp-log.d.ts.map +0 -1
  197. package/dist/cdp-log.js.map +0 -1
  198. package/dist/cdp-log.test.d.ts +0 -2
  199. package/dist/cdp-log.test.d.ts.map +0 -1
  200. package/dist/cdp-log.test.js +0 -109
  201. package/dist/cdp-log.test.js.map +0 -1
  202. package/dist/cdp-relay.d.ts.map +0 -1
  203. package/dist/cdp-relay.js.map +0 -1
  204. package/dist/cdp-session.d.ts.map +0 -1
  205. package/dist/cdp-session.js.map +0 -1
  206. package/dist/cdp-types.d.ts.map +0 -1
  207. package/dist/cdp-types.js.map +0 -1
  208. package/dist/channel-owner-inspect.test.d.ts +0 -2
  209. package/dist/channel-owner-inspect.test.d.ts.map +0 -1
  210. package/dist/channel-owner-inspect.test.js +0 -75
  211. package/dist/channel-owner-inspect.test.js.map +0 -1
  212. package/dist/chrome-discovery.d.ts.map +0 -1
  213. package/dist/chrome-discovery.js.map +0 -1
  214. package/dist/chrome-discovery.test.d.ts +0 -2
  215. package/dist/chrome-discovery.test.d.ts.map +0 -1
  216. package/dist/chrome-discovery.test.js +0 -41
  217. package/dist/chrome-discovery.test.js.map +0 -1
  218. package/dist/clean-html.d.ts.map +0 -1
  219. package/dist/clean-html.js.map +0 -1
  220. package/dist/cli-help.test.d.ts +0 -2
  221. package/dist/cli-help.test.d.ts.map +0 -1
  222. package/dist/cli-help.test.js +0 -98
  223. package/dist/cli-help.test.js.map +0 -1
  224. package/dist/cli.d.ts.map +0 -1
  225. package/dist/cli.js.map +0 -1
  226. package/dist/cloud-client.d.ts.map +0 -1
  227. package/dist/cloud-client.js.map +0 -1
  228. package/dist/create-logger.d.ts.map +0 -1
  229. package/dist/create-logger.js.map +0 -1
  230. package/dist/debugger-examples-types.d.ts.map +0 -1
  231. package/dist/debugger-examples-types.js.map +0 -1
  232. package/dist/debugger-examples.d.ts.map +0 -1
  233. package/dist/debugger-examples.js.map +0 -1
  234. package/dist/debugger.d.ts.map +0 -1
  235. package/dist/debugger.js.map +0 -1
  236. package/dist/diff-utils.d.ts.map +0 -1
  237. package/dist/diff-utils.js.map +0 -1
  238. package/dist/diff-utils.test.d.ts +0 -2
  239. package/dist/diff-utils.test.d.ts.map +0 -1
  240. package/dist/diff-utils.test.js +0 -137
  241. package/dist/diff-utils.test.js.map +0 -1
  242. package/dist/doctor.d.ts.map +0 -1
  243. package/dist/doctor.js.map +0 -1
  244. package/dist/doctor.test.d.ts +0 -2
  245. package/dist/doctor.test.d.ts.map +0 -1
  246. package/dist/doctor.test.js +0 -208
  247. package/dist/doctor.test.js.map +0 -1
  248. package/dist/editor-examples.d.ts.map +0 -1
  249. package/dist/editor-examples.js.map +0 -1
  250. package/dist/editor.d.ts.map +0 -1
  251. package/dist/editor.js.map +0 -1
  252. package/dist/env-compat.d.ts.map +0 -1
  253. package/dist/env-compat.js.map +0 -1
  254. package/dist/executor.d.ts.map +0 -1
  255. package/dist/executor.js.map +0 -1
  256. package/dist/executor.unit.test.d.ts +0 -2
  257. package/dist/executor.unit.test.d.ts.map +0 -1
  258. package/dist/executor.unit.test.js +0 -143
  259. package/dist/executor.unit.test.js.map +0 -1
  260. package/dist/extension-connection.test.d.ts +0 -2
  261. package/dist/extension-connection.test.d.ts.map +0 -1
  262. package/dist/extension-connection.test.js +0 -708
  263. package/dist/extension-connection.test.js.map +0 -1
  264. package/dist/extension-icon-warning.test.d.ts +0 -2
  265. package/dist/extension-icon-warning.test.d.ts.map +0 -1
  266. package/dist/extension-icon-warning.test.js +0 -33
  267. package/dist/extension-icon-warning.test.js.map +0 -1
  268. package/dist/ghost-browser.d.ts.map +0 -1
  269. package/dist/ghost-browser.js.map +0 -1
  270. package/dist/ghost-cursor-controller.d.ts.map +0 -1
  271. package/dist/ghost-cursor-controller.js.map +0 -1
  272. package/dist/ghost-cursor.d.ts.map +0 -1
  273. package/dist/ghost-cursor.js.map +0 -1
  274. package/dist/htmlrewrite.d.ts.map +0 -1
  275. package/dist/htmlrewrite.js.map +0 -1
  276. package/dist/htmlrewrite.test.d.ts +0 -2
  277. package/dist/htmlrewrite.test.d.ts.map +0 -1
  278. package/dist/htmlrewrite.test.js +0 -7975
  279. package/dist/htmlrewrite.test.js.map +0 -1
  280. package/dist/index.d.ts.map +0 -1
  281. package/dist/index.js.map +0 -1
  282. package/dist/kill-port.d.ts.map +0 -1
  283. package/dist/kill-port.js.map +0 -1
  284. package/dist/kitty-graphics.d.ts.map +0 -1
  285. package/dist/kitty-graphics.js.map +0 -1
  286. package/dist/kitty-graphics.test.d.ts +0 -2
  287. package/dist/kitty-graphics.test.d.ts.map +0 -1
  288. package/dist/kitty-graphics.test.js +0 -125
  289. package/dist/kitty-graphics.test.js.map +0 -1
  290. package/dist/locator-selector.test.d.ts +0 -2
  291. package/dist/locator-selector.test.d.ts.map +0 -1
  292. package/dist/locator-selector.test.js +0 -98
  293. package/dist/locator-selector.test.js.map +0 -1
  294. package/dist/mcp-client.d.ts +0 -20
  295. package/dist/mcp-client.d.ts.map +0 -1
  296. package/dist/mcp-client.js +0 -56
  297. package/dist/mcp-client.js.map +0 -1
  298. package/dist/mcp.d.ts.map +0 -1
  299. package/dist/mcp.js.map +0 -1
  300. package/dist/on-mouse-action.test.d.ts +0 -2
  301. package/dist/on-mouse-action.test.d.ts.map +0 -1
  302. package/dist/on-mouse-action.test.js +0 -180
  303. package/dist/on-mouse-action.test.js.map +0 -1
  304. package/dist/options-page.test.d.ts +0 -2
  305. package/dist/options-page.test.d.ts.map +0 -1
  306. package/dist/options-page.test.js +0 -773
  307. package/dist/options-page.test.js.map +0 -1
  308. package/dist/package-paths.d.ts.map +0 -1
  309. package/dist/package-paths.js.map +0 -1
  310. package/dist/page-markdown.d.ts.map +0 -1
  311. package/dist/page-markdown.js.map +0 -1
  312. package/dist/performance-examples.d.ts.map +0 -1
  313. package/dist/performance-examples.js.map +0 -1
  314. package/dist/playwright-import.d.ts.map +0 -1
  315. package/dist/playwright-import.js.map +0 -1
  316. package/dist/popup-relocation.test.d.ts +0 -7
  317. package/dist/popup-relocation.test.d.ts.map +0 -1
  318. package/dist/popup-relocation.test.js +0 -139
  319. package/dist/popup-relocation.test.js.map +0 -1
  320. package/dist/product-paths.d.ts.map +0 -1
  321. package/dist/product-paths.js.map +0 -1
  322. package/dist/product-paths.test.d.ts +0 -2
  323. package/dist/product-paths.test.d.ts.map +0 -1
  324. package/dist/product-paths.test.js +0 -39
  325. package/dist/product-paths.test.js.map +0 -1
  326. package/dist/protocol.d.ts.map +0 -1
  327. package/dist/protocol.js.map +0 -1
  328. package/dist/protocol.test.d.ts +0 -2
  329. package/dist/protocol.test.d.ts.map +0 -1
  330. package/dist/protocol.test.js +0 -31
  331. package/dist/protocol.test.js.map +0 -1
  332. package/dist/react-source.d.ts.map +0 -1
  333. package/dist/react-source.js.map +0 -1
  334. package/dist/relay-client.d.ts.map +0 -1
  335. package/dist/relay-client.js.map +0 -1
  336. package/dist/relay-client.test.d.ts +0 -2
  337. package/dist/relay-client.test.d.ts.map +0 -1
  338. package/dist/relay-client.test.js +0 -305
  339. package/dist/relay-client.test.js.map +0 -1
  340. package/dist/relay-core.test.d.ts +0 -2
  341. package/dist/relay-core.test.d.ts.map +0 -1
  342. package/dist/relay-core.test.js +0 -1427
  343. package/dist/relay-core.test.js.map +0 -1
  344. package/dist/relay-navigation.test.d.ts +0 -2
  345. package/dist/relay-navigation.test.d.ts.map +0 -1
  346. package/dist/relay-navigation.test.js +0 -661
  347. package/dist/relay-navigation.test.js.map +0 -1
  348. package/dist/relay-session.test.d.ts +0 -2
  349. package/dist/relay-session.test.d.ts.map +0 -1
  350. package/dist/relay-session.test.js +0 -1121
  351. package/dist/relay-session.test.js.map +0 -1
  352. package/dist/relay-state.d.ts.map +0 -1
  353. package/dist/relay-state.js.map +0 -1
  354. package/dist/relay-state.test.d.ts +0 -2
  355. package/dist/relay-state.test.d.ts.map +0 -1
  356. package/dist/relay-state.test.js +0 -594
  357. package/dist/relay-state.test.js.map +0 -1
  358. package/dist/replay-ai-index.d.ts.map +0 -1
  359. package/dist/replay-ai-index.js.map +0 -1
  360. package/dist/replay-ai-index.test.d.ts +0 -2
  361. package/dist/replay-ai-index.test.d.ts.map +0 -1
  362. package/dist/replay-ai-index.test.js +0 -255
  363. package/dist/replay-ai-index.test.js.map +0 -1
  364. package/dist/replay-cli.test.d.ts +0 -2
  365. package/dist/replay-cli.test.d.ts.map +0 -1
  366. package/dist/replay-cli.test.js +0 -275
  367. package/dist/replay-cli.test.js.map +0 -1
  368. package/dist/replay-eval.d.ts.map +0 -1
  369. package/dist/replay-eval.js.map +0 -1
  370. package/dist/replay-handoff.d.ts.map +0 -1
  371. package/dist/replay-handoff.js.map +0 -1
  372. package/dist/replay-handoff.test.d.ts +0 -2
  373. package/dist/replay-handoff.test.d.ts.map +0 -1
  374. package/dist/replay-handoff.test.js +0 -123
  375. package/dist/replay-handoff.test.js.map +0 -1
  376. package/dist/replay-workflow-compiler.d.ts.map +0 -1
  377. package/dist/replay-workflow-compiler.js.map +0 -1
  378. package/dist/replay-workflow-compiler.test.d.ts +0 -2
  379. package/dist/replay-workflow-compiler.test.d.ts.map +0 -1
  380. package/dist/replay-workflow-compiler.test.js +0 -223
  381. package/dist/replay-workflow-compiler.test.js.map +0 -1
  382. package/dist/rrweb-recording-relay.d.ts.map +0 -1
  383. package/dist/rrweb-recording-relay.js.map +0 -1
  384. package/dist/rrweb-recording-relay.test.d.ts +0 -2
  385. package/dist/rrweb-recording-relay.test.d.ts.map +0 -1
  386. package/dist/rrweb-recording-relay.test.js +0 -85
  387. package/dist/rrweb-recording-relay.test.js.map +0 -1
  388. package/dist/rrweb-recording.d.ts.map +0 -1
  389. package/dist/rrweb-recording.js.map +0 -1
  390. package/dist/scoped-fs.d.ts.map +0 -1
  391. package/dist/scoped-fs.js.map +0 -1
  392. package/dist/scoped-fs.test.d.ts +0 -5
  393. package/dist/scoped-fs.test.d.ts.map +0 -1
  394. package/dist/scoped-fs.test.js +0 -73
  395. package/dist/scoped-fs.test.js.map +0 -1
  396. package/dist/skill-stub.test.d.ts +0 -2
  397. package/dist/skill-stub.test.d.ts.map +0 -1
  398. package/dist/skill-stub.test.js +0 -22
  399. package/dist/skill-stub.test.js.map +0 -1
  400. package/dist/snapshot-tools.test.d.ts +0 -2
  401. package/dist/snapshot-tools.test.d.ts.map +0 -1
  402. package/dist/snapshot-tools.test.js +0 -856
  403. package/dist/snapshot-tools.test.js.map +0 -1
  404. package/dist/start-relay-server.d.ts.map +0 -1
  405. package/dist/start-relay-server.js.map +0 -1
  406. package/dist/styles-examples.d.ts.map +0 -1
  407. package/dist/styles-examples.js.map +0 -1
  408. package/dist/styles.d.ts.map +0 -1
  409. package/dist/styles.js.map +0 -1
  410. package/dist/tabwright-agent-skill.d.ts.map +0 -1
  411. package/dist/tabwright-agent-skill.js.map +0 -1
  412. package/dist/tabwright-agent-skill.test.d.ts +0 -2
  413. package/dist/tabwright-agent-skill.test.d.ts.map +0 -1
  414. package/dist/tabwright-agent-skill.test.js +0 -51
  415. package/dist/tabwright-agent-skill.test.js.map +0 -1
  416. package/dist/test-declarations.d.ts.map +0 -1
  417. package/dist/test-declarations.js.map +0 -1
  418. package/dist/test-utils.d.ts +0 -69
  419. package/dist/test-utils.d.ts.map +0 -1
  420. package/dist/test-utils.js +0 -448
  421. package/dist/test-utils.js.map +0 -1
  422. package/dist/test-utils.test.d.ts +0 -2
  423. package/dist/test-utils.test.d.ts.map +0 -1
  424. package/dist/test-utils.test.js +0 -55
  425. package/dist/test-utils.test.js.map +0 -1
  426. package/dist/utils.d.ts.map +0 -1
  427. package/dist/utils.js.map +0 -1
  428. package/dist/wait-for-page-load.d.ts.map +0 -1
  429. package/dist/wait-for-page-load.js.map +0 -1
  430. package/dist/workflow-capability.d.ts.map +0 -1
  431. package/dist/workflow-capability.js.map +0 -1
  432. package/dist/workflow-script-flow.test.d.ts +0 -2
  433. package/dist/workflow-script-flow.test.d.ts.map +0 -1
  434. package/dist/workflow-script-flow.test.js +0 -285
  435. package/dist/workflow-script-flow.test.js.map +0 -1
  436. package/src/__snapshots__/x.com.processed.html +0 -1003
  437. package/src/__snapshots__/x.com.processed.withStyles.html +0 -2720
  438. package/src/a11y-client.ts +0 -241
  439. package/src/aria-snapshot.test.ts +0 -311
  440. package/src/aria-snapshot.ts +0 -1681
  441. package/src/aria-snapshot.unit.test.ts +0 -615
  442. package/src/aria-snapshots/github-interactive.txt +0 -193
  443. package/src/aria-snapshots/github-raw.txt +0 -309
  444. package/src/aria-snapshots/hackernews-interactive.txt +0 -477
  445. package/src/aria-snapshots/hackernews-raw.txt +0 -428
  446. package/src/aria-snapshots/prosemirror-interactive.txt +0 -66
  447. package/src/aria-snapshots/prosemirror-raw.txt +0 -145
  448. package/src/assets/aria-labels-hacker-news.png +0 -0
  449. package/src/assets/aria-labels-old-reddit.png +0 -0
  450. package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +0 -5
  451. package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +0 -18
  452. package/src/assets/x.com.html +0 -32946
  453. package/src/browser-config.ts +0 -179
  454. package/src/browser-install.ts +0 -284
  455. package/src/browser-launch.ts +0 -75
  456. package/src/builtin-capabilities.ts +0 -2765
  457. package/src/capability-agent-skill.ts +0 -305
  458. package/src/capability-auth-state.ts +0 -197
  459. package/src/capability-auth.ts +0 -249
  460. package/src/capability-cli-confirmation.test.ts +0 -90
  461. package/src/capability-options.test.ts +0 -89
  462. package/src/capability-options.ts +0 -57
  463. package/src/capability-package.test.ts +0 -204
  464. package/src/capability-package.ts +0 -555
  465. package/src/capability-registry.test.ts +0 -1905
  466. package/src/capability-registry.ts +0 -1234
  467. package/src/capability-runner.ts +0 -801
  468. package/src/capability-search-relevance.test.ts +0 -73
  469. package/src/capability-studio.test.ts +0 -45
  470. package/src/capability-studio.ts +0 -641
  471. package/src/cdp-log.test.ts +0 -131
  472. package/src/cdp-log.ts +0 -112
  473. package/src/cdp-relay.ts +0 -2944
  474. package/src/cdp-session.ts +0 -77
  475. package/src/cdp-types.ts +0 -158
  476. package/src/channel-owner-inspect.test.ts +0 -94
  477. package/src/chrome-discovery.test.ts +0 -50
  478. package/src/chrome-discovery.ts +0 -220
  479. package/src/clean-html.ts +0 -141
  480. package/src/cli-help.test.ts +0 -123
  481. package/src/cli.ts +0 -3181
  482. package/src/cloud-client.ts +0 -179
  483. package/src/create-logger.ts +0 -38
  484. package/src/debugger-examples-types.ts +0 -16
  485. package/src/debugger-examples.ts +0 -66
  486. package/src/debugger.ts +0 -708
  487. package/src/diff-utils.test.ts +0 -152
  488. package/src/diff-utils.ts +0 -70
  489. package/src/doctor.test.ts +0 -244
  490. package/src/doctor.ts +0 -321
  491. package/src/editor-examples.ts +0 -158
  492. package/src/editor.ts +0 -426
  493. package/src/env-compat.ts +0 -28
  494. package/src/executor.ts +0 -1824
  495. package/src/executor.unit.test.ts +0 -168
  496. package/src/extension-connection.test.ts +0 -855
  497. package/src/extension-icon-warning.test.ts +0 -45
  498. package/src/ghost-browser.ts +0 -149
  499. package/src/ghost-cursor-client.ts +0 -494
  500. package/src/ghost-cursor-controller.ts +0 -129
  501. package/src/ghost-cursor.ts +0 -123
  502. package/src/htmlrewrite.test.ts +0 -8008
  503. package/src/htmlrewrite.ts +0 -390
  504. package/src/index.ts +0 -53
  505. package/src/kill-port.ts +0 -219
  506. package/src/kitty-graphics.test.ts +0 -139
  507. package/src/kitty-graphics.ts +0 -79
  508. package/src/locator-selector.test.ts +0 -119
  509. package/src/mcp-client.ts +0 -78
  510. package/src/mcp.ts +0 -629
  511. package/src/on-mouse-action.test.ts +0 -226
  512. package/src/options-page.test.ts +0 -839
  513. package/src/package-paths.ts +0 -38
  514. package/src/page-markdown.ts +0 -240
  515. package/src/performance-examples.ts +0 -186
  516. package/src/playwright-import.ts +0 -59
  517. package/src/popup-relocation.test.ts +0 -163
  518. package/src/product-paths.test.ts +0 -47
  519. package/src/product-paths.ts +0 -28
  520. package/src/protocol.test.ts +0 -52
  521. package/src/protocol.ts +0 -351
  522. package/src/react-source.ts +0 -379
  523. package/src/relay-client.test.ts +0 -375
  524. package/src/relay-client.ts +0 -572
  525. package/src/relay-core.test.ts +0 -1603
  526. package/src/relay-navigation.test.ts +0 -790
  527. package/src/relay-session.test.ts +0 -1375
  528. package/src/relay-state.test.ts +0 -729
  529. package/src/relay-state.ts +0 -561
  530. package/src/replay-ai-index.test.ts +0 -278
  531. package/src/replay-ai-index.ts +0 -872
  532. package/src/replay-cli.test.ts +0 -325
  533. package/src/replay-eval.ts +0 -1039
  534. package/src/replay-handoff.test.ts +0 -163
  535. package/src/replay-handoff.ts +0 -109
  536. package/src/replay-workflow-compiler.test.ts +0 -250
  537. package/src/replay-workflow-compiler.ts +0 -700
  538. package/src/resource.md +0 -409
  539. package/src/rrweb-recording-relay.test.ts +0 -99
  540. package/src/rrweb-recording-relay.ts +0 -400
  541. package/src/rrweb-recording.ts +0 -322
  542. package/src/scoped-fs.test.ts +0 -80
  543. package/src/scoped-fs.ts +0 -420
  544. package/src/skill-stub.test.ts +0 -24
  545. package/src/snapshot-tools.test.ts +0 -1017
  546. package/src/snapshots/hacker-news-accessibility-full.md +0 -81
  547. package/src/snapshots/hacker-news-accessibility-interactive.md +0 -43
  548. package/src/snapshots/page-markdown-output.txt +0 -16
  549. package/src/snapshots/shadcn-ui-accessibility-full.md +0 -201
  550. package/src/snapshots/shadcn-ui-accessibility-interactive.md +0 -109
  551. package/src/start-relay-server.ts +0 -69
  552. package/src/styles-examples.ts +0 -84
  553. package/src/styles.ts +0 -343
  554. package/src/tabwright-agent-skill.test.ts +0 -61
  555. package/src/tabwright-agent-skill.ts +0 -105
  556. package/src/test-declarations.ts +0 -13
  557. package/src/test-utils.test.ts +0 -70
  558. package/src/test-utils.ts +0 -566
  559. package/src/utils.ts +0 -78
  560. package/src/wait-for-page-load.ts +0 -198
  561. package/src/workflow-capability.ts +0 -417
  562. package/src/workflow-script-flow.test.ts +0 -388
@@ -1,1121 +0,0 @@
1
- import { createMCPClient } from './mcp-client.js';
2
- import { describe, it, expect, beforeAll, afterAll } from 'vitest';
3
- import { chromium } from '@xmorse/playwright-core';
4
- import { getCdpUrl } from './utils.js';
5
- import { getCDPSessionForPage } from './cdp-session.js';
6
- import { Debugger } from './debugger.js';
7
- import { Editor } from './editor.js';
8
- import { PlaywrightExecutor } from './executor.js';
9
- import { setupTestContext, cleanupTestContext, getExtensionServiceWorker, createSseServer, safeCloseCDPBrowser, withTimeout, js, } from './test-utils.js';
10
- import './test-declarations.js';
11
- const TEST_PORT = 19993;
12
- // --- CDP Session Tests ---
13
- describe('CDP Session Tests', () => {
14
- let testCtx = null;
15
- beforeAll(async () => {
16
- testCtx = await setupTestContext({ port: TEST_PORT, tempDirPrefix: 'pw-cdp-test-', toggleExtension: true });
17
- const serviceWorker = await getExtensionServiceWorker(testCtx.browserContext);
18
- await serviceWorker.evaluate(async () => {
19
- await globalThis.disconnectEverything();
20
- });
21
- await new Promise((r) => setTimeout(r, 100));
22
- }, 600000);
23
- afterAll(async () => {
24
- await cleanupTestContext(testCtx);
25
- testCtx = null;
26
- });
27
- const getBrowserContext = () => {
28
- if (!testCtx?.browserContext)
29
- throw new Error('Browser not initialized');
30
- return testCtx.browserContext;
31
- };
32
- it('should use Debugger class to set breakpoints and inspect variables', async () => {
33
- const browserContext = getBrowserContext();
34
- const serviceWorker = await getExtensionServiceWorker(browserContext);
35
- const page = await browserContext.newPage();
36
- const testUrl = 'https://example.com/?test=debugger-variables';
37
- await page.goto(testUrl);
38
- await page.bringToFront();
39
- await serviceWorker.evaluate(async () => {
40
- await globalThis.toggleExtensionForActiveTab();
41
- });
42
- await new Promise((r) => setTimeout(r, 100));
43
- const wsUrl = getCdpUrl({ port: TEST_PORT });
44
- const cdpSession = await getCDPSessionForPage({ page });
45
- const dbg = new Debugger({ cdp: cdpSession });
46
- await dbg.enable();
47
- expect(dbg.isPaused()).toBe(false);
48
- const pausedPromise = new Promise((resolve) => {
49
- cdpSession.on('Debugger.paused', () => {
50
- resolve();
51
- });
52
- });
53
- const evalPromise = cdpSession.send('Runtime.evaluate', {
54
- expression: `(function testFunction() {
55
- const localVar = 'hello';
56
- const numberVar = 42;
57
- debugger;
58
- return localVar + numberVar;
59
- })()`,
60
- });
61
- await Promise.race([
62
- pausedPromise,
63
- new Promise((_, reject) => setTimeout(() => reject(new Error('Debugger.paused timeout')), 5000)),
64
- ]);
65
- expect(dbg.isPaused()).toBe(true);
66
- const location = await dbg.getLocation();
67
- expect(location.callstack[0].functionName).toBe('testFunction');
68
- expect(location.sourceContext).toContain('debugger');
69
- const vars = await dbg.inspectLocalVariables();
70
- expect(vars).toMatchInlineSnapshot(`
71
- {
72
- "localVar": "hello",
73
- "numberVar": 42,
74
- }
75
- `);
76
- const evalResult = await dbg.evaluate({ expression: 'localVar + " world"' });
77
- expect(evalResult.value).toBe('hello world');
78
- await dbg.resume();
79
- await new Promise((r) => setTimeout(r, 100));
80
- expect(dbg.isPaused()).toBe(false);
81
- await evalPromise;
82
- await cdpSession.detach();
83
- await page.close();
84
- }, 60000);
85
- it('should reuse cached CDP session and close on page close', async () => {
86
- const browserContext = getBrowserContext();
87
- const serviceWorker = await getExtensionServiceWorker(browserContext);
88
- const page = await browserContext.newPage();
89
- const testUrl = 'https://example.com/?test=debugger-step';
90
- await page.goto(testUrl);
91
- await page.bringToFront();
92
- await serviceWorker.evaluate(async () => {
93
- await globalThis.toggleExtensionForActiveTab();
94
- });
95
- await new Promise((r) => setTimeout(r, 100));
96
- const executor = new PlaywrightExecutor({
97
- cdpConfig: { port: TEST_PORT },
98
- logger: {
99
- log: () => { },
100
- error: () => { },
101
- },
102
- });
103
- const result = await executor.execute(js `
104
- const sessionA = await getCDPSession({ page })
105
- const sessionB = await getCDPSession({ page })
106
- await sessionA.send('Runtime.evaluate', { expression: '1 + 1', returnByValue: true })
107
- const evalResult = await sessionB.send('Runtime.evaluate', { expression: '2 + 2', returnByValue: true })
108
- return evalResult.result.value
109
- `);
110
- expect(result.isError).toBe(false);
111
- expect(result.text).toContain('[return value] 4');
112
- await page.close();
113
- }, 60000);
114
- it('should list scripts with Debugger class', async () => {
115
- const browserContext = getBrowserContext();
116
- const serviceWorker = await getExtensionServiceWorker(browserContext);
117
- // Use setContent with external script URLs so Debugger.listScripts returns them
118
- const page = await browserContext.newPage();
119
- await page.setContent(`
120
- <html>
121
- <head>
122
- <script src="data:text/javascript,function hello() { return 1; }"></script>
123
- <script src="data:text/javascript,function world() { return 2; }"></script>
124
- </head>
125
- <body><h1>Script test</h1></body>
126
- </html>
127
- `);
128
- await page.bringToFront();
129
- await serviceWorker.evaluate(async () => {
130
- await globalThis.toggleExtensionForActiveTab();
131
- });
132
- await new Promise((r) => setTimeout(r, 100));
133
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
134
- const cdpPage = browser
135
- .contexts()[0]
136
- .pages()
137
- .find((p) => p.url().startsWith('about:'));
138
- expect(cdpPage).toBeDefined();
139
- const wsUrl = getCdpUrl({ port: TEST_PORT });
140
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
141
- const dbg = new Debugger({ cdp: cdpSession });
142
- await dbg.enable();
143
- const scripts = await dbg.listScripts();
144
- expect(scripts.length).toBeGreaterThan(0);
145
- expect(scripts[0]).toHaveProperty('scriptId');
146
- expect(scripts[0]).toHaveProperty('url');
147
- await cdpSession.detach();
148
- await browser.close();
149
- await page.close();
150
- }, 60000);
151
- it('should manage breakpoints with Debugger class', async () => {
152
- const browserContext = getBrowserContext();
153
- const serviceWorker = await getExtensionServiceWorker(browserContext);
154
- const page = await browserContext.newPage();
155
- await page.setContent(`
156
- <html>
157
- <head>
158
- <script src="data:text/javascript,function testFunc() { return 42; }"></script>
159
- </head>
160
- <body></body>
161
- </html>
162
- `);
163
- await page.bringToFront();
164
- await serviceWorker.evaluate(async () => {
165
- await globalThis.toggleExtensionForActiveTab();
166
- });
167
- await new Promise((r) => setTimeout(r, 100));
168
- const wsUrl = getCdpUrl({ port: TEST_PORT });
169
- const cdpSession = await getCDPSessionForPage({ page });
170
- const dbg = new Debugger({ cdp: cdpSession });
171
- await dbg.enable();
172
- expect(dbg.listBreakpoints()).toHaveLength(0);
173
- const bpId = await dbg.setBreakpoint({ file: 'https://example.com/test.js', line: 1 });
174
- expect(typeof bpId).toBe('string');
175
- expect(dbg.listBreakpoints()).toHaveLength(1);
176
- expect(dbg.listBreakpoints()[0]).toMatchObject({
177
- id: bpId,
178
- file: 'https://example.com/test.js',
179
- line: 1,
180
- });
181
- await dbg.deleteBreakpoint({ breakpointId: bpId });
182
- expect(dbg.listBreakpoints()).toHaveLength(0);
183
- await cdpSession.detach();
184
- await page.close();
185
- }, 60000);
186
- it('should step through code with Debugger class', async () => {
187
- const browserContext = getBrowserContext();
188
- const serviceWorker = await getExtensionServiceWorker(browserContext);
189
- const page = await browserContext.newPage();
190
- await page.goto('https://example.com/');
191
- await page.bringToFront();
192
- await serviceWorker.evaluate(async () => {
193
- await globalThis.toggleExtensionForActiveTab();
194
- });
195
- await new Promise((r) => setTimeout(r, 100));
196
- const wsUrl = getCdpUrl({ port: TEST_PORT });
197
- const cdpSession = await getCDPSessionForPage({ page });
198
- const dbg = new Debugger({ cdp: cdpSession });
199
- await dbg.enable();
200
- const pausedPromise = new Promise((resolve) => {
201
- cdpSession.on('Debugger.paused', () => resolve());
202
- });
203
- const evalPromise = cdpSession.send('Runtime.evaluate', {
204
- expression: `(function outer() {
205
- function inner() {
206
- const x = 1;
207
- debugger;
208
- const y = 2;
209
- return x + y;
210
- }
211
- const result = inner();
212
- return result;
213
- })()`,
214
- });
215
- await pausedPromise;
216
- expect(dbg.isPaused()).toBe(true);
217
- const location1 = await dbg.getLocation();
218
- expect(location1.callstack.length).toBeGreaterThanOrEqual(2);
219
- expect(location1.callstack[0].functionName).toBe('inner');
220
- expect(location1.callstack[1].functionName).toBe('outer');
221
- const stepOverPromise = new Promise((resolve) => {
222
- cdpSession.on('Debugger.paused', () => resolve());
223
- });
224
- await dbg.stepOver();
225
- await stepOverPromise;
226
- const location2 = await dbg.getLocation();
227
- expect(location2.lineNumber).toBeGreaterThan(location1.lineNumber);
228
- const stepOutPromise = new Promise((resolve) => {
229
- cdpSession.on('Debugger.paused', () => resolve());
230
- });
231
- await dbg.stepOut();
232
- await stepOutPromise;
233
- const location3 = await dbg.getLocation();
234
- expect(location3.callstack[0].functionName).toBe('outer');
235
- await dbg.resume();
236
- await evalPromise;
237
- await cdpSession.detach();
238
- await page.close();
239
- }, 60000);
240
- it('should profile JavaScript execution using CDP Profiler', async () => {
241
- const browserContext = getBrowserContext();
242
- const serviceWorker = await getExtensionServiceWorker(browserContext);
243
- const page = await browserContext.newPage();
244
- const testUrl = 'https://example.com/?test=debugger-profiler';
245
- await page.goto(testUrl);
246
- await page.bringToFront();
247
- await serviceWorker.evaluate(async () => {
248
- await globalThis.toggleExtensionForActiveTab();
249
- });
250
- await new Promise((r) => setTimeout(r, 100));
251
- const wsUrl = getCdpUrl({ port: TEST_PORT });
252
- const cdpSession = await getCDPSessionForPage({ page });
253
- await cdpSession.send('Profiler.enable');
254
- await cdpSession.send('Profiler.start');
255
- await cdpSession.send('Runtime.evaluate', {
256
- expression: `(() => {
257
- function fibonacci(n) {
258
- if (n <= 1) return n
259
- return fibonacci(n - 1) + fibonacci(n - 2)
260
- }
261
- for (let i = 0; i < 5; i++) {
262
- fibonacci(20)
263
- }
264
- for (let i = 0; i < 1000; i++) {
265
- document.querySelectorAll('*')
266
- }
267
- })()`,
268
- });
269
- const stopResult = await cdpSession.send('Profiler.stop');
270
- const profile = stopResult.profile;
271
- const functionNames = profile.nodes
272
- .map((n) => n.callFrame.functionName)
273
- .filter((name) => name && name.length > 0)
274
- .slice(0, 10);
275
- expect(profile.nodes.length).toBeGreaterThan(0);
276
- expect(profile.endTime - profile.startTime).toBeGreaterThan(0);
277
- expect(functionNames.every((name) => typeof name === 'string')).toBe(true);
278
- await cdpSession.send('Profiler.disable');
279
- await cdpSession.detach();
280
- await page.close();
281
- }, 60000);
282
- it('should update Target.getTargets URL after page navigation', async () => {
283
- const browserContext = getBrowserContext();
284
- const serviceWorker = await getExtensionServiceWorker(browserContext);
285
- await serviceWorker.evaluate(async () => {
286
- await globalThis.disconnectEverything();
287
- });
288
- const page = await browserContext.newPage();
289
- await page.goto('https://example.com/');
290
- await page.bringToFront();
291
- await serviceWorker.evaluate(async () => {
292
- await globalThis.toggleExtensionForActiveTab();
293
- });
294
- await new Promise((r) => setTimeout(r, 100));
295
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
296
- const cdpPage = browser
297
- .contexts()[0]
298
- .pages()
299
- .find((p) => p.url().includes('example.com'));
300
- expect(cdpPage).toBeDefined();
301
- const wsUrl = getCdpUrl({ port: TEST_PORT });
302
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
303
- const initialTargets = await cdpSession.send('Target.getTargets');
304
- const initialPageTarget = initialTargets.targetInfos.find((t) => t.type === 'page' && t.url.includes('example.com'));
305
- expect(initialPageTarget?.url).toBe('https://example.com/');
306
- await cdpPage.goto('https://example.org/', { waitUntil: 'domcontentloaded' });
307
- await new Promise((r) => setTimeout(r, 100));
308
- const afterNavTargets = await cdpSession.send('Target.getTargets');
309
- const allPageTargets = afterNavTargets.targetInfos.filter((t) => t.type === 'page');
310
- const aboutBlankTargets = allPageTargets.filter((t) => t.url === 'about:blank');
311
- expect(aboutBlankTargets).toHaveLength(0);
312
- const exampleComTargets = allPageTargets.filter((t) => t.url.includes('example.com'));
313
- expect(exampleComTargets).toHaveLength(0);
314
- const exampleOrgTargets = allPageTargets.filter((t) => t.url.includes('example.org'));
315
- expect(exampleOrgTargets).toHaveLength(1);
316
- await cdpSession.detach();
317
- await browser.close();
318
- await page.close();
319
- }, 60000);
320
- it('should return correct targets for multiple pages via Target.getTargets', async () => {
321
- const browserContext = getBrowserContext();
322
- const serviceWorker = await getExtensionServiceWorker(browserContext);
323
- await serviceWorker.evaluate(async () => {
324
- await globalThis.disconnectEverything();
325
- });
326
- const page1 = await browserContext.newPage();
327
- await page1.goto('https://example.com/');
328
- await page1.bringToFront();
329
- await serviceWorker.evaluate(async () => {
330
- await globalThis.toggleExtensionForActiveTab();
331
- });
332
- const page2 = await browserContext.newPage();
333
- await page2.goto('https://example.org/');
334
- await page2.bringToFront();
335
- await serviceWorker.evaluate(async () => {
336
- await globalThis.toggleExtensionForActiveTab();
337
- });
338
- await new Promise((r) => setTimeout(r, 100));
339
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
340
- const cdpPage = browser
341
- .contexts()[0]
342
- .pages()
343
- .find((p) => p.url().includes('example.com'));
344
- expect(cdpPage).toBeDefined();
345
- const wsUrl = getCdpUrl({ port: TEST_PORT });
346
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
347
- const { targetInfos } = await cdpSession.send('Target.getTargets');
348
- const allPageTargets = targetInfos.filter((t) => t.type === 'page');
349
- const aboutBlankTargets = allPageTargets.filter((t) => t.url === 'about:blank');
350
- expect(aboutBlankTargets).toHaveLength(0);
351
- const pageTargets = allPageTargets
352
- .map((t) => ({ type: t.type, url: t.url }))
353
- .sort((a, b) => a.url.localeCompare(b.url));
354
- expect(pageTargets).toMatchInlineSnapshot(`
355
- [
356
- {
357
- "type": "page",
358
- "url": "https://example.com/",
359
- },
360
- {
361
- "type": "page",
362
- "url": "https://example.org/",
363
- },
364
- ]
365
- `);
366
- await cdpSession.detach();
367
- await browser.close();
368
- await page1.close();
369
- await page2.close();
370
- }, 60000);
371
- it('should create CDP session for page after navigation', async () => {
372
- const browserContext = getBrowserContext();
373
- const serviceWorker = await getExtensionServiceWorker(browserContext);
374
- const page = await browserContext.newPage();
375
- await page.goto('https://example.com/');
376
- await page.bringToFront();
377
- await serviceWorker.evaluate(async () => {
378
- await globalThis.toggleExtensionForActiveTab();
379
- });
380
- await new Promise((r) => setTimeout(r, 100));
381
- await page.goto('https://example.org/', { waitUntil: 'domcontentloaded' });
382
- await new Promise((r) => setTimeout(r, 100));
383
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
384
- const cdpPage = browser
385
- .contexts()[0]
386
- .pages()
387
- .find((p) => p.url().includes('example.org'));
388
- expect(cdpPage).toBeDefined();
389
- const wsUrl = getCdpUrl({ port: TEST_PORT });
390
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
391
- const evalResult = await cdpSession.send('Runtime.evaluate', {
392
- expression: 'document.title',
393
- returnByValue: true,
394
- });
395
- expect(evalResult.result.value).toContain('Example Domain');
396
- await cdpSession.detach();
397
- await browser.close();
398
- await page.close();
399
- }, 60000);
400
- it('should maintain CDP session functionality after page URL change', async () => {
401
- const browserContext = getBrowserContext();
402
- const serviceWorker = await getExtensionServiceWorker(browserContext);
403
- const page = await browserContext.newPage();
404
- const initialUrl = 'https://example.com/';
405
- await page.goto(initialUrl);
406
- await page.bringToFront();
407
- await serviceWorker.evaluate(async () => {
408
- await globalThis.toggleExtensionForActiveTab();
409
- });
410
- await new Promise((r) => setTimeout(r, 100));
411
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
412
- const cdpPage = browser
413
- .contexts()[0]
414
- .pages()
415
- .find((p) => p.url().includes('example.com'));
416
- expect(cdpPage).toBeDefined();
417
- const wsUrl = getCdpUrl({ port: TEST_PORT });
418
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
419
- const initialEvalResult = await cdpSession.send('Runtime.evaluate', {
420
- expression: 'document.title',
421
- returnByValue: true,
422
- });
423
- expect(initialEvalResult.result.value).toBe('Example Domain');
424
- const newUrl = 'https://example.org/';
425
- await cdpPage.goto(newUrl, { waitUntil: 'domcontentloaded' });
426
- expect(cdpPage.url()).toBe(newUrl);
427
- const layoutMetrics = await cdpSession.send('Page.getLayoutMetrics');
428
- expect(layoutMetrics.cssVisualViewport).toBeDefined();
429
- expect(layoutMetrics.cssVisualViewport.clientWidth).toBeGreaterThan(0);
430
- const afterNavEvalResult = await cdpSession.send('Runtime.evaluate', {
431
- expression: 'document.title',
432
- returnByValue: true,
433
- });
434
- expect(afterNavEvalResult.result.value).toContain('Example Domain');
435
- const locationResult = await cdpSession.send('Runtime.evaluate', {
436
- expression: 'window.location.href',
437
- returnByValue: true,
438
- });
439
- expect(locationResult.result.value).toBe(newUrl);
440
- await cdpSession.detach();
441
- await browser.close();
442
- await page.close();
443
- }, 60000);
444
- it('should pause on all exceptions with setPauseOnExceptions', async () => {
445
- const browserContext = getBrowserContext();
446
- const serviceWorker = await getExtensionServiceWorker(browserContext);
447
- const page = await browserContext.newPage();
448
- await page.goto('https://example.com/');
449
- await page.bringToFront();
450
- await serviceWorker.evaluate(async () => {
451
- await globalThis.toggleExtensionForActiveTab();
452
- });
453
- await new Promise((r) => setTimeout(r, 100));
454
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
455
- const cdpPage = browser
456
- .contexts()[0]
457
- .pages()
458
- .find((p) => p.url().includes('example.com'));
459
- expect(cdpPage).toBeDefined();
460
- const wsUrl = getCdpUrl({ port: TEST_PORT });
461
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
462
- const dbg = new Debugger({ cdp: cdpSession });
463
- await dbg.enable();
464
- await dbg.setPauseOnExceptions({ state: 'all' });
465
- const pausedPromise = new Promise((resolve) => {
466
- cdpSession.on('Debugger.paused', () => resolve());
467
- });
468
- const evalPromise = cdpSession.send('Runtime.evaluate', {
469
- expression: `(function() {
470
- try {
471
- throw new Error('Caught test error');
472
- } catch (e) {
473
- // caught but should still pause with state 'all'
474
- }
475
- })()`,
476
- });
477
- await Promise.race([
478
- pausedPromise,
479
- new Promise((_, reject) => setTimeout(() => reject(new Error('Debugger.paused timeout')), 5000)),
480
- ]);
481
- expect(dbg.isPaused()).toBe(true);
482
- const location = await dbg.getLocation();
483
- expect(location.sourceContext).toContain('throw');
484
- await dbg.resume();
485
- await evalPromise;
486
- await dbg.setPauseOnExceptions({ state: 'none' });
487
- await cdpSession.detach();
488
- await browser.close();
489
- await page.close();
490
- }, 60000);
491
- it('should inspect local and global variables with inline snapshots', async () => {
492
- const browserContext = getBrowserContext();
493
- const serviceWorker = await getExtensionServiceWorker(browserContext);
494
- const page = await browserContext.newPage();
495
- await page.setContent(`
496
- <html>
497
- <head>
498
- <script>
499
- const GLOBAL_CONFIG = 'production';
500
- function runTest() {
501
- const userName = 'Alice';
502
- const userAge = 25;
503
- const settings = { theme: 'dark', lang: 'en' };
504
- const scores = [10, 20, 30];
505
- debugger;
506
- return userName;
507
- }
508
- </script>
509
- </head>
510
- <body>
511
- <button onclick="runTest()">Run</button>
512
- </body>
513
- </html>
514
- `);
515
- await page.bringToFront();
516
- await serviceWorker.evaluate(async () => {
517
- await globalThis.toggleExtensionForActiveTab();
518
- });
519
- await new Promise((r) => setTimeout(r, 100));
520
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
521
- let cdpPage;
522
- for (const p of browser.contexts()[0].pages()) {
523
- const html = await p.content();
524
- if (html.includes('runTest')) {
525
- cdpPage = p;
526
- break;
527
- }
528
- }
529
- expect(cdpPage).toBeDefined();
530
- const wsUrl = getCdpUrl({ port: TEST_PORT });
531
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
532
- const dbg = new Debugger({ cdp: cdpSession });
533
- await dbg.enable();
534
- const globalVars = await dbg.inspectGlobalVariables();
535
- expect(globalVars).toMatchInlineSnapshot(`
536
- [
537
- "GLOBAL_CONFIG",
538
- ]
539
- `);
540
- const pausedPromise = new Promise((resolve) => {
541
- cdpSession.on('Debugger.paused', () => resolve());
542
- });
543
- // Don't await - we want it to pause at breakpoint
544
- const evalPromise = cdpPage.evaluate('runTest()').catch(() => {
545
- // Ignore errors from evaluate when browser closes
546
- });
547
- await pausedPromise;
548
- expect(dbg.isPaused()).toBe(true);
549
- const localVars = await dbg.inspectLocalVariables();
550
- expect(localVars).toMatchInlineSnapshot(`
551
- {
552
- "GLOBAL_CONFIG": "production",
553
- "scores": "[array]",
554
- "settings": "[object]",
555
- "userAge": 25,
556
- "userName": "Alice",
557
- }
558
- `);
559
- await dbg.resume();
560
- // Wait for evaluate to complete after resume
561
- await evalPromise;
562
- await cdpSession.detach();
563
- await browser.close();
564
- await page.close();
565
- }, 60000);
566
- it('should click at correct coordinates on high-DPI simulation', async () => {
567
- const browserContext = getBrowserContext();
568
- const serviceWorker = await getExtensionServiceWorker(browserContext);
569
- const page = await browserContext.newPage();
570
- await page.goto('https://example.com/');
571
- await page.bringToFront();
572
- await serviceWorker.evaluate(async () => {
573
- await globalThis.toggleExtensionForActiveTab();
574
- });
575
- await new Promise((r) => setTimeout(r, 100));
576
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
577
- const cdpPage = browser
578
- .contexts()[0]
579
- .pages()
580
- .find((p) => p.url().includes('example.com'));
581
- expect(cdpPage).toBeDefined();
582
- const h1Bounds = await cdpPage.locator('h1').boundingBox();
583
- expect(h1Bounds).toBeDefined();
584
- console.log('H1 bounding box:', h1Bounds);
585
- await cdpPage.evaluate(() => {
586
- ;
587
- window.clickedAt = null;
588
- document.addEventListener('click', (e) => {
589
- ;
590
- window.clickedAt = { x: e.clientX, y: e.clientY };
591
- });
592
- });
593
- await cdpPage.locator('h1').click();
594
- const clickedAt = await cdpPage.evaluate(() => window.clickedAt);
595
- console.log('Clicked at:', clickedAt);
596
- expect(clickedAt).toBeDefined();
597
- expect(clickedAt.x).toBeGreaterThan(0);
598
- expect(clickedAt.y).toBeGreaterThan(0);
599
- await browser.close();
600
- await page.close();
601
- }, 60000);
602
- it('should use Editor class to list, read, and edit scripts', async () => {
603
- const browserContext = getBrowserContext();
604
- const serviceWorker = await getExtensionServiceWorker(browserContext);
605
- const page = await browserContext.newPage();
606
- await page.goto('https://example.com/');
607
- await page.bringToFront();
608
- await serviceWorker.evaluate(async () => {
609
- await globalThis.toggleExtensionForActiveTab();
610
- });
611
- await new Promise((r) => setTimeout(r, 100));
612
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
613
- const cdpPage = browser
614
- .contexts()[0]
615
- .pages()
616
- .find((p) => p.url().includes('example.com'));
617
- expect(cdpPage).toBeDefined();
618
- const wsUrl = getCdpUrl({ port: TEST_PORT });
619
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
620
- const editor = new Editor({ cdp: cdpSession });
621
- await editor.enable();
622
- await cdpPage.addScriptTag({
623
- content: `
624
- function greetUser(name) {
625
- console.log('Hello, ' + name);
626
- return 'Hello, ' + name;
627
- }
628
- `,
629
- });
630
- await new Promise((r) => setTimeout(r, 100));
631
- const scripts = await editor.list();
632
- expect(scripts.length).toBeGreaterThan(0);
633
- const matches = await editor.grep({ regex: /greetUser/ });
634
- expect(matches.length).toBeGreaterThan(0);
635
- const match = matches[0];
636
- const { content, totalLines } = await editor.read({ url: match.url });
637
- expect(content).toContain('greetUser');
638
- expect(totalLines).toBeGreaterThan(0);
639
- await editor.edit({
640
- url: match.url,
641
- oldString: "console.log('Hello, ' + name);",
642
- newString: "console.log('Hello, ' + name); console.log('EDITOR_TEST_MARKER');",
643
- });
644
- const consoleLogs = [];
645
- cdpPage.on('console', (msg) => {
646
- consoleLogs.push(msg.text());
647
- });
648
- await cdpPage.evaluate(() => {
649
- ;
650
- window.greetUser('World');
651
- });
652
- await new Promise((r) => setTimeout(r, 100));
653
- expect(consoleLogs).toContain('Hello, World');
654
- expect(consoleLogs).toContain('EDITOR_TEST_MARKER');
655
- await cdpSession.detach();
656
- await browser.close();
657
- await page.close();
658
- }, 60000);
659
- it('editor can list, read, and edit CSS stylesheets', async () => {
660
- const browserContext = getBrowserContext();
661
- const serviceWorker = await getExtensionServiceWorker(browserContext);
662
- const page = await browserContext.newPage();
663
- await page.goto('https://example.com/');
664
- await page.bringToFront();
665
- await serviceWorker.evaluate(async () => {
666
- await globalThis.toggleExtensionForActiveTab();
667
- });
668
- await new Promise((r) => setTimeout(r, 100));
669
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
670
- const cdpPage = browser
671
- .contexts()[0]
672
- .pages()
673
- .find((p) => p.url().includes('example.com'));
674
- expect(cdpPage).toBeDefined();
675
- const wsUrl = getCdpUrl({ port: TEST_PORT });
676
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
677
- const editor = new Editor({ cdp: cdpSession });
678
- await editor.enable();
679
- await cdpPage.addStyleTag({
680
- content: `
681
- .editor-test-element {
682
- color: rgb(255, 0, 0);
683
- background-color: rgb(0, 0, 255);
684
- }
685
- `,
686
- });
687
- await new Promise((r) => setTimeout(r, 100));
688
- const stylesheets = await editor.list({ pattern: /inline-css:/ });
689
- expect(stylesheets.length).toBeGreaterThan(0);
690
- const cssMatches = await editor.grep({ regex: /editor-test-element/, pattern: /inline-css:/ });
691
- expect(cssMatches.length).toBeGreaterThan(0);
692
- const cssMatch = cssMatches[0];
693
- const { content, totalLines } = await editor.read({ url: cssMatch.url });
694
- expect(content).toContain('editor-test-element');
695
- expect(content).toContain('rgb(255, 0, 0)');
696
- expect(totalLines).toBeGreaterThan(0);
697
- await cdpPage.evaluate(() => {
698
- const el = document.createElement('div');
699
- el.className = 'editor-test-element';
700
- el.id = 'test-div';
701
- el.textContent = 'Test';
702
- document.body.appendChild(el);
703
- });
704
- const colorBefore = await cdpPage.evaluate(() => {
705
- const el = document.getElementById('test-div');
706
- return window.getComputedStyle(el).color;
707
- });
708
- expect(colorBefore).toBe('rgb(255, 0, 0)');
709
- await editor.edit({
710
- url: cssMatch.url,
711
- oldString: 'color: rgb(255, 0, 0);',
712
- newString: 'color: rgb(0, 255, 0);',
713
- });
714
- const colorAfter = await cdpPage.evaluate(() => {
715
- const el = document.getElementById('test-div');
716
- return window.getComputedStyle(el).color;
717
- });
718
- expect(colorAfter).toBe('rgb(0, 255, 0)');
719
- await cdpSession.detach();
720
- await browser.close();
721
- await page.close();
722
- }, 60000);
723
- it('should inject bippy and find React fiber with getReactSource', async () => {
724
- const browserContext = getBrowserContext();
725
- const serviceWorker = await getExtensionServiceWorker(browserContext);
726
- const page = await browserContext.newPage();
727
- await page.setContent(`
728
- <!DOCTYPE html>
729
- <html>
730
- <head>
731
- <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
732
- <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
733
- </head>
734
- <body>
735
- <div id="root"></div>
736
- <script>
737
- function SaveButton(props) {
738
- return React.createElement('button', { id: 'react-btn' }, props.label);
739
- }
740
- function Panel() {
741
- return React.createElement('section', null, React.createElement(SaveButton, {
742
- label: 'Click me',
743
- count: 3,
744
- config: { variant: 'primary' },
745
- onClick: () => {}
746
- }));
747
- }
748
- function App() {
749
- return React.createElement(Panel);
750
- }
751
- const root = ReactDOM.createRoot(document.getElementById('root'));
752
- root.render(React.createElement(App));
753
- </script>
754
- <button id="plain-btn">Plain</button>
755
- </body>
756
- </html>
757
- `);
758
- await page.bringToFront();
759
- await serviceWorker.evaluate(async () => {
760
- await globalThis.toggleExtensionForActiveTab();
761
- });
762
- await new Promise((r) => setTimeout(r, 500));
763
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
764
- const pages = browser.contexts()[0].pages();
765
- const cdpPage = pages.find((p) => p.url().startsWith('about:'));
766
- expect(cdpPage).toBeDefined();
767
- const btn = cdpPage.locator('#react-btn');
768
- const btnCount = await btn.count();
769
- expect(btnCount).toBe(1);
770
- const hasBippyBefore = await cdpPage.evaluate(() => !!globalThis.__bippy);
771
- expect(hasBippyBefore).toBe(false);
772
- const wsUrl = getCdpUrl({ port: TEST_PORT });
773
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
774
- const { getReactSource, getReactComponentInfo } = await import('./react-source.js');
775
- const source = await getReactSource({ locator: btn, cdp: cdpSession });
776
- const info = await getReactComponentInfo({ locator: btn, cdp: cdpSession });
777
- const plainInfo = await getReactComponentInfo({ locator: cdpPage.locator('#plain-btn'), cdp: cdpSession });
778
- const hasBippyAfter = await cdpPage.evaluate(() => !!globalThis.__bippy);
779
- expect(hasBippyAfter).toBe(true);
780
- const hasFiber = await btn.evaluate((el) => {
781
- const bippy = globalThis.__bippy;
782
- if (!bippy)
783
- return false;
784
- const fiber = bippy.getFiberFromHostInstance(el);
785
- return !!fiber;
786
- });
787
- expect(hasFiber).toBe(true);
788
- const componentName = await btn.evaluate((el) => {
789
- const bippy = globalThis.__bippy;
790
- if (!bippy)
791
- return null;
792
- const fiber = bippy.getFiberFromHostInstance(el);
793
- let current = fiber;
794
- while (current) {
795
- if (bippy.isCompositeFiber(current)) {
796
- return bippy.getDisplayName(current.type);
797
- }
798
- current = current.return ?? null;
799
- }
800
- return null;
801
- });
802
- expect(componentName).toBe('SaveButton');
803
- expect(plainInfo).toBe(null);
804
- expect(info?.componentName).toBe('SaveButton');
805
- expect(info?.hierarchy.map((item) => item.componentName)).toEqual(['SaveButton', 'Panel', 'App']);
806
- expect(info?.props).toEqual({
807
- label: 'Click me',
808
- count: 3,
809
- config: { variant: 'primary' },
810
- onClick: '[function]',
811
- });
812
- console.log('Component name from fiber:', componentName);
813
- console.log('React component info:', info);
814
- console.log('Source location (null for UMD React, works on local dev servers with JSX transform):', source);
815
- await browser.close();
816
- await page.close();
817
- }, 60000);
818
- });
819
- // --- Service Worker Target Tests ---
820
- describe('Service Worker Target Tests', () => {
821
- let testCtx = null;
822
- beforeAll(async () => {
823
- testCtx = await setupTestContext({ port: TEST_PORT, tempDirPrefix: 'pw-sw-test-', toggleExtension: true });
824
- }, 600000);
825
- afterAll(async () => {
826
- await cleanupTestContext(testCtx);
827
- testCtx = null;
828
- });
829
- const getBrowserContext = () => {
830
- if (!testCtx?.browserContext)
831
- throw new Error('Browser not initialized');
832
- return testCtx.browserContext;
833
- };
834
- it('should not expose service worker targets to Playwright (issue #14)', async () => {
835
- const browserContext = getBrowserContext();
836
- const serviceWorker = await getExtensionServiceWorker(browserContext);
837
- const page = await browserContext.newPage();
838
- await page.goto('https://web.dev/', { waitUntil: 'load' });
839
- await page.bringToFront();
840
- await serviceWorker.evaluate(async () => {
841
- await globalThis.toggleExtensionForActiveTab();
842
- });
843
- await new Promise((r) => setTimeout(r, 500));
844
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
845
- const context = browser.contexts()[0];
846
- const pages = context.pages();
847
- for (const p of pages) {
848
- const url = p.url();
849
- console.log('Page URL:', url);
850
- expect(url).not.toMatch(/sw\.js$/i);
851
- expect(url).not.toMatch(/service.?worker/i);
852
- }
853
- const targetPage = pages.find((p) => p.url().includes('web.dev'));
854
- expect(targetPage).toBeDefined();
855
- const title = await targetPage.title();
856
- expect(title).toBeTruthy();
857
- await safeCloseCDPBrowser(browser);
858
- await page.close();
859
- }, 60000);
860
- it('should allow reading response bodies after re-enabling Network buffering', async () => {
861
- const browserContext = getBrowserContext();
862
- const serviceWorker = await getExtensionServiceWorker(browserContext);
863
- const page = await browserContext.newPage();
864
- await page.goto('https://example.com/');
865
- await page.bringToFront();
866
- await serviceWorker.evaluate(async () => {
867
- await globalThis.toggleExtensionForActiveTab();
868
- });
869
- await new Promise((r) => setTimeout(r, 100));
870
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
871
- const cdpPage = browser
872
- .contexts()[0]
873
- .pages()
874
- .find((p) => p.url().includes('example.com'));
875
- expect(cdpPage).toBeDefined();
876
- const wsUrl = getCdpUrl({ port: TEST_PORT });
877
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
878
- await cdpSession.send('Network.disable');
879
- await cdpSession.send('Network.enable', {
880
- maxTotalBufferSize: 10000000,
881
- maxResourceBufferSize: 5000000,
882
- });
883
- const [response] = await Promise.all([
884
- cdpPage.waitForResponse((resp) => resp.url() === 'https://example.com/'),
885
- cdpPage.goto('https://example.com/'),
886
- ]);
887
- const body = await response.text();
888
- expect(body).toBeDefined();
889
- expect(body).toContain('Example Domain');
890
- expect(body).toContain('</html>');
891
- await cdpSession.detach();
892
- await browser.close();
893
- await page.close();
894
- }, 60000);
895
- it('should stream SSE without waiting for response end', async () => {
896
- const browserContext = getBrowserContext();
897
- const serviceWorker = await withTimeout({
898
- promise: getExtensionServiceWorker(browserContext),
899
- timeoutMs: 5000,
900
- errorMessage: 'getExtensionServiceWorker timed out',
901
- });
902
- const sseServer = await withTimeout({
903
- promise: createSseServer(),
904
- timeoutMs: 5000,
905
- errorMessage: 'createSseServer timed out',
906
- });
907
- let page = null;
908
- let browser = null;
909
- try {
910
- page = await withTimeout({
911
- promise: browserContext.newPage(),
912
- timeoutMs: 5000,
913
- errorMessage: 'newPage timed out',
914
- });
915
- await withTimeout({
916
- promise: page.goto(`${sseServer.baseUrl}/`),
917
- timeoutMs: 5000,
918
- errorMessage: 'page.goto timed out',
919
- });
920
- await page.bringToFront();
921
- await withTimeout({
922
- promise: serviceWorker.evaluate(async () => {
923
- await globalThis.toggleExtensionForActiveTab();
924
- }),
925
- timeoutMs: 5000,
926
- errorMessage: 'toggleExtensionForActiveTab timed out',
927
- });
928
- await new Promise((resolve) => {
929
- setTimeout(resolve, 100);
930
- });
931
- browser = await withTimeout({
932
- promise: chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT })),
933
- timeoutMs: 5000,
934
- errorMessage: 'connectOverCDP timed out',
935
- });
936
- const cdpPage = browser
937
- .contexts()[0]
938
- .pages()
939
- .find((p) => {
940
- return p.url().startsWith(sseServer.baseUrl);
941
- });
942
- expect(cdpPage).toBeDefined();
943
- await cdpPage.evaluate(() => {
944
- return window.startSse();
945
- });
946
- await withTimeout({
947
- promise: cdpPage.waitForFunction(() => {
948
- return window.__sseMessages.length > 0;
949
- }, { timeout: 5000 }),
950
- timeoutMs: 7000,
951
- errorMessage: 'SSE message not received in time',
952
- });
953
- const firstMessage = await cdpPage.evaluate(() => {
954
- return window.__sseMessages[0];
955
- });
956
- expect(firstMessage).toBe('hello');
957
- const sseState = sseServer.getState();
958
- expect(sseState.connected).toBe(true);
959
- expect(sseState.finished).toBe(false);
960
- expect(sseState.closed).toBe(false);
961
- expect(sseState.writeCount).toBeGreaterThan(0);
962
- const readyState = await cdpPage.evaluate(() => {
963
- if (!window.__sseSource) {
964
- return -1;
965
- }
966
- return window.__sseSource.readyState;
967
- });
968
- expect(readyState).toBe(1);
969
- await cdpPage.evaluate(() => {
970
- window.stopSse();
971
- });
972
- await new Promise((resolve) => {
973
- setTimeout(resolve, 100);
974
- });
975
- }
976
- finally {
977
- if (browser) {
978
- await withTimeout({
979
- promise: browser.close(),
980
- timeoutMs: 5000,
981
- errorMessage: 'browser.close timed out',
982
- });
983
- }
984
- if (page) {
985
- await withTimeout({
986
- promise: page.close(),
987
- timeoutMs: 5000,
988
- errorMessage: 'page.close timed out',
989
- });
990
- }
991
- await withTimeout({
992
- promise: sseServer.close(),
993
- timeoutMs: 5000,
994
- errorMessage: 'sseServer.close timed out',
995
- });
996
- }
997
- }, 60000);
998
- });
999
- // --- Auto-enable Tests ---
1000
- describe('Auto-enable Tests', () => {
1001
- let testCtx = null;
1002
- let client;
1003
- let cleanup = null;
1004
- beforeAll(async () => {
1005
- process.env.PLAYWRITER_AUTO_ENABLE = '1';
1006
- testCtx = await setupTestContext({ port: TEST_PORT, tempDirPrefix: 'pw-auto-test-' });
1007
- const result = await createMCPClient({ port: TEST_PORT });
1008
- client = result.client;
1009
- cleanup = result.cleanup;
1010
- // Disconnect all tabs to start with a clean state
1011
- const serviceWorker = await getExtensionServiceWorker(testCtx.browserContext);
1012
- await serviceWorker.evaluate(async () => {
1013
- await globalThis.disconnectEverything();
1014
- });
1015
- await new Promise((r) => setTimeout(r, 100));
1016
- }, 600000);
1017
- afterAll(async () => {
1018
- delete process.env.PLAYWRITER_AUTO_ENABLE;
1019
- await cleanupTestContext(testCtx, cleanup);
1020
- cleanup = null;
1021
- testCtx = null;
1022
- });
1023
- const getBrowserContext = () => {
1024
- if (!testCtx?.browserContext)
1025
- throw new Error('Browser not initialized');
1026
- return testCtx.browserContext;
1027
- };
1028
- it('should auto-create a tab when Playwright connects and no tabs exist', async () => {
1029
- const browserContext = getBrowserContext();
1030
- const serviceWorker = await getExtensionServiceWorker(browserContext);
1031
- await serviceWorker.evaluate(async () => {
1032
- await globalThis.disconnectEverything();
1033
- });
1034
- await new Promise((r) => setTimeout(r, 100));
1035
- const tabCountBefore = await serviceWorker.evaluate(() => {
1036
- const state = globalThis.getExtensionState();
1037
- return state.tabs.size;
1038
- });
1039
- expect(tabCountBefore).toBe(0);
1040
- const previousAutoEnable = process.env.PLAYWRITER_AUTO_ENABLE;
1041
- delete process.env.PLAYWRITER_AUTO_ENABLE;
1042
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT })).finally(() => {
1043
- if (previousAutoEnable === undefined) {
1044
- delete process.env.PLAYWRITER_AUTO_ENABLE;
1045
- return;
1046
- }
1047
- process.env.PLAYWRITER_AUTO_ENABLE = previousAutoEnable;
1048
- });
1049
- const pages = browser.contexts()[0].pages();
1050
- expect(pages.length).toBeGreaterThan(0);
1051
- expect(pages.length).toBe(1);
1052
- const autoCreatedPage = pages[0];
1053
- expect(autoCreatedPage.url()).toBe('about:blank');
1054
- const tabCountAfter = await serviceWorker.evaluate(() => {
1055
- const state = globalThis.getExtensionState();
1056
- return state.tabs.size;
1057
- });
1058
- expect(tabCountAfter).toBe(1);
1059
- await autoCreatedPage.setContent('<h1>Auto-created page</h1>');
1060
- const title = await autoCreatedPage.locator('h1').textContent();
1061
- expect(title).toBe('Auto-created page');
1062
- await browser.close();
1063
- }, 60000);
1064
- it('should auto-create a page when MCP executes with no connected pages', async () => {
1065
- const browserContext = getBrowserContext();
1066
- const serviceWorker = await getExtensionServiceWorker(browserContext);
1067
- await serviceWorker.evaluate(async () => {
1068
- await globalThis.disconnectEverything();
1069
- });
1070
- await new Promise((r) => {
1071
- setTimeout(r, 100);
1072
- });
1073
- const tabCountBefore = await serviceWorker.evaluate(() => {
1074
- const state = globalThis.getExtensionState();
1075
- return state.tabs.size;
1076
- });
1077
- expect(tabCountBefore).toBe(0);
1078
- const result = await client.callTool({
1079
- name: 'execute',
1080
- arguments: {
1081
- code: js `
1082
- return { pageCount: context.pages().length, url: page.url() };
1083
- `,
1084
- },
1085
- });
1086
- expect(result.isError).toBeFalsy();
1087
- const text = result.content[0].text;
1088
- expect(text).toContain('pageCount');
1089
- expect(text).toContain('about:blank');
1090
- const tabCountAfter = await serviceWorker.evaluate(() => {
1091
- const state = globalThis.getExtensionState();
1092
- return state.tabs.size;
1093
- });
1094
- expect(tabCountAfter).toBe(1);
1095
- await client.callTool({
1096
- name: 'execute',
1097
- arguments: {
1098
- code: js `
1099
- await page.close();
1100
- return { remaining: context.pages().length };
1101
- `,
1102
- },
1103
- });
1104
- await new Promise((r) => {
1105
- setTimeout(r, 100);
1106
- });
1107
- const afterCloseResult = await client.callTool({
1108
- name: 'execute',
1109
- arguments: {
1110
- code: js `
1111
- return { pageCount: context.pages().length, url: page.url() };
1112
- `,
1113
- },
1114
- });
1115
- expect(afterCloseResult.isError).toBeFalsy();
1116
- const afterCloseText = afterCloseResult.content[0].text;
1117
- expect(afterCloseText).toContain('pageCount');
1118
- expect(afterCloseText).toContain('about:blank');
1119
- }, 60000);
1120
- });
1121
- //# sourceMappingURL=relay-session.test.js.map