tabwright 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/dist/agent-skills/tabwright/SKILL.md +3 -0
  2. package/dist/aria-snapshot.d.ts +0 -1
  3. package/dist/aria-snapshot.js +9 -1
  4. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +0 -1
  5. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +0 -1
  6. package/dist/bippy.js +5 -5
  7. package/dist/browser-config.d.ts +0 -1
  8. package/dist/browser-config.js +0 -1
  9. package/dist/browser-install.d.ts +0 -1
  10. package/dist/browser-install.js +0 -1
  11. package/dist/browser-launch.d.ts +0 -1
  12. package/dist/browser-launch.js +0 -1
  13. package/dist/capability-agent-skill.d.ts +0 -1
  14. package/dist/capability-agent-skill.js +0 -1
  15. package/dist/capability-auth-state.d.ts +0 -1
  16. package/dist/capability-auth-state.js +0 -1
  17. package/dist/capability-auth.d.ts +0 -1
  18. package/dist/capability-auth.js +0 -1
  19. package/dist/capability-options.d.ts +0 -1
  20. package/dist/capability-options.js +0 -1
  21. package/dist/capability-package.d.ts +0 -1
  22. package/dist/capability-package.js +47 -2
  23. package/dist/capability-registry.d.ts +0 -1
  24. package/dist/capability-registry.js +0 -1
  25. package/dist/capability-runner.d.ts +0 -1
  26. package/dist/capability-runner.js +0 -1
  27. package/dist/capability-studio.d.ts +0 -1
  28. package/dist/capability-studio.js +0 -1
  29. package/dist/cdp-log.d.ts +0 -1
  30. package/dist/cdp-log.js +0 -1
  31. package/dist/cdp-relay.d.ts +0 -1
  32. package/dist/cdp-relay.js +0 -1
  33. package/dist/cdp-session.d.ts +0 -1
  34. package/dist/cdp-session.js +0 -1
  35. package/dist/cdp-types.d.ts +0 -1
  36. package/dist/cdp-types.js +0 -1
  37. package/dist/chrome-discovery.d.ts +0 -1
  38. package/dist/chrome-discovery.js +0 -1
  39. package/dist/clean-html.d.ts +0 -1
  40. package/dist/clean-html.js +0 -1
  41. package/dist/cli.d.ts +0 -1
  42. package/dist/cli.js +10 -56
  43. package/dist/cloud-client.d.ts +0 -1
  44. package/dist/cloud-client.js +0 -1
  45. package/dist/create-logger.d.ts +0 -1
  46. package/dist/create-logger.js +0 -1
  47. package/dist/debugger-examples-types.d.ts +0 -1
  48. package/dist/debugger-examples-types.js +0 -1
  49. package/dist/debugger-examples.d.ts +0 -1
  50. package/dist/debugger-examples.js +0 -1
  51. package/dist/debugger.d.ts +0 -1
  52. package/dist/debugger.js +0 -1
  53. package/dist/diff-utils.d.ts +0 -1
  54. package/dist/diff-utils.js +0 -1
  55. package/dist/doctor.d.ts +0 -1
  56. package/dist/doctor.js +5 -7
  57. package/dist/editor-examples.d.ts +0 -1
  58. package/dist/editor-examples.js +0 -1
  59. package/dist/editor.d.ts +0 -1
  60. package/dist/editor.js +0 -1
  61. package/dist/env-compat.d.ts +0 -1
  62. package/dist/env-compat.js +0 -1
  63. package/dist/executor.d.ts +0 -1
  64. package/dist/executor.js +1 -2
  65. package/dist/extension/background.js +10 -6
  66. package/dist/extension/manifest.json +1 -1
  67. package/dist/extension/options.js +1 -1
  68. package/dist/extension/rrweb-recorder.js +1 -1
  69. package/dist/ghost-browser.d.ts +0 -1
  70. package/dist/ghost-browser.js +0 -1
  71. package/dist/ghost-cursor-controller.d.ts +0 -1
  72. package/dist/ghost-cursor-controller.js +0 -1
  73. package/dist/ghost-cursor.d.ts +0 -1
  74. package/dist/ghost-cursor.js +0 -1
  75. package/dist/htmlrewrite.d.ts +0 -1
  76. package/dist/htmlrewrite.js +0 -1
  77. package/dist/index.d.ts +0 -1
  78. package/dist/index.js +0 -1
  79. package/dist/kill-port.d.ts +0 -1
  80. package/dist/kill-port.js +0 -1
  81. package/dist/kitty-graphics.d.ts +0 -1
  82. package/dist/kitty-graphics.js +0 -1
  83. package/dist/mcp.d.ts +0 -1
  84. package/dist/mcp.js +0 -1
  85. package/dist/package-paths.d.ts +0 -1
  86. package/dist/package-paths.js +0 -1
  87. package/dist/page-markdown.d.ts +0 -1
  88. package/dist/page-markdown.js +0 -1
  89. package/dist/performance-examples.d.ts +0 -1
  90. package/dist/performance-examples.js +0 -1
  91. package/dist/playwright-import.d.ts +0 -1
  92. package/dist/playwright-import.js +0 -1
  93. package/dist/product-paths.d.ts +0 -1
  94. package/dist/product-paths.js +0 -1
  95. package/dist/protocol.d.ts +0 -1
  96. package/dist/protocol.js +0 -1
  97. package/dist/react-source.d.ts +0 -1
  98. package/dist/react-source.js +0 -1
  99. package/dist/readability.js +4 -4
  100. package/dist/relay-client.d.ts +0 -1
  101. package/dist/relay-client.js +0 -1
  102. package/dist/relay-state.d.ts +0 -1
  103. package/dist/relay-state.js +0 -1
  104. package/dist/replay-ai-index.d.ts +0 -1
  105. package/dist/replay-ai-index.js +0 -1
  106. package/dist/replay-eval.d.ts +0 -1
  107. package/dist/replay-eval.js +0 -1
  108. package/dist/replay-handoff.d.ts +0 -1
  109. package/dist/replay-handoff.js +0 -1
  110. package/dist/replay-workflow-compiler.d.ts +0 -1
  111. package/dist/replay-workflow-compiler.js +0 -1
  112. package/dist/rrweb-recording-relay.d.ts +0 -1
  113. package/dist/rrweb-recording-relay.js +0 -1
  114. package/dist/rrweb-recording.d.ts +0 -1
  115. package/dist/rrweb-recording.js +0 -1
  116. package/dist/scoped-fs.d.ts +0 -1
  117. package/dist/scoped-fs.js +0 -1
  118. package/dist/selector-generator.js +2 -2
  119. package/dist/start-relay-server.d.ts +0 -1
  120. package/dist/start-relay-server.js +0 -1
  121. package/dist/styles-examples.d.ts +0 -1
  122. package/dist/styles-examples.js +0 -1
  123. package/dist/styles.d.ts +0 -1
  124. package/dist/styles.js +0 -1
  125. package/dist/tabwright-agent-skill.d.ts +0 -1
  126. package/dist/tabwright-agent-skill.js +0 -1
  127. package/dist/test-declarations.d.ts +0 -1
  128. package/dist/test-declarations.js +0 -1
  129. package/dist/utils.d.ts +0 -1
  130. package/dist/utils.js +2 -2
  131. package/dist/wait-for-page-load.d.ts +0 -1
  132. package/dist/wait-for-page-load.js +0 -1
  133. package/dist/workflow-capability.d.ts +0 -1
  134. package/dist/workflow-capability.js +0 -1
  135. package/package.json +8 -4
  136. package/readme.md +43 -0
  137. package/src/skill.md +5 -2
  138. package/dist/aria-snapshot.d.ts.map +0 -1
  139. package/dist/aria-snapshot.js.map +0 -1
  140. package/dist/aria-snapshot.test.d.ts +0 -2
  141. package/dist/aria-snapshot.test.d.ts.map +0 -1
  142. package/dist/aria-snapshot.test.js +0 -270
  143. package/dist/aria-snapshot.test.js.map +0 -1
  144. package/dist/aria-snapshot.unit.test.d.ts +0 -2
  145. package/dist/aria-snapshot.unit.test.d.ts.map +0 -1
  146. package/dist/aria-snapshot.unit.test.js +0 -542
  147. package/dist/aria-snapshot.unit.test.js.map +0 -1
  148. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +0 -1
  149. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +0 -1
  150. package/dist/browser-config.d.ts.map +0 -1
  151. package/dist/browser-config.js.map +0 -1
  152. package/dist/browser-install.d.ts.map +0 -1
  153. package/dist/browser-install.js.map +0 -1
  154. package/dist/browser-launch.d.ts.map +0 -1
  155. package/dist/browser-launch.js.map +0 -1
  156. package/dist/builtin-capabilities.d.ts +0 -28
  157. package/dist/builtin-capabilities.d.ts.map +0 -1
  158. package/dist/builtin-capabilities.js +0 -2673
  159. package/dist/builtin-capabilities.js.map +0 -1
  160. package/dist/capability-agent-skill.d.ts.map +0 -1
  161. package/dist/capability-agent-skill.js.map +0 -1
  162. package/dist/capability-auth-state.d.ts.map +0 -1
  163. package/dist/capability-auth-state.js.map +0 -1
  164. package/dist/capability-auth.d.ts.map +0 -1
  165. package/dist/capability-auth.js.map +0 -1
  166. package/dist/capability-cli-confirmation.test.d.ts +0 -2
  167. package/dist/capability-cli-confirmation.test.d.ts.map +0 -1
  168. package/dist/capability-cli-confirmation.test.js +0 -79
  169. package/dist/capability-cli-confirmation.test.js.map +0 -1
  170. package/dist/capability-options.d.ts.map +0 -1
  171. package/dist/capability-options.js.map +0 -1
  172. package/dist/capability-options.test.d.ts +0 -2
  173. package/dist/capability-options.test.d.ts.map +0 -1
  174. package/dist/capability-options.test.js +0 -81
  175. package/dist/capability-options.test.js.map +0 -1
  176. package/dist/capability-package.d.ts.map +0 -1
  177. package/dist/capability-package.js.map +0 -1
  178. package/dist/capability-package.test.d.ts +0 -2
  179. package/dist/capability-package.test.d.ts.map +0 -1
  180. package/dist/capability-package.test.js +0 -179
  181. package/dist/capability-package.test.js.map +0 -1
  182. package/dist/capability-registry.d.ts.map +0 -1
  183. package/dist/capability-registry.js.map +0 -1
  184. package/dist/capability-registry.test.d.ts +0 -2
  185. package/dist/capability-registry.test.d.ts.map +0 -1
  186. package/dist/capability-registry.test.js +0 -1683
  187. package/dist/capability-registry.test.js.map +0 -1
  188. package/dist/capability-runner.d.ts.map +0 -1
  189. package/dist/capability-runner.js.map +0 -1
  190. package/dist/capability-search-relevance.test.d.ts +0 -2
  191. package/dist/capability-search-relevance.test.d.ts.map +0 -1
  192. package/dist/capability-search-relevance.test.js +0 -67
  193. package/dist/capability-search-relevance.test.js.map +0 -1
  194. package/dist/capability-studio.d.ts.map +0 -1
  195. package/dist/capability-studio.js.map +0 -1
  196. package/dist/capability-studio.test.d.ts +0 -2
  197. package/dist/capability-studio.test.d.ts.map +0 -1
  198. package/dist/capability-studio.test.js +0 -41
  199. package/dist/capability-studio.test.js.map +0 -1
  200. package/dist/cdp-log.d.ts.map +0 -1
  201. package/dist/cdp-log.js.map +0 -1
  202. package/dist/cdp-log.test.d.ts +0 -2
  203. package/dist/cdp-log.test.d.ts.map +0 -1
  204. package/dist/cdp-log.test.js +0 -109
  205. package/dist/cdp-log.test.js.map +0 -1
  206. package/dist/cdp-relay.d.ts.map +0 -1
  207. package/dist/cdp-relay.js.map +0 -1
  208. package/dist/cdp-session.d.ts.map +0 -1
  209. package/dist/cdp-session.js.map +0 -1
  210. package/dist/cdp-types.d.ts.map +0 -1
  211. package/dist/cdp-types.js.map +0 -1
  212. package/dist/channel-owner-inspect.test.d.ts +0 -2
  213. package/dist/channel-owner-inspect.test.d.ts.map +0 -1
  214. package/dist/channel-owner-inspect.test.js +0 -75
  215. package/dist/channel-owner-inspect.test.js.map +0 -1
  216. package/dist/chrome-discovery.d.ts.map +0 -1
  217. package/dist/chrome-discovery.js.map +0 -1
  218. package/dist/chrome-discovery.test.d.ts +0 -2
  219. package/dist/chrome-discovery.test.d.ts.map +0 -1
  220. package/dist/chrome-discovery.test.js +0 -41
  221. package/dist/chrome-discovery.test.js.map +0 -1
  222. package/dist/clean-html.d.ts.map +0 -1
  223. package/dist/clean-html.js.map +0 -1
  224. package/dist/cli-help.test.d.ts +0 -2
  225. package/dist/cli-help.test.d.ts.map +0 -1
  226. package/dist/cli-help.test.js +0 -98
  227. package/dist/cli-help.test.js.map +0 -1
  228. package/dist/cli.d.ts.map +0 -1
  229. package/dist/cli.js.map +0 -1
  230. package/dist/cloud-client.d.ts.map +0 -1
  231. package/dist/cloud-client.js.map +0 -1
  232. package/dist/create-logger.d.ts.map +0 -1
  233. package/dist/create-logger.js.map +0 -1
  234. package/dist/debugger-examples-types.d.ts.map +0 -1
  235. package/dist/debugger-examples-types.js.map +0 -1
  236. package/dist/debugger-examples.d.ts.map +0 -1
  237. package/dist/debugger-examples.js.map +0 -1
  238. package/dist/debugger.d.ts.map +0 -1
  239. package/dist/debugger.js.map +0 -1
  240. package/dist/diff-utils.d.ts.map +0 -1
  241. package/dist/diff-utils.js.map +0 -1
  242. package/dist/diff-utils.test.d.ts +0 -2
  243. package/dist/diff-utils.test.d.ts.map +0 -1
  244. package/dist/diff-utils.test.js +0 -137
  245. package/dist/diff-utils.test.js.map +0 -1
  246. package/dist/doctor.d.ts.map +0 -1
  247. package/dist/doctor.js.map +0 -1
  248. package/dist/doctor.test.d.ts +0 -2
  249. package/dist/doctor.test.d.ts.map +0 -1
  250. package/dist/doctor.test.js +0 -208
  251. package/dist/doctor.test.js.map +0 -1
  252. package/dist/editor-examples.d.ts.map +0 -1
  253. package/dist/editor-examples.js.map +0 -1
  254. package/dist/editor.d.ts.map +0 -1
  255. package/dist/editor.js.map +0 -1
  256. package/dist/env-compat.d.ts.map +0 -1
  257. package/dist/env-compat.js.map +0 -1
  258. package/dist/executor.d.ts.map +0 -1
  259. package/dist/executor.js.map +0 -1
  260. package/dist/executor.unit.test.d.ts +0 -2
  261. package/dist/executor.unit.test.d.ts.map +0 -1
  262. package/dist/executor.unit.test.js +0 -143
  263. package/dist/executor.unit.test.js.map +0 -1
  264. package/dist/extension-connection.test.d.ts +0 -2
  265. package/dist/extension-connection.test.d.ts.map +0 -1
  266. package/dist/extension-connection.test.js +0 -708
  267. package/dist/extension-connection.test.js.map +0 -1
  268. package/dist/extension-icon-warning.test.d.ts +0 -2
  269. package/dist/extension-icon-warning.test.d.ts.map +0 -1
  270. package/dist/extension-icon-warning.test.js +0 -33
  271. package/dist/extension-icon-warning.test.js.map +0 -1
  272. package/dist/ghost-browser.d.ts.map +0 -1
  273. package/dist/ghost-browser.js.map +0 -1
  274. package/dist/ghost-cursor-controller.d.ts.map +0 -1
  275. package/dist/ghost-cursor-controller.js.map +0 -1
  276. package/dist/ghost-cursor.d.ts.map +0 -1
  277. package/dist/ghost-cursor.js.map +0 -1
  278. package/dist/htmlrewrite.d.ts.map +0 -1
  279. package/dist/htmlrewrite.js.map +0 -1
  280. package/dist/htmlrewrite.test.d.ts +0 -2
  281. package/dist/htmlrewrite.test.d.ts.map +0 -1
  282. package/dist/htmlrewrite.test.js +0 -7975
  283. package/dist/htmlrewrite.test.js.map +0 -1
  284. package/dist/index.d.ts.map +0 -1
  285. package/dist/index.js.map +0 -1
  286. package/dist/kill-port.d.ts.map +0 -1
  287. package/dist/kill-port.js.map +0 -1
  288. package/dist/kitty-graphics.d.ts.map +0 -1
  289. package/dist/kitty-graphics.js.map +0 -1
  290. package/dist/kitty-graphics.test.d.ts +0 -2
  291. package/dist/kitty-graphics.test.d.ts.map +0 -1
  292. package/dist/kitty-graphics.test.js +0 -125
  293. package/dist/kitty-graphics.test.js.map +0 -1
  294. package/dist/locator-selector.test.d.ts +0 -2
  295. package/dist/locator-selector.test.d.ts.map +0 -1
  296. package/dist/locator-selector.test.js +0 -98
  297. package/dist/locator-selector.test.js.map +0 -1
  298. package/dist/mcp-client.d.ts +0 -20
  299. package/dist/mcp-client.d.ts.map +0 -1
  300. package/dist/mcp-client.js +0 -56
  301. package/dist/mcp-client.js.map +0 -1
  302. package/dist/mcp.d.ts.map +0 -1
  303. package/dist/mcp.js.map +0 -1
  304. package/dist/on-mouse-action.test.d.ts +0 -2
  305. package/dist/on-mouse-action.test.d.ts.map +0 -1
  306. package/dist/on-mouse-action.test.js +0 -180
  307. package/dist/on-mouse-action.test.js.map +0 -1
  308. package/dist/options-page.test.d.ts +0 -2
  309. package/dist/options-page.test.d.ts.map +0 -1
  310. package/dist/options-page.test.js +0 -773
  311. package/dist/options-page.test.js.map +0 -1
  312. package/dist/package-paths.d.ts.map +0 -1
  313. package/dist/package-paths.js.map +0 -1
  314. package/dist/page-markdown.d.ts.map +0 -1
  315. package/dist/page-markdown.js.map +0 -1
  316. package/dist/performance-examples.d.ts.map +0 -1
  317. package/dist/performance-examples.js.map +0 -1
  318. package/dist/playwright-import.d.ts.map +0 -1
  319. package/dist/playwright-import.js.map +0 -1
  320. package/dist/popup-relocation.test.d.ts +0 -7
  321. package/dist/popup-relocation.test.d.ts.map +0 -1
  322. package/dist/popup-relocation.test.js +0 -139
  323. package/dist/popup-relocation.test.js.map +0 -1
  324. package/dist/product-paths.d.ts.map +0 -1
  325. package/dist/product-paths.js.map +0 -1
  326. package/dist/product-paths.test.d.ts +0 -2
  327. package/dist/product-paths.test.d.ts.map +0 -1
  328. package/dist/product-paths.test.js +0 -39
  329. package/dist/product-paths.test.js.map +0 -1
  330. package/dist/protocol.d.ts.map +0 -1
  331. package/dist/protocol.js.map +0 -1
  332. package/dist/protocol.test.d.ts +0 -2
  333. package/dist/protocol.test.d.ts.map +0 -1
  334. package/dist/protocol.test.js +0 -31
  335. package/dist/protocol.test.js.map +0 -1
  336. package/dist/react-source.d.ts.map +0 -1
  337. package/dist/react-source.js.map +0 -1
  338. package/dist/relay-client.d.ts.map +0 -1
  339. package/dist/relay-client.js.map +0 -1
  340. package/dist/relay-client.test.d.ts +0 -2
  341. package/dist/relay-client.test.d.ts.map +0 -1
  342. package/dist/relay-client.test.js +0 -305
  343. package/dist/relay-client.test.js.map +0 -1
  344. package/dist/relay-core.test.d.ts +0 -2
  345. package/dist/relay-core.test.d.ts.map +0 -1
  346. package/dist/relay-core.test.js +0 -1427
  347. package/dist/relay-core.test.js.map +0 -1
  348. package/dist/relay-navigation.test.d.ts +0 -2
  349. package/dist/relay-navigation.test.d.ts.map +0 -1
  350. package/dist/relay-navigation.test.js +0 -661
  351. package/dist/relay-navigation.test.js.map +0 -1
  352. package/dist/relay-session.test.d.ts +0 -2
  353. package/dist/relay-session.test.d.ts.map +0 -1
  354. package/dist/relay-session.test.js +0 -1121
  355. package/dist/relay-session.test.js.map +0 -1
  356. package/dist/relay-state.d.ts.map +0 -1
  357. package/dist/relay-state.js.map +0 -1
  358. package/dist/relay-state.test.d.ts +0 -2
  359. package/dist/relay-state.test.d.ts.map +0 -1
  360. package/dist/relay-state.test.js +0 -594
  361. package/dist/relay-state.test.js.map +0 -1
  362. package/dist/replay-ai-index.d.ts.map +0 -1
  363. package/dist/replay-ai-index.js.map +0 -1
  364. package/dist/replay-ai-index.test.d.ts +0 -2
  365. package/dist/replay-ai-index.test.d.ts.map +0 -1
  366. package/dist/replay-ai-index.test.js +0 -255
  367. package/dist/replay-ai-index.test.js.map +0 -1
  368. package/dist/replay-cli.test.d.ts +0 -2
  369. package/dist/replay-cli.test.d.ts.map +0 -1
  370. package/dist/replay-cli.test.js +0 -275
  371. package/dist/replay-cli.test.js.map +0 -1
  372. package/dist/replay-eval.d.ts.map +0 -1
  373. package/dist/replay-eval.js.map +0 -1
  374. package/dist/replay-handoff.d.ts.map +0 -1
  375. package/dist/replay-handoff.js.map +0 -1
  376. package/dist/replay-handoff.test.d.ts +0 -2
  377. package/dist/replay-handoff.test.d.ts.map +0 -1
  378. package/dist/replay-handoff.test.js +0 -123
  379. package/dist/replay-handoff.test.js.map +0 -1
  380. package/dist/replay-workflow-compiler.d.ts.map +0 -1
  381. package/dist/replay-workflow-compiler.js.map +0 -1
  382. package/dist/replay-workflow-compiler.test.d.ts +0 -2
  383. package/dist/replay-workflow-compiler.test.d.ts.map +0 -1
  384. package/dist/replay-workflow-compiler.test.js +0 -223
  385. package/dist/replay-workflow-compiler.test.js.map +0 -1
  386. package/dist/rrweb-recording-relay.d.ts.map +0 -1
  387. package/dist/rrweb-recording-relay.js.map +0 -1
  388. package/dist/rrweb-recording-relay.test.d.ts +0 -2
  389. package/dist/rrweb-recording-relay.test.d.ts.map +0 -1
  390. package/dist/rrweb-recording-relay.test.js +0 -85
  391. package/dist/rrweb-recording-relay.test.js.map +0 -1
  392. package/dist/rrweb-recording.d.ts.map +0 -1
  393. package/dist/rrweb-recording.js.map +0 -1
  394. package/dist/scoped-fs.d.ts.map +0 -1
  395. package/dist/scoped-fs.js.map +0 -1
  396. package/dist/scoped-fs.test.d.ts +0 -5
  397. package/dist/scoped-fs.test.d.ts.map +0 -1
  398. package/dist/scoped-fs.test.js +0 -73
  399. package/dist/scoped-fs.test.js.map +0 -1
  400. package/dist/skill-stub.test.d.ts +0 -2
  401. package/dist/skill-stub.test.d.ts.map +0 -1
  402. package/dist/skill-stub.test.js +0 -22
  403. package/dist/skill-stub.test.js.map +0 -1
  404. package/dist/snapshot-tools.test.d.ts +0 -2
  405. package/dist/snapshot-tools.test.d.ts.map +0 -1
  406. package/dist/snapshot-tools.test.js +0 -856
  407. package/dist/snapshot-tools.test.js.map +0 -1
  408. package/dist/start-relay-server.d.ts.map +0 -1
  409. package/dist/start-relay-server.js.map +0 -1
  410. package/dist/styles-examples.d.ts.map +0 -1
  411. package/dist/styles-examples.js.map +0 -1
  412. package/dist/styles.d.ts.map +0 -1
  413. package/dist/styles.js.map +0 -1
  414. package/dist/tabwright-agent-skill.d.ts.map +0 -1
  415. package/dist/tabwright-agent-skill.js.map +0 -1
  416. package/dist/tabwright-agent-skill.test.d.ts +0 -2
  417. package/dist/tabwright-agent-skill.test.d.ts.map +0 -1
  418. package/dist/tabwright-agent-skill.test.js +0 -51
  419. package/dist/tabwright-agent-skill.test.js.map +0 -1
  420. package/dist/test-declarations.d.ts.map +0 -1
  421. package/dist/test-declarations.js.map +0 -1
  422. package/dist/test-utils.d.ts +0 -69
  423. package/dist/test-utils.d.ts.map +0 -1
  424. package/dist/test-utils.js +0 -448
  425. package/dist/test-utils.js.map +0 -1
  426. package/dist/test-utils.test.d.ts +0 -2
  427. package/dist/test-utils.test.d.ts.map +0 -1
  428. package/dist/test-utils.test.js +0 -55
  429. package/dist/test-utils.test.js.map +0 -1
  430. package/dist/utils.d.ts.map +0 -1
  431. package/dist/utils.js.map +0 -1
  432. package/dist/wait-for-page-load.d.ts.map +0 -1
  433. package/dist/wait-for-page-load.js.map +0 -1
  434. package/dist/workflow-capability.d.ts.map +0 -1
  435. package/dist/workflow-capability.js.map +0 -1
  436. package/dist/workflow-script-flow.test.d.ts +0 -2
  437. package/dist/workflow-script-flow.test.d.ts.map +0 -1
  438. package/dist/workflow-script-flow.test.js +0 -285
  439. package/dist/workflow-script-flow.test.js.map +0 -1
  440. package/src/__snapshots__/x.com.processed.html +0 -1003
  441. package/src/__snapshots__/x.com.processed.withStyles.html +0 -2720
  442. package/src/a11y-client.ts +0 -241
  443. package/src/agent-skills/conan-config/SKILL.md +0 -141
  444. package/src/agent-skills/conan-config/agents/openai.yaml +0 -4
  445. package/src/aria-snapshot.test.ts +0 -311
  446. package/src/aria-snapshot.ts +0 -1681
  447. package/src/aria-snapshot.unit.test.ts +0 -615
  448. package/src/aria-snapshots/github-interactive.txt +0 -193
  449. package/src/aria-snapshots/github-raw.txt +0 -309
  450. package/src/aria-snapshots/hackernews-interactive.txt +0 -477
  451. package/src/aria-snapshots/hackernews-raw.txt +0 -428
  452. package/src/aria-snapshots/prosemirror-interactive.txt +0 -66
  453. package/src/aria-snapshots/prosemirror-raw.txt +0 -145
  454. package/src/assets/aria-labels-hacker-news.png +0 -0
  455. package/src/assets/aria-labels-old-reddit.png +0 -0
  456. package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +0 -5
  457. package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +0 -18
  458. package/src/assets/x.com.html +0 -32946
  459. package/src/browser-config.ts +0 -179
  460. package/src/browser-install.ts +0 -284
  461. package/src/browser-launch.ts +0 -75
  462. package/src/builtin-capabilities.ts +0 -2765
  463. package/src/capability-agent-skill.ts +0 -305
  464. package/src/capability-auth-state.ts +0 -197
  465. package/src/capability-auth.ts +0 -249
  466. package/src/capability-cli-confirmation.test.ts +0 -90
  467. package/src/capability-options.test.ts +0 -89
  468. package/src/capability-options.ts +0 -57
  469. package/src/capability-package.test.ts +0 -204
  470. package/src/capability-package.ts +0 -555
  471. package/src/capability-registry.test.ts +0 -1905
  472. package/src/capability-registry.ts +0 -1234
  473. package/src/capability-runner.ts +0 -801
  474. package/src/capability-search-relevance.test.ts +0 -73
  475. package/src/capability-studio.test.ts +0 -45
  476. package/src/capability-studio.ts +0 -641
  477. package/src/cdp-log.test.ts +0 -131
  478. package/src/cdp-log.ts +0 -112
  479. package/src/cdp-relay.ts +0 -2944
  480. package/src/cdp-session.ts +0 -77
  481. package/src/cdp-types.ts +0 -158
  482. package/src/channel-owner-inspect.test.ts +0 -94
  483. package/src/chrome-discovery.test.ts +0 -50
  484. package/src/chrome-discovery.ts +0 -220
  485. package/src/clean-html.ts +0 -141
  486. package/src/cli-help.test.ts +0 -123
  487. package/src/cli.ts +0 -3181
  488. package/src/cloud-client.ts +0 -179
  489. package/src/create-logger.ts +0 -38
  490. package/src/debugger-examples-types.ts +0 -16
  491. package/src/debugger-examples.ts +0 -66
  492. package/src/debugger.ts +0 -708
  493. package/src/diff-utils.test.ts +0 -152
  494. package/src/diff-utils.ts +0 -70
  495. package/src/doctor.test.ts +0 -244
  496. package/src/doctor.ts +0 -321
  497. package/src/editor-examples.ts +0 -158
  498. package/src/editor.ts +0 -426
  499. package/src/env-compat.ts +0 -28
  500. package/src/executor.ts +0 -1824
  501. package/src/executor.unit.test.ts +0 -168
  502. package/src/extension-connection.test.ts +0 -855
  503. package/src/extension-icon-warning.test.ts +0 -45
  504. package/src/ghost-browser.ts +0 -149
  505. package/src/ghost-cursor-client.ts +0 -494
  506. package/src/ghost-cursor-controller.ts +0 -129
  507. package/src/ghost-cursor.ts +0 -123
  508. package/src/htmlrewrite.test.ts +0 -8008
  509. package/src/htmlrewrite.ts +0 -390
  510. package/src/index.ts +0 -53
  511. package/src/kill-port.ts +0 -219
  512. package/src/kitty-graphics.test.ts +0 -139
  513. package/src/kitty-graphics.ts +0 -79
  514. package/src/locator-selector.test.ts +0 -119
  515. package/src/mcp-client.ts +0 -78
  516. package/src/mcp.ts +0 -629
  517. package/src/on-mouse-action.test.ts +0 -226
  518. package/src/options-page.test.ts +0 -839
  519. package/src/package-paths.ts +0 -38
  520. package/src/page-markdown.ts +0 -240
  521. package/src/performance-examples.ts +0 -186
  522. package/src/playwright-import.ts +0 -59
  523. package/src/popup-relocation.test.ts +0 -163
  524. package/src/product-paths.test.ts +0 -47
  525. package/src/product-paths.ts +0 -28
  526. package/src/protocol.test.ts +0 -52
  527. package/src/protocol.ts +0 -351
  528. package/src/react-source.ts +0 -379
  529. package/src/relay-client.test.ts +0 -375
  530. package/src/relay-client.ts +0 -572
  531. package/src/relay-core.test.ts +0 -1603
  532. package/src/relay-navigation.test.ts +0 -790
  533. package/src/relay-session.test.ts +0 -1375
  534. package/src/relay-state.test.ts +0 -729
  535. package/src/relay-state.ts +0 -561
  536. package/src/replay-ai-index.test.ts +0 -278
  537. package/src/replay-ai-index.ts +0 -872
  538. package/src/replay-cli.test.ts +0 -325
  539. package/src/replay-eval.ts +0 -1039
  540. package/src/replay-handoff.test.ts +0 -163
  541. package/src/replay-handoff.ts +0 -109
  542. package/src/replay-workflow-compiler.test.ts +0 -250
  543. package/src/replay-workflow-compiler.ts +0 -700
  544. package/src/resource.md +0 -409
  545. package/src/rrweb-recording-relay.test.ts +0 -99
  546. package/src/rrweb-recording-relay.ts +0 -400
  547. package/src/rrweb-recording.ts +0 -322
  548. package/src/scoped-fs.test.ts +0 -80
  549. package/src/scoped-fs.ts +0 -420
  550. package/src/skill-stub.test.ts +0 -24
  551. package/src/snapshot-tools.test.ts +0 -1017
  552. package/src/snapshots/hacker-news-accessibility-full.md +0 -81
  553. package/src/snapshots/hacker-news-accessibility-interactive.md +0 -43
  554. package/src/snapshots/page-markdown-output.txt +0 -16
  555. package/src/snapshots/shadcn-ui-accessibility-full.md +0 -201
  556. package/src/snapshots/shadcn-ui-accessibility-interactive.md +0 -109
  557. package/src/start-relay-server.ts +0 -69
  558. package/src/styles-examples.ts +0 -84
  559. package/src/styles.ts +0 -343
  560. package/src/tabwright-agent-skill.test.ts +0 -61
  561. package/src/tabwright-agent-skill.ts +0 -105
  562. package/src/test-declarations.ts +0 -13
  563. package/src/test-utils.test.ts +0 -70
  564. package/src/test-utils.ts +0 -566
  565. package/src/utils.ts +0 -78
  566. package/src/wait-for-page-load.ts +0 -198
  567. package/src/workflow-capability.ts +0 -417
  568. package/src/workflow-script-flow.test.ts +0 -388
