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,855 +0,0 @@
1
- import fs from 'node:fs'
2
- import os from 'node:os'
3
- import path from 'node:path'
4
- import { createMCPClient } from './mcp-client.js'
5
- import { describe, it, expect, beforeAll, afterAll } from 'vitest'
6
- import { chromium } from '@xmorse/playwright-core'
7
- import { getCdpUrl } from './utils.js'
8
- import {
9
- setupTestContext,
10
- cleanupTestContext,
11
- getExtensionServiceWorker,
12
- launchPersistentContextWithExtensions,
13
- type TestContext,
14
- js,
15
- } from './test-utils.js'
16
- import { getExtensionsStatus } from './relay-client.js'
17
- import './test-declarations.js'
18
-
19
- const TEST_PORT = 19990
20
-
21
- describe('Extension Connection Tests', () => {
22
- let client: Awaited<ReturnType<typeof createMCPClient>>['client']
23
- let cleanup: (() => Promise<void>) | null = null
24
- let testCtx: TestContext | null = null
25
-
26
- beforeAll(async () => {
27
- testCtx = await setupTestContext({ port: TEST_PORT, tempDirPrefix: 'pw-conn-test-', toggleExtension: true })
28
-
29
- const result = await createMCPClient({ port: TEST_PORT })
30
- client = result.client
31
- cleanup = result.cleanup
32
- }, 600000)
33
-
34
- afterAll(async () => {
35
- await cleanupTestContext(testCtx, cleanup)
36
- cleanup = null
37
- testCtx = null
38
- })
39
-
40
- const getBrowserContext = () => {
41
- if (!testCtx?.browserContext) throw new Error('Browser not initialized')
42
- return testCtx.browserContext
43
- }
44
-
45
- it('should handle new pages and toggling with new connections', async () => {
46
- const browserContext = getBrowserContext()
47
- const serviceWorker = await getExtensionServiceWorker(browserContext)
48
-
49
- // 1. Create a new page
50
- const page = await browserContext.newPage()
51
- const testUrl = 'https://example.com/'
52
- await page.goto(testUrl)
53
-
54
- await page.bringToFront()
55
-
56
- // 2. Enable extension on this new tab
57
- const result = await serviceWorker.evaluate(async () => {
58
- return await globalThis.toggleExtensionForActiveTab()
59
- })
60
- expect(result.isConnected).toBe(true)
61
-
62
- // 3. Verify we can connect via direct CDP and see the page
63
- let directBrowser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
64
- let contexts = directBrowser.contexts()
65
- let pages = contexts[0].pages()
66
-
67
- let foundPage = pages.find((p) => p.url() === testUrl)
68
- expect(foundPage).toBeDefined()
69
- expect(foundPage?.url()).toBe(testUrl)
70
-
71
- const sum1 = await foundPage?.evaluate(() => 1 + 1)
72
- expect(sum1).toBe(2)
73
-
74
- await directBrowser.close()
75
-
76
- // 4. Disable extension on this tab
77
- const resultDisabled = await serviceWorker.evaluate(async () => {
78
- return await globalThis.toggleExtensionForActiveTab()
79
- })
80
- expect(resultDisabled.isConnected).toBe(false)
81
-
82
- // 5. Connect again - page should NOT be visible
83
- directBrowser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
84
- contexts = directBrowser.contexts()
85
- pages = contexts[0].pages()
86
-
87
- foundPage = pages.find((p) => p.url() === testUrl)
88
- expect(foundPage).toBeUndefined()
89
-
90
- await directBrowser.close()
91
-
92
- // 6. Re-enable extension
93
- const resultEnabled = await serviceWorker.evaluate(async () => {
94
- return await globalThis.toggleExtensionForActiveTab()
95
- })
96
- expect(resultEnabled.isConnected).toBe(true)
97
-
98
- // 7. Verify page is back
99
- directBrowser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
100
- await new Promise((r) => setTimeout(r, 100))
101
-
102
- contexts = directBrowser.contexts()
103
- if (contexts[0].pages().length === 0) {
104
- await new Promise((r) => setTimeout(r, 100))
105
- }
106
- pages = contexts[0].pages()
107
-
108
- foundPage = pages.find((p) => p.url() === testUrl)
109
- expect(foundPage).toBeDefined()
110
- expect(foundPage?.url()).toBe(testUrl)
111
-
112
- const sum2 = await foundPage?.evaluate(() => 2 + 2)
113
- expect(sum2).toBe(4)
114
-
115
- await directBrowser.close()
116
- await page.close()
117
- }, 120000)
118
-
119
- it('should handle new pages and toggling with persistent connection', async () => {
120
- const browserContext = getBrowserContext()
121
- const serviceWorker = await getExtensionServiceWorker(browserContext)
122
-
123
- const directBrowser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
124
- await new Promise((r) => setTimeout(r, 100))
125
-
126
- // 1. Create a new page
127
- const page = await browserContext.newPage()
128
- const testUrl = 'https://example.com/persistent'
129
- await page.goto(testUrl)
130
- await page.bringToFront()
131
-
132
- // 2. Enable extension
133
- await serviceWorker.evaluate(async () => {
134
- await globalThis.toggleExtensionForActiveTab()
135
- })
136
-
137
- // 3. Verify page appears (polling)
138
- let foundPage
139
- for (let i = 0; i < 50; i++) {
140
- const pages = directBrowser.contexts()[0].pages()
141
- foundPage = pages.find((p) => p.url() === testUrl)
142
- if (foundPage) break
143
- await new Promise((r) => setTimeout(r, 100))
144
- }
145
- expect(foundPage).toBeDefined()
146
- expect(foundPage?.url()).toBe(testUrl)
147
-
148
- const sum1 = await foundPage?.evaluate(() => 10 + 20)
149
- expect(sum1).toBe(30)
150
-
151
- // 4. Disable extension
152
- await serviceWorker.evaluate(async () => {
153
- await globalThis.toggleExtensionForActiveTab()
154
- })
155
-
156
- // 5. Verify page disappears (polling)
157
- for (let i = 0; i < 50; i++) {
158
- const pages = directBrowser.contexts()[0].pages()
159
- foundPage = pages.find((p) => p.url() === testUrl)
160
- if (!foundPage) break
161
- await new Promise((r) => setTimeout(r, 100))
162
- }
163
- expect(foundPage).toBeUndefined()
164
-
165
- // 6. Re-enable extension
166
- await serviceWorker.evaluate(async () => {
167
- await globalThis.toggleExtensionForActiveTab()
168
- })
169
-
170
- // 7. Verify page reappears (polling)
171
- for (let i = 0; i < 50; i++) {
172
- const pages = directBrowser.contexts()[0].pages()
173
- foundPage = pages.find((p) => p.url() === testUrl)
174
- if (foundPage) break
175
- await new Promise((r) => setTimeout(r, 100))
176
- }
177
- expect(foundPage).toBeDefined()
178
- expect(foundPage?.url()).toBe(testUrl)
179
-
180
- const sum2 = await foundPage?.evaluate(() => 30 + 40)
181
- expect(sum2).toBe(70)
182
-
183
- await page.close()
184
- await directBrowser.close()
185
- })
186
-
187
- it('should maintain connection across reloads and navigation', async () => {
188
- const browserContext = getBrowserContext()
189
- const serviceWorker = await getExtensionServiceWorker(browserContext)
190
-
191
- // 1. Setup page
192
- const page = await browserContext.newPage()
193
- const initialUrl = 'https://example.com/'
194
- await page.goto(initialUrl)
195
- await page.bringToFront()
196
-
197
- // 2. Enable extension
198
- await serviceWorker.evaluate(async () => {
199
- await globalThis.toggleExtensionForActiveTab()
200
- })
201
-
202
- // 3. Connect via CDP
203
- const cdpUrl = getCdpUrl({ port: TEST_PORT })
204
- const directBrowser = await chromium.connectOverCDP(cdpUrl)
205
- const connectedPage = directBrowser
206
- .contexts()[0]
207
- .pages()
208
- .find((p) => p.url() === initialUrl)
209
- expect(connectedPage).toBeDefined()
210
-
211
- expect(await connectedPage?.evaluate(() => 1 + 1)).toBe(2)
212
-
213
- // 4. Reload
214
- await connectedPage?.reload()
215
- await connectedPage?.waitForLoadState('domcontentloaded')
216
- expect(await connectedPage?.title()).toBe('Example Domain')
217
-
218
- expect(await connectedPage?.evaluate(() => 2 + 2)).toBe(4)
219
-
220
- // 5. Navigate to new URL
221
- const newUrl = 'https://example.org/'
222
- await connectedPage?.goto(newUrl)
223
- await connectedPage?.waitForLoadState('domcontentloaded')
224
-
225
- expect(connectedPage?.url()).toBe(newUrl)
226
- expect(await connectedPage?.title()).toContain('Example Domain')
227
-
228
- expect(await connectedPage?.evaluate(() => 3 + 3)).toBe(6)
229
-
230
- await directBrowser.close()
231
- await page.close()
232
- })
233
-
234
- it('should support multiple concurrent tabs', async () => {
235
- const browserContext = getBrowserContext()
236
- const serviceWorker = await getExtensionServiceWorker(browserContext)
237
- await new Promise((resolve) => setTimeout(resolve, 100))
238
-
239
- // Tab A
240
- const pageA = await browserContext.newPage()
241
- await pageA.goto('https://example.com/tab-a')
242
- await pageA.bringToFront()
243
- await new Promise((resolve) => setTimeout(resolve, 100))
244
- await serviceWorker.evaluate(async () => {
245
- await globalThis.toggleExtensionForActiveTab()
246
- })
247
-
248
- // Tab B
249
- const pageB = await browserContext.newPage()
250
- await pageB.goto('https://example.com/tab-b')
251
- await pageB.bringToFront()
252
- await new Promise((resolve) => setTimeout(resolve, 100))
253
- await serviceWorker.evaluate(async () => {
254
- await globalThis.toggleExtensionForActiveTab()
255
- })
256
-
257
- // Get target IDs for both
258
- const targetIds = await serviceWorker.evaluate(async () => {
259
- const state = globalThis.getExtensionState()
260
- const chrome = globalThis.chrome
261
- const tabs = await chrome.tabs.query({})
262
- const tabA = tabs.find((t: any) => t.url?.includes('tab-a'))
263
- const tabB = tabs.find((t: any) => t.url?.includes('tab-b'))
264
- return {
265
- idA: state.tabs.get(tabA?.id ?? -1)?.targetId,
266
- idB: state.tabs.get(tabB?.id ?? -1)?.targetId,
267
- }
268
- })
269
-
270
- expect(targetIds).toMatchInlineSnapshot(
271
- {
272
- idA: expect.any(String),
273
- idB: expect.any(String),
274
- },
275
- `
276
- {
277
- "idA": Any<String>,
278
- "idB": Any<String>,
279
- }
280
- `,
281
- )
282
- expect(targetIds.idA).not.toBe(targetIds.idB)
283
-
284
- // Verify independent connections
285
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
286
-
287
- const pages = browser.contexts()[0].pages()
288
-
289
- const results = await Promise.all(
290
- pages.map(async (p) => ({
291
- url: p.url(),
292
- title: await p.title(),
293
- })),
294
- )
295
-
296
- expect(results).toMatchInlineSnapshot(`
297
- [
298
- {
299
- "title": "",
300
- "url": "about:blank",
301
- },
302
- {
303
- "title": "Example Domain",
304
- "url": "https://example.com/tab-a",
305
- },
306
- {
307
- "title": "Example Domain",
308
- "url": "https://example.com/tab-b",
309
- },
310
- ]
311
- `)
312
-
313
- // Verify execution on both pages
314
- const pageA_CDP = pages.find((p) => p.url().includes('tab-a'))
315
- const pageB_CDP = pages.find((p) => p.url().includes('tab-b'))
316
-
317
- expect(await pageA_CDP?.evaluate(() => 10 + 10)).toBe(20)
318
- expect(await pageB_CDP?.evaluate(() => 20 + 20)).toBe(40)
319
-
320
- await browser.close()
321
- await pageA.close()
322
- await pageB.close()
323
- })
324
-
325
- it('should warn and switch page when the active page closes', async () => {
326
- const browserContext = getBrowserContext()
327
- const serviceWorker = await getExtensionServiceWorker(browserContext)
328
-
329
- const pageA = await browserContext.newPage()
330
- await pageA.goto('https://example.com/close-warning-a')
331
- await pageA.bringToFront()
332
- await serviceWorker.evaluate(async () => {
333
- await globalThis.toggleExtensionForActiveTab()
334
- })
335
-
336
- const pageB = await browserContext.newPage()
337
- await pageB.goto('https://example.com/close-warning-b')
338
- await pageB.bringToFront()
339
- await serviceWorker.evaluate(async () => {
340
- await globalThis.toggleExtensionForActiveTab()
341
- })
342
-
343
- const closeResult = await client.callTool({
344
- name: 'execute',
345
- arguments: {
346
- code: js`
347
- state.page = page;
348
- const closedUrl = state.page.url();
349
- await state.page.close();
350
- return { closedUrl, remainingPages: context.pages().length };
351
- `,
352
- },
353
- })
354
-
355
- const closeOutput = (closeResult as any).content[0].text
356
- expect(closeOutput).toContain('[WARNING] The current page in state.page was closed')
357
- expect(closeOutput).toContain('Switched active page to index')
358
- expect((closeResult as any).isError).not.toBe(true)
359
-
360
- const nextResult = await client.callTool({
361
- name: 'execute',
362
- arguments: {
363
- code: js`
364
- return { pageUrl: page.url(), pagesCount: context.pages().length };
365
- `,
366
- },
367
- })
368
-
369
- const nextOutput = (nextResult as any).content[0].text
370
- expect(nextOutput).toContain('pagesCount')
371
- expect(nextOutput).not.toContain('No Playwright pages are available')
372
- expect(nextOutput).not.toContain('[WARNING] The current page was closed')
373
- expect((nextResult as any).isError).not.toBe(true)
374
-
375
- if (!pageA.isClosed()) {
376
- await pageA.close()
377
- }
378
- if (!pageB.isClosed()) {
379
- await pageB.close()
380
- }
381
- })
382
-
383
- it('should switch page without warning when closed page is not stored in state', async () => {
384
- const browserContext = getBrowserContext()
385
- const serviceWorker = await getExtensionServiceWorker(browserContext)
386
-
387
- const pageA = await browserContext.newPage()
388
- await pageA.goto('https://example.com/close-no-state-warning-a')
389
- await pageA.bringToFront()
390
- await serviceWorker.evaluate(async () => {
391
- await globalThis.toggleExtensionForActiveTab()
392
- })
393
-
394
- const pageB = await browserContext.newPage()
395
- await pageB.goto('https://example.com/close-no-state-warning-b')
396
- await pageB.bringToFront()
397
- await serviceWorker.evaluate(async () => {
398
- await globalThis.toggleExtensionForActiveTab()
399
- })
400
-
401
- const closeResult = await client.callTool({
402
- name: 'execute',
403
- arguments: {
404
- code: js`
405
- const closedUrl = page.url();
406
- await page.close();
407
- return { closedUrl, remainingPages: context.pages().length };
408
- `,
409
- },
410
- })
411
-
412
- const closeOutput = (closeResult as any).content[0].text
413
- expect(closeOutput).not.toContain('[WARNING] The current page in state.page was closed')
414
- expect(closeOutput).not.toContain('Switched active page to index')
415
- expect((closeResult as any).isError).not.toBe(true)
416
-
417
- const nextResult = await client.callTool({
418
- name: 'execute',
419
- arguments: {
420
- code: js`
421
- return { pageUrl: page.url(), pagesCount: context.pages().length };
422
- `,
423
- },
424
- })
425
-
426
- const nextOutput = (nextResult as any).content[0].text
427
- expect(nextOutput).toContain('pagesCount')
428
- expect((nextResult as any).isError).not.toBe(true)
429
-
430
- if (!pageA.isClosed()) {
431
- await pageA.close()
432
- }
433
- if (!pageB.isClosed()) {
434
- await pageB.close()
435
- }
436
- })
437
-
438
- it('should show correct url when enabling extension after navigation', async () => {
439
- const browserContext = getBrowserContext()
440
- const serviceWorker = await getExtensionServiceWorker(browserContext)
441
-
442
- const page = await browserContext.newPage()
443
- const targetUrl = 'https://example.com/late-enable'
444
- await page.goto(targetUrl)
445
- await page.bringToFront()
446
-
447
- await page.waitForLoadState('domcontentloaded')
448
-
449
- await serviceWorker.evaluate(async () => {
450
- await globalThis.toggleExtensionForActiveTab()
451
- })
452
-
453
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
454
- await new Promise((r) => setTimeout(r, 100))
455
-
456
- const cdpPage = browser
457
- .contexts()[0]
458
- .pages()
459
- .find((p) => p.url() === targetUrl)
460
-
461
- expect(cdpPage).toBeDefined()
462
- expect(cdpPage?.url()).toBe(targetUrl)
463
-
464
- await browser.close()
465
- await page.close()
466
- }, 60000)
467
-
468
- it('should be able to reconnect after disconnecting everything', async () => {
469
- const browserContext = getBrowserContext()
470
- const serviceWorker = await getExtensionServiceWorker(browserContext)
471
-
472
- const pages = await browserContext.pages()
473
- expect(pages.length).toBeGreaterThan(0)
474
- const page = pages[0]
475
-
476
- await page.goto('https://example.com/disconnect-test')
477
- await page.waitForLoadState('domcontentloaded')
478
- await page.bringToFront()
479
-
480
- // Enable extension on this page
481
- const initialEnable = await serviceWorker.evaluate(async () => {
482
- return await globalThis.toggleExtensionForActiveTab()
483
- })
484
- console.log('Initial enable result:', initialEnable)
485
- expect(initialEnable.isConnected).toBe(true)
486
-
487
- await new Promise((resolve) => setTimeout(resolve, 100))
488
-
489
- // Verify MCP can see the page
490
- const beforeDisconnect = await client.callTool({
491
- name: 'execute',
492
- arguments: {
493
- code: js`
494
- const pages = context.pages();
495
- console.log('Pages before disconnect:', pages.length);
496
- const testPage = pages.find(p => p.url().includes('disconnect-test'));
497
- console.log('Found test page:', !!testPage);
498
- return { pagesCount: pages.length, foundTestPage: !!testPage };
499
- `,
500
- },
501
- })
502
-
503
- const beforeOutput = (beforeDisconnect as any).content[0].text
504
- expect(beforeOutput).toContain('foundTestPage')
505
- console.log('Before disconnect:', beforeOutput)
506
-
507
- // 2. Disconnect everything
508
- console.log('Calling disconnectEverything...')
509
- await serviceWorker.evaluate(async () => {
510
- await globalThis.disconnectEverything()
511
- })
512
-
513
- await new Promise((resolve) => setTimeout(resolve, 100))
514
-
515
- // 3. The disconnected page must disappear. Depending on auto-enable and
516
- // extension generation, the relay may expose a fresh blank target or no page.
517
- const afterDisconnect = await client.callTool({
518
- name: 'execute',
519
- arguments: {
520
- code: js`
521
- const pages = context.pages();
522
- console.log('Pages after disconnect:', pages.length);
523
- const disconnectedPage = pages.find(p => p.url().includes('disconnect-test'));
524
- return { pagesCount: pages.length, foundDisconnectedPage: !!disconnectedPage };
525
- `,
526
- },
527
- })
528
-
529
- const afterDisconnectOutput = (afterDisconnect as any).content[0].text
530
- console.log('After disconnect:', afterDisconnectOutput)
531
- if ((afterDisconnect as any).isError === true) {
532
- expect(afterDisconnectOutput).toContain('No Playwright pages are available')
533
- } else {
534
- expect(afterDisconnectOutput).toContain('foundDisconnectedPage: false')
535
- }
536
-
537
- // 4. Re-enable extension on the same page
538
- console.log('Re-enabling extension...')
539
- await page.bringToFront()
540
- const reconnectResult = await serviceWorker.evaluate(async () => {
541
- console.log('About to call toggleExtensionForActiveTab')
542
- const result = await globalThis.toggleExtensionForActiveTab()
543
- console.log('toggleExtensionForActiveTab result:', result)
544
- return result
545
- })
546
-
547
- console.log('Reconnect result:', reconnectResult)
548
- expect(reconnectResult.isConnected).toBe(true)
549
-
550
- console.log('Waiting for reconnection to stabilize...')
551
- await new Promise((resolve) => setTimeout(resolve, 100))
552
-
553
- // 5. Reset the MCP client's playwright connection
554
- console.log('Resetting MCP playwright connection...')
555
- const resetResult = await client.callTool({
556
- name: 'reset',
557
- arguments: {},
558
- })
559
- console.log('Reset result:', (resetResult as any).content[0].text)
560
- expect((resetResult as any).content[0].text).toContain('Connection reset successfully')
561
-
562
- // 6. Verify MCP can see the page again
563
- console.log('Attempting to access page via MCP...')
564
- const afterReconnect = await client.callTool({
565
- name: 'execute',
566
- arguments: {
567
- code: js`
568
- console.log('Checking pages after reconnect...');
569
- const pages = context.pages();
570
- console.log('Pages after reconnect:', pages.length);
571
-
572
- if (pages.length === 0) {
573
- console.log('No pages found!');
574
- return { pagesCount: 0, foundTestPage: false };
575
- }
576
-
577
- const testPage = pages.find(p => p.url().includes('disconnect-test'));
578
- console.log('Found test page after reconnect:', !!testPage);
579
-
580
- if (testPage) {
581
- console.log('Test page URL:', testPage.url());
582
- return { pagesCount: pages.length, foundTestPage: true, url: testPage.url() };
583
- }
584
-
585
- return { pagesCount: pages.length, foundTestPage: false };
586
- `,
587
- },
588
- })
589
-
590
- const afterReconnectOutput = (afterReconnect as any).content[0].text
591
- console.log('After reconnect:', afterReconnectOutput)
592
- expect(afterReconnectOutput).toContain('foundTestPage')
593
- expect(afterReconnectOutput).toContain('disconnect-test')
594
-
595
- // Clean up
596
- await page.goto('about:blank')
597
- })
598
-
599
- it('should auto-reconnect MCP after extension WebSocket reconnects', async () => {
600
- const serviceWorker = await getExtensionServiceWorker(testCtx!.browserContext)
601
-
602
- // 1. Create a test page and enable extension
603
- const page = await testCtx!.browserContext.newPage()
604
- await page.goto('https://example.com/auto-reconnect-test')
605
- await page.waitForLoadState('domcontentloaded')
606
- await page.bringToFront()
607
-
608
- const initialEnable = await serviceWorker.evaluate(async () => {
609
- return await globalThis.toggleExtensionForActiveTab()
610
- })
611
- expect(initialEnable.isConnected).toBe(true)
612
- await new Promise((resolve) => setTimeout(resolve, 100))
613
-
614
- // 2. Verify MCP can execute commands
615
- const beforeResult = await client.callTool({
616
- name: 'execute',
617
- arguments: {
618
- code: js`
619
- let testPage;
620
- for (let i = 0; i < 20; i++) {
621
- const pages = context.pages();
622
- testPage = pages.find(p => p.url().includes('auto-reconnect-test'));
623
- if (testPage) break;
624
- await new Promise((r) => { setTimeout(r, 100) });
625
- }
626
- const pages = context.pages();
627
- return { pagesCount: pages.length, foundTestPage: !!testPage, url: testPage?.url() };
628
- `,
629
- },
630
- })
631
- const beforeOutput = (beforeResult as any).content[0].text
632
- expect(beforeOutput).toContain('foundTestPage')
633
- expect(beforeOutput).toContain('true')
634
- expect(beforeOutput).toContain('auto-reconnect-test')
635
-
636
- // 3. Simulate extension WebSocket reconnection
637
- await serviceWorker.evaluate(async () => {
638
- await globalThis.disconnectEverything()
639
- })
640
- await new Promise((resolve) => setTimeout(resolve, 100))
641
-
642
- // Re-enable extension
643
- await page.bringToFront()
644
- const reconnectResult = await serviceWorker.evaluate(async () => {
645
- return await globalThis.toggleExtensionForActiveTab()
646
- })
647
- expect(reconnectResult.isConnected).toBe(true)
648
- await new Promise((resolve) => setTimeout(resolve, 100))
649
-
650
- // 4. Execute command WITHOUT calling resetPlaywright()
651
- const afterResult = await client.callTool({
652
- name: 'execute',
653
- arguments: {
654
- code: js`
655
- let testPage;
656
- for (let i = 0; i < 20; i++) {
657
- const pages = context.pages();
658
- testPage = pages.find(p => p.url().includes('auto-reconnect-test'));
659
- if (testPage) break;
660
- await new Promise((r) => { setTimeout(r, 100) });
661
- }
662
- const pages = context.pages();
663
- return { pagesCount: pages.length, foundTestPage: !!testPage, url: testPage?.url() };
664
- `,
665
- },
666
- })
667
-
668
- const afterOutput = (afterResult as any).content[0].text
669
- expect(afterOutput).toContain('foundTestPage')
670
- expect(afterOutput).toContain('true')
671
- expect(afterOutput).toContain('auto-reconnect-test')
672
- expect(afterOutput).not.toContain('Extension not connected')
673
- expect((afterResult as any).isError).not.toBe(true)
674
-
675
- // Clean up
676
- await page.goto('about:blank')
677
- })
678
-
679
- it('should keep an active browser connected when another Chromium context starts', async () => {
680
- const browserContext = getBrowserContext()
681
- const serviceWorker = await getExtensionServiceWorker(browserContext)
682
-
683
- await serviceWorker.evaluate(async () => {
684
- await globalThis.disconnectEverything()
685
- })
686
-
687
- const page = await browserContext.newPage()
688
- const targetUrl = 'https://example.com/multi-context-stability'
689
- await page.goto(targetUrl)
690
- await page.waitForLoadState('domcontentloaded')
691
- await page.bringToFront()
692
-
693
- const enableResult = await serviceWorker.evaluate(async () => {
694
- return await globalThis.toggleExtensionForActiveTab()
695
- })
696
- expect(enableResult.isConnected).toBe(true)
697
-
698
- const secondUserDataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pw-conn-second-'))
699
- const extensionPath = path.resolve(process.cwd(), '../extension', `dist-${TEST_PORT}`)
700
- const secondContext = await launchPersistentContextWithExtensions({
701
- userDataDir: secondUserDataDir,
702
- extensionPaths: [extensionPath],
703
- })
704
-
705
- try {
706
- await getExtensionServiceWorker(secondContext)
707
-
708
- const statusSnapshots: Array<{ keys: string[]; activeTargets: number[] }> = []
709
- for (let i = 0; i < 4; i++) {
710
- await new Promise((resolve) => {
711
- setTimeout(resolve, 1000)
712
- })
713
- const statuses = await getExtensionsStatus(TEST_PORT)
714
- statusSnapshots.push({
715
- keys: statuses.map((status) => {
716
- return status.stableKey || status.extensionId
717
- }),
718
- activeTargets: statuses.map((status) => {
719
- return status.activeTargets
720
- }),
721
- })
722
- }
723
-
724
- expect(statusSnapshots.every((snapshot) => {
725
- return snapshot.keys.length >= 2
726
- })).toBe(true)
727
- expect(statusSnapshots.every((snapshot) => {
728
- return new Set(snapshot.keys).size === snapshot.keys.length
729
- })).toBe(true)
730
- expect(statusSnapshots.every((snapshot) => {
731
- return snapshot.activeTargets.some((count) => count > 0)
732
- })).toBe(true)
733
-
734
- const executeResult = await client.callTool({
735
- name: 'execute',
736
- arguments: {
737
- code: js`
738
- const pages = context.pages();
739
- const testPage = pages.find((p) => p.url().includes('multi-context-stability'));
740
- return { pagesCount: pages.length, found: !!testPage, url: testPage?.url() };
741
- `,
742
- },
743
- })
744
-
745
- const executeOutput = (executeResult as any).content[0].text
746
- expect(executeOutput).toContain('found: true')
747
- expect(executeOutput).toContain(targetUrl)
748
- expect((executeResult as any).isError).not.toBe(true)
749
- } finally {
750
- await secondContext.close()
751
- fs.rmSync(secondUserDataDir, { recursive: true, force: true })
752
- if (!page.isClosed()) {
753
- await page.close()
754
- }
755
- await serviceWorker.evaluate(async () => {
756
- await globalThis.disconnectEverything()
757
- })
758
- }
759
- }, 120000)
760
-
761
- it('should maintain correct page.url() with service worker pages', async () => {
762
- const browserContext = getBrowserContext()
763
- const serviceWorker = await getExtensionServiceWorker(browserContext)
764
-
765
- const page = await browserContext.newPage()
766
- const targetUrl = 'https://example.com/sw-test'
767
- await page.goto(targetUrl)
768
- await page.bringToFront()
769
-
770
- await serviceWorker.evaluate(async () => {
771
- await globalThis.toggleExtensionForActiveTab()
772
- })
773
-
774
- await new Promise((r) => setTimeout(r, 100))
775
-
776
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
777
- const cdpPages = browser.contexts()[0].pages()
778
- const testPage = cdpPages.find((p) => p.url().includes('sw-test'))
779
-
780
- expect(testPage).toBeDefined()
781
- expect(testPage?.url()).toContain('sw-test')
782
- expect(testPage?.url()).not.toContain('sw.js')
783
-
784
- await browser.close()
785
- await page.close()
786
- }, 30000)
787
-
788
- it('should maintain correct page.url() after repeated connections', async () => {
789
- const browserContext = getBrowserContext()
790
- const serviceWorker = await getExtensionServiceWorker(browserContext)
791
-
792
- const page = await browserContext.newPage()
793
- const targetUrl = 'https://example.com/repeated-test'
794
- await page.goto(targetUrl)
795
- await page.bringToFront()
796
-
797
- await serviceWorker.evaluate(async () => {
798
- await globalThis.toggleExtensionForActiveTab()
799
- })
800
-
801
- for (let i = 0; i < 5; i++) {
802
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }))
803
- const cdpPages = browser.contexts()[0].pages()
804
- const testPage = cdpPages.find((p) => p.url().includes('repeated-test'))
805
-
806
- expect(testPage).toBeDefined()
807
- expect(testPage?.url()).toBe(targetUrl)
808
-
809
- await browser.close()
810
- await new Promise((r) => setTimeout(r, 100))
811
- }
812
-
813
- await page.close()
814
- }, 30000)
815
-
816
- it('should maintain correct page.url() with concurrent MCP and CDP connections', async () => {
817
- const browserContext = getBrowserContext()
818
- const serviceWorker = await getExtensionServiceWorker(browserContext)
819
-
820
- const page = await browserContext.newPage()
821
- const targetUrl = 'https://example.com/concurrent-test'
822
- await page.goto(targetUrl)
823
- await page.bringToFront()
824
-
825
- await serviceWorker.evaluate(async () => {
826
- await globalThis.toggleExtensionForActiveTab()
827
- })
828
-
829
- await new Promise((r) => setTimeout(r, 400))
830
-
831
- const [mcpResult, cdpBrowser] = await Promise.all([
832
- client.callTool({
833
- name: 'execute',
834
- arguments: {
835
- code: js`
836
- const pages = context.pages();
837
- const testPage = pages.find(p => p.url().includes('concurrent-test'));
838
- return { url: testPage?.url(), found: !!testPage };
839
- `,
840
- },
841
- }),
842
- chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT })),
843
- ])
844
-
845
- const mcpOutput = (mcpResult as any).content[0].text
846
- expect(mcpOutput).toContain(targetUrl)
847
-
848
- const cdpPages = cdpBrowser.contexts()[0].pages()
849
- const cdpPage = cdpPages.find((p) => p.url().includes('concurrent-test'))
850
- expect(cdpPage?.url()).toBe(targetUrl)
851
-
852
- await cdpBrowser.close()
853
- await page.close()
854
- }, 30000)
855
- })