@@ -1,856 +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 path from 'node:path';
5
- import fs from 'node:fs';
6
- import os from 'node:os';
7
- import { imageSize } from 'image-size';
8
- import { getCdpUrl } from './utils.js';
9
- import { getCDPSessionForPage } from './cdp-session.js';
10
- import { setupTestContext, cleanupTestContext, getExtensionServiceWorker, js } from './test-utils.js';
11
- import './test-declarations.js';
12
- const TEST_PORT = 19991;
13
- describe('Snapshot & Screenshot Tests', () => {
14
- let client;
15
- let cleanup = null;
16
- let testCtx = null;
17
- beforeAll(async () => {
18
- testCtx = await setupTestContext({ port: TEST_PORT, tempDirPrefix: 'pw-snap-test-', toggleExtension: true });
19
- const result = await createMCPClient({ port: TEST_PORT });
20
- client = result.client;
21
- cleanup = result.cleanup;
22
- }, 600000);
23
- afterAll(async () => {
24
- await cleanupTestContext(testCtx, cleanup);
25
- cleanup = null;
26
- testCtx = null;
27
- });
28
- const getBrowserContext = () => {
29
- if (!testCtx?.browserContext)
30
- throw new Error('Browser not initialized');
31
- return testCtx.browserContext;
32
- };
33
- it('should capture screenshot correctly', async () => {
34
- const browserContext = getBrowserContext();
35
- const serviceWorker = await getExtensionServiceWorker(browserContext);
36
- const page = await browserContext.newPage();
37
- await page.goto('https://example.com/');
38
- await page.bringToFront();
39
- await serviceWorker.evaluate(async () => {
40
- await globalThis.toggleExtensionForActiveTab();
41
- });
42
- await new Promise((r) => setTimeout(r, 100));
43
- const capturedCommands = [];
44
- const commandHandler = ({ command }) => {
45
- if (command.method === 'Page.captureScreenshot') {
46
- capturedCommands.push(command);
47
- }
48
- };
49
- testCtx.relayServer.on('cdp:command', commandHandler);
50
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
51
- const cdpPage = browser
52
- .contexts()[0]
53
- .pages()
54
- .find((p) => p.url().includes('example.com'));
55
- expect(cdpPage).toBeDefined();
56
- const viewportSize = cdpPage.viewportSize();
57
- console.log('Viewport size:', viewportSize);
58
- const viewportScreenshot = await cdpPage.screenshot();
59
- expect(viewportScreenshot).toBeDefined();
60
- const viewportDimensions = imageSize(viewportScreenshot);
61
- console.log('Viewport screenshot dimensions:', viewportDimensions);
62
- expect(viewportDimensions.width).toBeGreaterThan(0);
63
- expect(viewportDimensions.height).toBeGreaterThan(0);
64
- if (viewportSize) {
65
- expect(viewportDimensions.width).toBe(viewportSize.width);
66
- expect(viewportDimensions.height).toBe(viewportSize.height);
67
- }
68
- const fullPageScreenshot = await cdpPage.screenshot({ fullPage: true });
69
- expect(fullPageScreenshot).toBeDefined();
70
- const fullPageDimensions = imageSize(fullPageScreenshot);
71
- console.log('Full page screenshot dimensions:', fullPageDimensions);
72
- expect(fullPageDimensions.width).toBeGreaterThan(0);
73
- expect(fullPageDimensions.height).toBeGreaterThan(0);
74
- expect(fullPageDimensions.width).toBeGreaterThanOrEqual(viewportDimensions.width);
75
- testCtx.relayServer.off('cdp:command', commandHandler);
76
- expect(capturedCommands.length).toBe(2);
77
- expect(capturedCommands.map((c) => ({
78
- method: c.method,
79
- params: c.params,
80
- }))).toMatchInlineSnapshot(`
81
- [
82
- {
83
- "method": "Page.captureScreenshot",
84
- "params": {
85
- "captureBeyondViewport": false,
86
- "clip": {
87
- "height": 720,
88
- "scale": 1,
89
- "width": 1280,
90
- "x": 0,
91
- "y": 0,
92
- },
93
- "format": "png",
94
- },
95
- },
96
- {
97
- "method": "Page.captureScreenshot",
98
- "params": {
99
- "captureBeyondViewport": false,
100
- "clip": {
101
- "height": 581,
102
- "scale": 1,
103
- "width": 1280,
104
- "x": 0,
105
- "y": 0,
106
- },
107
- "format": "png",
108
- },
109
- },
110
- ]
111
- `);
112
- const screenshotPath = path.join(os.tmpdir(), 'tabwright-test-screenshot.png');
113
- fs.writeFileSync(screenshotPath, viewportScreenshot);
114
- console.log('Screenshot saved to:', screenshotPath);
115
- await browser.close();
116
- await page.close();
117
- }, 60000);
118
- it('should match window.innerWidth/Height without clip param', async () => {
119
- // Proves that in connectOverCDP mode, Playwright already queries
120
- // window.innerWidth/innerHeight for viewport screenshots, so passing
121
- // a manual clip is redundant.
122
- const browserContext = getBrowserContext();
123
- const serviceWorker = await getExtensionServiceWorker(browserContext);
124
- const page = await browserContext.newPage();
125
- await page.goto('https://example.com/');
126
- await page.bringToFront();
127
- await serviceWorker.evaluate(async () => {
128
- await globalThis.toggleExtensionForActiveTab();
129
- });
130
- await new Promise((r) => setTimeout(r, 100));
131
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
132
- const cdpPage = browser
133
- .contexts()[0]
134
- .pages()
135
- .find((p) => p.url().includes('example.com'));
136
- expect(cdpPage).toBeDefined();
137
- // Get actual browser viewport via JS
138
- const actualViewport = await cdpPage.evaluate(() => ({
139
- width: window.innerWidth,
140
- height: window.innerHeight,
141
- }));
142
- console.log('Actual viewport (window.inner*):', actualViewport);
143
- // Plain screenshot with scale:'css', NO clip
144
- const screenshot = await cdpPage.screenshot({ scale: 'css' });
145
- const dimensions = imageSize(screenshot);
146
- console.log('Screenshot dimensions (no clip):', dimensions);
147
- expect(dimensions.width).toBe(actualViewport.width);
148
- expect(dimensions.height).toBe(actualViewport.height);
149
- await browser.close();
150
- await page.close();
151
- }, 60000);
152
- it('should capture element screenshot with correct coordinates', async () => {
153
- const browserContext = getBrowserContext();
154
- const serviceWorker = await getExtensionServiceWorker(browserContext);
155
- const target = { x: 200, y: 150, width: 300, height: 100 };
156
- const scrolledTarget = { x: 100, y: 1500, width: 200, height: 80 };
157
- const page = await browserContext.newPage();
158
- await page.setContent(`
159
- <html>
160
- <head>
161
- <style>
162
- body { margin: 0; padding: 0; height: 2000px; }
163
- #target {
164
- position: absolute;
165
- top: ${target.y}px;
166
- left: ${target.x}px;
167
- width: ${target.width}px;
168
- height: ${target.height}px;
169
- background: red;
170
- }
171
- #scrolled-target {
172
- position: absolute;
173
- top: ${scrolledTarget.y}px;
174
- left: ${scrolledTarget.x}px;
175
- width: ${scrolledTarget.width}px;
176
- height: ${scrolledTarget.height}px;
177
- background: blue;
178
- }
179
- </style>
180
- </head>
181
- <body>
182
- <div id="target">Target Element</div>
183
- <div id="scrolled-target">Scrolled Target</div>
184
- </body>
185
- </html>
186
- `);
187
- await page.bringToFront();
188
- await serviceWorker.evaluate(async () => {
189
- await globalThis.toggleExtensionForActiveTab();
190
- });
191
- await new Promise((r) => setTimeout(r, 400));
192
- const capturedCommands = [];
193
- const commandHandler = ({ command }) => {
194
- if (command.method === 'Page.captureScreenshot') {
195
- capturedCommands.push(command);
196
- }
197
- };
198
- testCtx.relayServer.on('cdp:command', commandHandler);
199
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
200
- let cdpPage;
201
- for (const p of browser.contexts()[0].pages()) {
202
- const html = await p.content();
203
- if (html.includes('scrolled-target')) {
204
- cdpPage = p;
205
- break;
206
- }
207
- }
208
- expect(cdpPage).toBeDefined();
209
- await cdpPage.locator('#target').screenshot();
210
- await cdpPage.locator('#scrolled-target').screenshot();
211
- testCtx.relayServer.off('cdp:command', commandHandler);
212
- expect(capturedCommands.length).toBe(2);
213
- const targetCmd = capturedCommands[0];
214
- expect(targetCmd.method).toBe('Page.captureScreenshot');
215
- const targetClip = targetCmd.params.clip;
216
- expect(targetClip.x).toBe(target.x);
217
- expect(targetClip.y).toBe(target.y);
218
- expect(targetClip.width).toBe(target.width);
219
- expect(targetClip.height).toBe(target.height);
220
- const scrolledCmd = capturedCommands[1];
221
- expect(scrolledCmd.method).toBe('Page.captureScreenshot');
222
- const scrolledClip = scrolledCmd.params.clip;
223
- expect(scrolledClip.x).toBe(scrolledTarget.x);
224
- expect(scrolledClip.y).toBe(scrolledTarget.y);
225
- expect(scrolledClip.width).toBe(scrolledTarget.width);
226
- expect(scrolledClip.height).toBe(scrolledTarget.height);
227
- await browser.close();
228
- await page.close();
229
- }, 60000);
230
- it('should get locator string for element using getLocatorStringForElement', async () => {
231
- const browserContext = getBrowserContext();
232
- const serviceWorker = await getExtensionServiceWorker(browserContext);
233
- const page = await browserContext.newPage();
234
- await page.setContent(`
235
- <html>
236
- <body>
237
- <button id="test-btn">Click Me</button>
238
- <input type="text" placeholder="Enter name" />
239
- </body>
240
- </html>
241
- `);
242
- await page.bringToFront();
243
- await serviceWorker.evaluate(async () => {
244
- await globalThis.toggleExtensionForActiveTab();
245
- });
246
- await new Promise((r) => setTimeout(r, 400));
247
- const result = await client.callTool({
248
- name: 'execute',
249
- arguments: {
250
- code: js `
251
- let testPage;
252
- for (const p of context.pages()) {
253
- const html = await p.content();
254
- if (html.includes('test-btn')) { testPage = p; break; }
255
- }
256
- if (!testPage) throw new Error('Test page not found');
257
- const btn = testPage.locator('#test-btn');
258
- const locatorString = await getLocatorStringForElement(btn);
259
- console.log('Locator string:', locatorString);
260
- const locatorFromString = eval('testPage.' + locatorString);
261
- const count = await locatorFromString.count();
262
- console.log('Locator count:', count);
263
- const text = await locatorFromString.textContent();
264
- console.log('Locator text:', text);
265
- `,
266
- timeout: 30000,
267
- },
268
- });
269
- expect(result.isError).toBeFalsy();
270
- const text = result.content[0]?.text || '';
271
- expect(text).toContain('Locator string:');
272
- expect(text).toContain("getByRole('button', { name: 'Click Me' })");
273
- expect(text).toContain('Locator count:');
274
- expect(text).toContain('Locator text:');
275
- expect(text).toContain('Click Me');
276
- await page.close();
277
- }, 60000);
278
- it('should get styles for element using getStylesForLocator', async () => {
279
- const browserContext = getBrowserContext();
280
- const serviceWorker = await getExtensionServiceWorker(browserContext);
281
- const page = await browserContext.newPage();
282
- await page.setContent(`
283
- <html>
284
- <head>
285
- <style>
286
- body { font-family: Arial, sans-serif; color: #333; }
287
- .container { padding: 20px; margin: 10px; }
288
- #main-btn { background-color: blue; color: white; border-radius: 4px; }
289
- .btn { padding: 8px 16px; }
290
- </style>
291
- </head>
292
- <body>
293
- <div class="container">
294
- <button id="main-btn" class="btn" style="font-weight: bold;">Click Me</button>
295
- </div>
296
- </body>
297
- </html>
298
- `);
299
- await page.bringToFront();
300
- await serviceWorker.evaluate(async () => {
301
- await globalThis.toggleExtensionForActiveTab();
302
- });
303
- await new Promise((r) => setTimeout(r, 400));
304
- const stylesResult = await client.callTool({
305
- name: 'execute',
306
- arguments: {
307
- code: js `
308
- let testPage;
309
- for (const p of context.pages()) {
310
- const html = await p.content();
311
- if (html.includes('main-btn')) { testPage = p; break; }
312
- }
313
- if (!testPage) throw new Error('Test page not found');
314
- const btn = testPage.locator('#main-btn');
315
- const styles = await getStylesForLocator({ locator: btn });
316
- return styles;
317
- `,
318
- timeout: 30000,
319
- },
320
- });
321
- expect(stylesResult.isError).toBeFalsy();
322
- const stylesText = stylesResult.content[0]?.text || '';
323
- expect(stylesText).toMatchInlineSnapshot(`
324
- "[return value] {
325
- element: 'button#main-btn.btn',
326
- inlineStyle: { 'font-weight': 'bold' },
327
- rules: [
328
- {
329
- selector: '.btn',
330
- source: null,
331
- origin: 'regular',
332
- declarations: {
333
- padding: '8px 16px',
334
- 'padding-top': '8px',
335
- 'padding-right': '16px',
336
- 'padding-bottom': '8px',
337
- 'padding-left': '16px'
338
- },
339
- inheritedFrom: null
340
- },
341
- {
342
- selector: '#main-btn',
343
- source: null,
344
- origin: 'regular',
345
- declarations: {
346
- 'background-color': 'blue',
347
- color: 'white',
348
- 'border-radius': '4px',
349
- 'border-top-left-radius': '4px',
350
- 'border-top-right-radius': '4px',
351
- 'border-bottom-right-radius': '4px',
352
- 'border-bottom-left-radius': '4px'
353
- },
354
- inheritedFrom: null
355
- },
356
- {
357
- selector: '.container',
358
- source: null,
359
- origin: 'regular',
360
- declarations: {
361
- padding: '20px',
362
- margin: '10px',
363
- 'padding-top': '20px',
364
- 'padding-right': '20px',
365
- 'padding-bottom': '20px',
366
- 'padding-left': '20px',
367
- 'margin-top': '10px',
368
- 'margin-right': '10px',
369
- 'margin-bottom': '10px',
370
- 'margin-left': '10px'
371
- },
372
- inheritedFrom: 'ancestor[1]'
373
- },
374
- {
375
- selector: 'body',
376
- source: null,
377
- origin: 'regular',
378
- declarations: { 'font-family': 'Arial, sans-serif', color: 'rgb(51, 51, 51)' },
379
- inheritedFrom: 'ancestor[2]'
380
- }
381
- ]
382
- }"
383
- `);
384
- const formattedResult = await client.callTool({
385
- name: 'execute',
386
- arguments: {
387
- code: js `
388
- let testPage;
389
- for (const p of context.pages()) {
390
- const html = await p.content();
391
- if (html.includes('main-btn')) { testPage = p; break; }
392
- }
393
- if (!testPage) throw new Error('Test page not found');
394
- const btn = testPage.locator('#main-btn');
395
- const styles = await getStylesForLocator({ locator: btn });
396
- return formatStylesAsText(styles);
397
- `,
398
- timeout: 30000,
399
- },
400
- });
401
- expect(formattedResult.isError).toBeFalsy();
402
- const formattedText = formattedResult.content[0]?.text || '';
403
- expect(formattedText).toMatchInlineSnapshot(`
404
- "[return value] Element: button#main-btn.btn
405
-
406
- Inline styles:
407
- font-weight: bold
408
-
409
- Matched rules:
410
- .btn {
411
- padding: 8px 16px;
412
- padding-top: 8px;
413
- padding-right: 16px;
414
- padding-bottom: 8px;
415
- padding-left: 16px;
416
- }
417
- #main-btn {
418
- background-color: blue;
419
- color: white;
420
- border-radius: 4px;
421
- border-top-left-radius: 4px;
422
- border-top-right-radius: 4px;
423
- border-bottom-right-radius: 4px;
424
- border-bottom-left-radius: 4px;
425
- }
426
-
427
- Inherited from ancestor[1]:
428
- .container {
429
- padding: 20px;
430
- margin: 10px;
431
- padding-top: 20px;
432
- padding-right: 20px;
433
- padding-bottom: 20px;
434
- padding-left: 20px;
435
- margin-top: 10px;
436
- margin-right: 10px;
437
- margin-bottom: 10px;
438
- margin-left: 10px;
439
- }
440
-
441
- Inherited from ancestor[2]:
442
- body {
443
- font-family: Arial, sans-serif;
444
- color: rgb(51, 51, 51);
445
- }"
446
- `);
447
- await page.close();
448
- }, 60000);
449
- it('should return correct layout metrics via CDP', async () => {
450
- const browserContext = getBrowserContext();
451
- const serviceWorker = await getExtensionServiceWorker(browserContext);
452
- const page = await browserContext.newPage();
453
- await page.goto('https://example.com/');
454
- await page.bringToFront();
455
- await serviceWorker.evaluate(async () => {
456
- await globalThis.toggleExtensionForActiveTab();
457
- });
458
- await new Promise((r) => setTimeout(r, 100));
459
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
460
- const cdpPage = browser
461
- .contexts()[0]
462
- .pages()
463
- .find((p) => p.url().includes('example.com'));
464
- expect(cdpPage).toBeDefined();
465
- const cdpSession = await getCDPSessionForPage({ page: cdpPage });
466
- const layoutMetrics = await cdpSession.send('Page.getLayoutMetrics');
467
- const normalized = {
468
- cssLayoutViewport: layoutMetrics.cssLayoutViewport,
469
- cssVisualViewport: layoutMetrics.cssVisualViewport,
470
- layoutViewport: layoutMetrics.layoutViewport,
471
- visualViewport: layoutMetrics.visualViewport,
472
- devicePixelRatio: layoutMetrics.cssVisualViewport.clientWidth > 0
473
- ? layoutMetrics.visualViewport.clientWidth / layoutMetrics.cssVisualViewport.clientWidth
474
- : 1,
475
- };
476
- expect(normalized).toMatchInlineSnapshot(`
477
- {
478
- "cssLayoutViewport": {
479
- "clientHeight": 720,
480
- "clientWidth": 1280,
481
- "pageX": 0,
482
- "pageY": 0,
483
- },
484
- "cssVisualViewport": {
485
- "clientHeight": 720,
486
- "clientWidth": 1280,
487
- "offsetX": 0,
488
- "offsetY": 0,
489
- "pageX": 0,
490
- "pageY": 0,
491
- "scale": 1,
492
- "zoom": 1,
493
- },
494
- "devicePixelRatio": 1,
495
- "layoutViewport": {
496
- "clientHeight": 720,
497
- "clientWidth": 1280,
498
- "pageX": 0,
499
- "pageY": 0,
500
- },
501
- "visualViewport": {
502
- "clientHeight": 720,
503
- "clientWidth": 1280,
504
- "offsetX": 0,
505
- "offsetY": 0,
506
- "pageX": 0,
507
- "pageY": 0,
508
- "scale": 1,
509
- "zoom": 1,
510
- },
511
- }
512
- `);
513
- const windowDpr = await cdpPage.evaluate(() => globalThis.devicePixelRatio);
514
- console.log('window.devicePixelRatio:', windowDpr);
515
- expect(windowDpr).toBe(1);
516
- await cdpSession.detach();
517
- await browser.close();
518
- await page.close();
519
- }, 60000);
520
- it('should support getExistingCDPSession through the relay (reusing Playwright WS)', async () => {
521
- const browserContext = getBrowserContext();
522
- const serviceWorker = await getExtensionServiceWorker(browserContext);
523
- const page = await browserContext.newPage();
524
- await page.goto('https://example.com/');
525
- await page.bringToFront();
526
- await serviceWorker.evaluate(async () => {
527
- await globalThis.toggleExtensionForActiveTab();
528
- });
529
- await new Promise((r) => setTimeout(r, 100));
530
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
531
- const cdpPage = browser
532
- .contexts()[0]
533
- .pages()
534
- .find((p) => p.url().includes('example.com'));
535
- expect(cdpPage).toBeDefined();
536
- // Use the new getCDPSessionForPage which reuses Playwright's internal WS
537
- const cdpClient = await getCDPSessionForPage({ page: cdpPage });
538
- // Should be able to send CDP commands just like the regular getCDPSessionForPage
539
- const layoutMetrics = await cdpClient.send('Page.getLayoutMetrics');
540
- expect(layoutMetrics).toBeDefined();
541
- const metrics = layoutMetrics;
542
- expect(metrics.cssVisualViewport).toBeDefined();
543
- expect(metrics.cssVisualViewport.clientWidth).toBeGreaterThan(0);
544
- // Test DOM access
545
- const document = await cdpClient.send('DOM.getDocument');
546
- expect(document).toBeDefined();
547
- await cdpClient.detach();
548
- await browser.close();
549
- await page.close();
550
- }, 60000);
551
- it('should get aria ref for locator using getAriaSnapshot', async () => {
552
- const browserContext = getBrowserContext();
553
- const serviceWorker = await getExtensionServiceWorker(browserContext);
554
- const page = await browserContext.newPage();
555
- // Use data-testid for stable refs, regular id for the button
556
- await page.setContent(`
557
- <html>
558
- <body>
559
- <button data-testid="submit-btn">Submit Form</button>
560
- <a href="/about" data-testid="about-link">About Us</a>
561
- <input type="text" placeholder="Enter your name" data-testid="name-input" />
562
- </body>
563
- </html>
564
- `);
565
- await page.bringToFront();
566
- await serviceWorker.evaluate(async () => {
567
- await globalThis.toggleExtensionForActiveTab();
568
- });
569
- await new Promise((r) => setTimeout(r, 400));
570
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
571
- let cdpPage;
572
- for (const p of browser.contexts()[0].pages()) {
573
- const html = await p.content();
574
- if (html.includes('submit-btn')) {
575
- cdpPage = p;
576
- break;
577
- }
578
- }
579
- expect(cdpPage).toBeDefined();
580
- const { getAriaSnapshot } = await import('./aria-snapshot.js');
581
- const ariaResult = await getAriaSnapshot({
582
- page: cdpPage,
583
- });
584
- expect(ariaResult.snapshot).toBeDefined();
585
- expect(ariaResult.snapshot.length).toBeGreaterThan(0);
586
- expect(ariaResult.snapshot).toContain('Submit Form');
587
- // Snapshot lines include Playwright locators for interactive elements
588
- expect(ariaResult.snapshot).toContain('[data-testid="submit-btn"]');
589
- expect(ariaResult.snapshot).toContain('[data-testid="about-link"]');
590
- expect(ariaResult.snapshot).toContain('[data-testid="name-input"]');
591
- const flattenNodes = (nodes) => {
592
- return nodes.flatMap((node) => {
593
- return [node, ...flattenNodes(node.children)];
594
- });
595
- };
596
- const allNodes = flattenNodes(ariaResult.tree);
597
- const findByLocator = (locator) => {
598
- return allNodes.find((node) => node.locator === locator);
599
- };
600
- const submitNode = findByLocator('[data-testid="submit-btn"]');
601
- const aboutNode = findByLocator('[data-testid="about-link"]');
602
- const nameNode = findByLocator('[data-testid="name-input"]');
603
- expect(submitNode).toBeDefined();
604
- expect(aboutNode).toBeDefined();
605
- expect(nameNode).toBeDefined();
606
- const submitLocator = cdpPage.locator(submitNode.locator);
607
- const aboutLocator = cdpPage.locator(aboutNode.locator);
608
- const nameLocator = cdpPage.locator(nameNode.locator);
609
- expect(await submitLocator.count()).toBe(1);
610
- expect(await aboutLocator.count()).toBe(1);
611
- expect(await nameLocator.count()).toBe(1);
612
- expect(await submitLocator.textContent()).toBe('Submit Form');
613
- expect(await aboutLocator.textContent()).toBe('About Us');
614
- expect(await nameLocator.getAttribute('placeholder')).toBe('Enter your name');
615
- expect(ariaResult.refToElement.size).toBeGreaterThan(0);
616
- console.log('RefToElement map size:', ariaResult.refToElement.size);
617
- console.log('RefToElement entries:', [...ariaResult.refToElement.entries()]);
618
- // Verify refs are stable test IDs
619
- expect(ariaResult.refToElement.has('submit-btn')).toBe(true);
620
- expect(ariaResult.refToElement.has('about-link')).toBe(true);
621
- expect(ariaResult.refToElement.has('name-input')).toBe(true);
622
- // Use getSelectorForRef to get CSS selector for a ref
623
- const btnSelector = ariaResult.getSelectorForRef('submit-btn');
624
- expect(btnSelector).toBeDefined();
625
- console.log('Button selector:', btnSelector);
626
- // Verify the selector works
627
- const btnViaSelector = cdpPage.locator(btnSelector);
628
- const btnTextViaRef = await btnViaSelector.textContent();
629
- console.log('Button text via selector:', btnTextViaRef);
630
- expect(btnTextViaRef).toBe('Submit Form');
631
- // Test role and name
632
- const btnInfo = ariaResult.refToElement.get('submit-btn');
633
- expect(btnInfo?.role).toBe('button');
634
- expect(btnInfo?.name).toBe('Submit Form');
635
- const linkInfo = ariaResult.refToElement.get('about-link');
636
- expect(linkInfo?.role).toBe('link');
637
- expect(linkInfo?.name).toBe('About Us');
638
- const inputInfo = ariaResult.refToElement.get('name-input');
639
- expect(inputInfo?.role).toBe('textbox');
640
- await browser.close();
641
- await page.close();
642
- }, 60000);
643
- it('should show aria ref labels on real pages and save screenshots', async () => {
644
- const browserContext = getBrowserContext();
645
- const serviceWorker = await getExtensionServiceWorker(browserContext);
646
- const { showAriaRefLabels, hideAriaRefLabels } = await import('./aria-snapshot.js');
647
- // Create assets folder for screenshots
648
- const assetsDir = path.join(path.dirname(new URL(import.meta.url).pathname), 'assets');
649
- if (!fs.existsSync(assetsDir)) {
650
- fs.mkdirSync(assetsDir, { recursive: true });
651
- }
652
- const testPages = [
653
- { name: 'old-reddit', url: 'https://old.reddit.com/' },
654
- { name: 'hacker-news', url: 'https://news.ycombinator.com/' },
655
- ];
656
- const loadPageWithRetries = async ({ name, url }) => {
657
- const page = await browserContext.newPage();
658
- page.setDefaultNavigationTimeout(60000);
659
- const attempts = 2;
660
- let lastError = null;
661
- for (let attempt = 1; attempt <= attempts; attempt += 1) {
662
- try {
663
- console.log(`[labels] opening ${name}: ${url} (attempt ${attempt}/${attempts})`);
664
- await page.goto(url, { waitUntil: 'load' });
665
- console.log(`[labels] loaded ${name}: ${page.url()}`);
666
- return { name, url, page };
667
- }
668
- catch (error) {
669
- lastError = error;
670
- }
671
- }
672
- await page.close();
673
- throw new Error(`Failed to load ${name} after ${attempts} attempts`, {
674
- cause: lastError instanceof Error ? lastError : undefined,
675
- });
676
- };
677
- const pages = await Promise.all(testPages.map((testPage) => {
678
- return loadPageWithRetries(testPage);
679
- }));
680
- for (const { page } of pages) {
681
- await page.bringToFront();
682
- await serviceWorker.evaluate(async () => {
683
- await globalThis.toggleExtensionForActiveTab();
684
- });
685
- }
686
- const browser = await chromium.connectOverCDP(getCdpUrl({ port: TEST_PORT }));
687
- const withTimeout = async (label, task, timeoutMs) => {
688
- let timeoutId = null;
689
- const timeoutPromise = new Promise((_, reject) => {
690
- timeoutId = setTimeout(() => {
691
- reject(new Error(`Timed out after ${timeoutMs}ms: ${label}`));
692
- }, timeoutMs);
693
- });
694
- try {
695
- return await Promise.race([task(), timeoutPromise]);
696
- }
697
- finally {
698
- if (timeoutId) {
699
- clearTimeout(timeoutId);
700
- }
701
- }
702
- };
703
- const wsUrl = getCdpUrl({ port: TEST_PORT });
704
- for (const { name, url, page } of pages) {
705
- console.log(`[labels] start ${name}`);
706
- const cdpPage = browser
707
- .contexts()[0]
708
- .pages()
709
- .find((p) => p.url().includes(new URL(url).hostname));
710
- if (!cdpPage) {
711
- throw new Error(`Could not find CDP page for ${name}`);
712
- }
713
- console.log(`[labels] show labels ${name}`);
714
- const { labelCount } = await withTimeout(`showAriaRefLabels(${name})`, async () => {
715
- return await showAriaRefLabels({ page: cdpPage });
716
- }, 60000);
717
- console.log(`${name}: ${labelCount} labels shown`);
718
- expect(labelCount).toBeGreaterThan(0);
719
- console.log(`[labels] screenshot ${name}`);
720
- const screenshot = await withTimeout(`screenshot(${name})`, async () => {
721
- return await cdpPage.screenshot({ type: 'png', fullPage: false });
722
- }, 30000);
723
- const screenshotPath = path.join(assetsDir, `aria-labels-${name}.png`);
724
- fs.writeFileSync(screenshotPath, screenshot);
725
- console.log(`Screenshot saved: ${screenshotPath}`);
726
- console.log(`[labels] count dom labels ${name}`);
727
- const labelElements = await withTimeout(`countLabels(${name})`, async () => {
728
- return await cdpPage.evaluate(() => document.querySelectorAll('.__pw_label__').length);
729
- }, 10000);
730
- expect(labelElements).toBe(labelCount);
731
- console.log(`[labels] hide labels ${name}`);
732
- await withTimeout(`hideAriaRefLabels(${name})`, async () => {
733
- await hideAriaRefLabels({ page: cdpPage });
734
- }, 10000);
735
- const labelsAfterHide = await withTimeout(`verifyHide(${name})`, async () => {
736
- return await cdpPage.evaluate(() => document.getElementById('__tabwright_labels__'));
737
- }, 10000);
738
- expect(labelsAfterHide).toBeNull();
739
- console.log(`[labels] close page ${name}`);
740
- await page.close();
741
- }
742
- await browser.close();
743
- console.log(`Screenshots saved to: ${assetsDir}`);
744
- }, 180000);
745
- it('should take screenshot with accessibility labels via MCP execute tool', async () => {
746
- const browserContext = getBrowserContext();
747
- const serviceWorker = await getExtensionServiceWorker(browserContext);
748
- const page = await browserContext.newPage();
749
- await page.setContent(`
750
- <html>
751
- <head>
752
- <style>
753
- body {
754
- margin: 0;
755
- background: #e8f4f8;
756
- position: relative;
757
- min-height: 100vh;
758
- }
759
- .controls {
760
- padding: 20px;
761
- position: relative;
762
- z-index: 10;
763
- }
764
- .grid-marker {
765
- position: absolute;
766
- background: rgba(255, 100, 100, 0.3);
767
- border: 1px solid #ff6464;
768
- font-size: 10px;
769
- color: #333;
770
- display: flex;
771
- align-items: center;
772
- justify-content: center;
773
- }
774
- .h-marker {
775
- left: 0;
776
- width: 100%;
777
- height: 20px;
778
- }
779
- .v-marker {
780
- top: 0;
781
- height: 100%;
782
- width: 20px;
783
- }
784
- </style>
785
- </head>
786
- <body>
787
- <div class="controls">
788
- <button id="submit-btn">Submit Form</button>
789
- <a href="/about">About Us</a>
790
- <input type="text" placeholder="Enter your name" />
791
- </div>
792
- <!-- Horizontal markers every 200px -->
793
- <div class="grid-marker h-marker" style="top: 200px;">200px</div>
794
- <div class="grid-marker h-marker" style="top: 400px;">400px</div>
795
- <div class="grid-marker h-marker" style="top: 600px;">600px</div>
796
- <!-- Vertical markers every 200px -->
797
- <div class="grid-marker v-marker" style="left: 200px;">200</div>
798
- <div class="grid-marker v-marker" style="left: 400px;">400</div>
799
- <div class="grid-marker v-marker" style="left: 600px;">600</div>
800
- <div class="grid-marker v-marker" style="left: 800px;">800</div>
801
- <div class="grid-marker v-marker" style="left: 1000px;">1000</div>
802
- <div class="grid-marker v-marker" style="left: 1200px;">1200</div>
803
- </body>
804
- </html>
805
- `);
806
- await page.bringToFront();
807
- await serviceWorker.evaluate(async () => {
808
- await globalThis.toggleExtensionForActiveTab();
809
- });
810
- await new Promise((r) => setTimeout(r, 400));
811
- const result = await client.callTool({
812
- name: 'execute',
813
- arguments: {
814
- code: js `
815
- let testPage;
816
- for (const p of context.pages()) {
817
- const html = await p.content();
818
- if (html.includes('submit-btn')) { testPage = p; break; }
819
- }
820
- if (!testPage) throw new Error('Test page not found');
821
- await screenshotWithAccessibilityLabels({ page: testPage });
822
- `,
823
- timeout: 15000,
824
- },
825
- });
826
- expect(result.isError).toBeFalsy();
827
- const content = result.content;
828
- expect(content.length).toBe(2);
829
- const textContent = content.find((c) => c.type === 'text');
830
- expect(textContent).toBeDefined();
831
- expect(textContent.text).toContain('Screenshot saved to:');
832
- expect(textContent.text).toContain('image included below');
833
- expect(textContent.text).toContain('Accessibility snapshot:');
834
- expect(textContent.text).toContain('Submit Form');
835
- const imageContent = content.find((c) => c.type === 'image');
836
- expect(imageContent).toBeDefined();
837
- expect(imageContent.mimeType).toBe('image/png');
838
- expect(imageContent.data).toBeDefined();
839
- expect(imageContent.data.length).toBeGreaterThan(100);
840
- const buffer = Buffer.from(imageContent.data, 'base64');
841
- const dimensions = imageSize(buffer);
842
- const viewport = await page.evaluate(() => ({
843
- innerWidth: window.innerWidth,
844
- innerHeight: window.innerHeight,
845
- outerWidth: window.outerWidth,
846
- outerHeight: window.outerHeight,
847
- }));
848
- console.log('Screenshot dimensions:', dimensions.width, 'x', dimensions.height);
849
- console.log('Window viewport:', viewport);
850
- expect(dimensions.type).toBe('png');
851
- expect(dimensions.width).toBeGreaterThan(0);
852
- expect(dimensions.height).toBeGreaterThan(0);
853
- await page.close();
854
- }, 60000);
855
- });
856
- //# sourceMappingURL=snapshot-tools.test.js.map