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,241 +0,0 @@
1
- /**
2
- * Browser-side accessibility label renderer.
3
- * Bundled and injected into page context via CDP.
4
- */
5
-
6
- export interface LabelBox {
7
- x: number
8
- y: number
9
- width: number
10
- height: number
11
- }
12
-
13
- export interface A11yLabel {
14
- ref: string
15
- role: string
16
- box: LabelBox
17
- }
18
-
19
- // ============================================================================
20
- // Constants
21
- // ============================================================================
22
-
23
- const LABELS_CONTAINER_ID = '__tabwright_labels__'
24
- const LABELS_TIMER_KEY = '__tabwright_labels_timer__'
25
-
26
- // Color scheme for labels by role
27
- const ROLE_COLORS: Record<string, [string, string, string]> = {
28
- link: ['#FFF785', '#FFC542', '#E3BE23'],
29
- button: ['#FFE0B2', '#FFCC80', '#FFB74D'],
30
- textbox: ['#FFCDD2', '#EF9A9A', '#E57373'],
31
- combobox: ['#F8BBD0', '#F48FB1', '#F06292'],
32
- searchbox: ['#F8BBD0', '#F48FB1', '#F06292'],
33
- checkbox: ['#C8E6C9', '#A5D6A7', '#81C784'],
34
- radio: ['#C8E6C9', '#A5D6A7', '#81C784'],
35
- slider: ['#BBDEFB', '#90CAF9', '#64B5F6'],
36
- spinbutton: ['#BBDEFB', '#90CAF9', '#64B5F6'],
37
- switch: ['#D1C4E9', '#B39DDB', '#9575CD'],
38
- menuitem: ['#FFE0B2', '#FFCC80', '#FFB74D'],
39
- menuitemcheckbox: ['#FFE0B2', '#FFCC80', '#FFB74D'],
40
- menuitemradio: ['#FFE0B2', '#FFCC80', '#FFB74D'],
41
- option: ['#FFE0B2', '#FFCC80', '#FFB74D'],
42
- tab: ['#FFE0B2', '#FFCC80', '#FFB74D'],
43
- treeitem: ['#FFE0B2', '#FFCC80', '#FFB74D'],
44
- img: ['#B3E5FC', '#81D4FA', '#4FC3F7'],
45
- video: ['#B3E5FC', '#81D4FA', '#4FC3F7'],
46
- audio: ['#B3E5FC', '#81D4FA', '#4FC3F7'],
47
- }
48
-
49
- const DEFAULT_COLORS: [string, string, string] = ['#FFF9C4', '#FFF59D', '#FFEB3B']
50
-
51
- // ============================================================================
52
- // Label Rendering
53
- // ============================================================================
54
-
55
- function renderA11yLabels(labels: A11yLabel[]): number {
56
- const doc = document
57
- const win = window as typeof window & { [LABELS_TIMER_KEY]?: number | null }
58
-
59
- // Cancel any pending auto-hide timer
60
- if (win[LABELS_TIMER_KEY]) {
61
- win.clearTimeout(win[LABELS_TIMER_KEY])
62
- win[LABELS_TIMER_KEY] = null
63
- }
64
-
65
- // Remove existing labels
66
- doc.getElementById(LABELS_CONTAINER_ID)?.remove()
67
-
68
- // Create container
69
- const container = doc.createElement('div')
70
- container.id = LABELS_CONTAINER_ID
71
- container.style.cssText = 'position:absolute;left:0;top:0;z-index:2147483647;pointer-events:none;'
72
-
73
- // Inject styles
74
- const style = doc.createElement('style')
75
- style.textContent = `
76
- .__pw_label__ {
77
- position: absolute;
78
- font: bold 12px Helvetica, Arial, sans-serif;
79
- padding: 1px 4px;
80
- border-radius: 3px;
81
- color: black;
82
- text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
83
- white-space: nowrap;
84
- }
85
- `
86
- container.appendChild(style)
87
-
88
- // Create SVG for connector lines
89
- const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg')
90
- svg.style.cssText = 'position:absolute;left:0;top:0;pointer-events:none;overflow:visible;'
91
- svg.setAttribute('width', `${doc.documentElement.scrollWidth}`)
92
- svg.setAttribute('height', `${doc.documentElement.scrollHeight}`)
93
-
94
- // Arrow markers
95
- const defs = doc.createElementNS('http://www.w3.org/2000/svg', 'defs')
96
- svg.appendChild(defs)
97
- const markerCache: Record<string, string> = {}
98
-
99
- function getArrowMarkerId(color: string): string {
100
- if (markerCache[color]) {
101
- return markerCache[color]
102
- }
103
- const markerId = `arrow-${color.replace('#', '')}`
104
- const marker = doc.createElementNS('http://www.w3.org/2000/svg', 'marker')
105
- marker.setAttribute('id', markerId)
106
- marker.setAttribute('viewBox', '0 0 10 10')
107
- marker.setAttribute('refX', '9')
108
- marker.setAttribute('refY', '5')
109
- marker.setAttribute('markerWidth', '6')
110
- marker.setAttribute('markerHeight', '6')
111
- marker.setAttribute('orient', 'auto-start-reverse')
112
- const path = doc.createElementNS('http://www.w3.org/2000/svg', 'path')
113
- path.setAttribute('d', 'M 0 0 L 10 5 L 0 10 z')
114
- path.setAttribute('fill', color)
115
- marker.appendChild(path)
116
- defs.appendChild(marker)
117
- markerCache[color] = markerId
118
- return markerId
119
- }
120
-
121
- container.appendChild(svg)
122
-
123
- // Track placed labels for overlap detection
124
- const placedLabels: Array<{ left: number; top: number; right: number; bottom: number }> = []
125
- const LABEL_HEIGHT = 17
126
- const LABEL_CHAR_WIDTH = 7
127
-
128
- const viewportLeft = win.scrollX
129
- const viewportTop = win.scrollY
130
- const viewportRight = viewportLeft + win.innerWidth
131
- const viewportBottom = viewportTop + win.innerHeight
132
-
133
- let count = 0
134
- for (const { ref, role, box } of labels) {
135
- const rectLeft = box.x
136
- const rectTop = box.y
137
- const rectRight = rectLeft + box.width
138
- const rectBottom = rectTop + box.height
139
-
140
- if (box.width <= 0 || box.height <= 0) {
141
- continue
142
- }
143
-
144
- // Skip if outside viewport
145
- if (rectRight < viewportLeft || rectLeft > viewportRight || rectBottom < viewportTop || rectTop > viewportBottom) {
146
- continue
147
- }
148
-
149
- // Calculate label position
150
- const labelWidth = ref.length * LABEL_CHAR_WIDTH + 8
151
- const labelLeft = rectLeft
152
- const labelTop = Math.max(0, rectTop - LABEL_HEIGHT)
153
- const labelRect = {
154
- left: labelLeft,
155
- top: labelTop,
156
- right: labelLeft + labelWidth,
157
- bottom: labelTop + LABEL_HEIGHT,
158
- }
159
-
160
- // Check overlap
161
- let overlaps = false
162
- for (const placed of placedLabels) {
163
- if (
164
- labelRect.left < placed.right &&
165
- labelRect.right > placed.left &&
166
- labelRect.top < placed.bottom &&
167
- labelRect.bottom > placed.top
168
- ) {
169
- overlaps = true
170
- break
171
- }
172
- }
173
- if (overlaps) {
174
- continue
175
- }
176
-
177
- // Get colors
178
- const [gradTop, gradBottom, border] = ROLE_COLORS[role] || DEFAULT_COLORS
179
-
180
- // Create label
181
- const label = doc.createElement('div')
182
- label.className = '__pw_label__'
183
- label.textContent = ref
184
- label.style.background = `linear-gradient(to bottom, ${gradTop} 0%, ${gradBottom} 100%)`
185
- label.style.border = `1px solid ${border}`
186
- label.style.left = `${labelLeft}px`
187
- label.style.top = `${labelTop}px`
188
- container.appendChild(label)
189
-
190
- // Draw connector line
191
- const line = doc.createElementNS('http://www.w3.org/2000/svg', 'line')
192
- const labelCenterX = labelLeft + labelWidth / 2
193
- const labelBottomY = labelTop + LABEL_HEIGHT
194
- const elementCenterX = rectLeft + box.width / 2
195
- const elementCenterY = rectTop + box.height / 2
196
- line.setAttribute('x1', `${labelCenterX}`)
197
- line.setAttribute('y1', `${labelBottomY}`)
198
- line.setAttribute('x2', `${elementCenterX}`)
199
- line.setAttribute('y2', `${elementCenterY}`)
200
- line.setAttribute('stroke', border)
201
- line.setAttribute('stroke-width', '1.5')
202
- line.setAttribute('marker-end', `url(#${getArrowMarkerId(border)})`)
203
- svg.appendChild(line)
204
-
205
- placedLabels.push(labelRect)
206
- count++
207
- }
208
-
209
- doc.documentElement.appendChild(container)
210
-
211
- // Auto-hide after 30 seconds
212
- win[LABELS_TIMER_KEY] = win.setTimeout(() => {
213
- doc.getElementById(LABELS_CONTAINER_ID)?.remove()
214
- win[LABELS_TIMER_KEY] = null
215
- }, 30000)
216
-
217
- return count
218
- }
219
-
220
- // ============================================================================
221
- // Hide Labels
222
- // ============================================================================
223
-
224
- export function hideA11yLabels(): void {
225
- const win = window as typeof window & { [LABELS_TIMER_KEY]?: number | null }
226
- if (win[LABELS_TIMER_KEY]) {
227
- win.clearTimeout(win[LABELS_TIMER_KEY])
228
- win[LABELS_TIMER_KEY] = null
229
- }
230
- document.getElementById(LABELS_CONTAINER_ID)?.remove()
231
- }
232
-
233
- // ============================================================================
234
- // Expose on globalThis for injection
235
- // ============================================================================
236
-
237
- ;(globalThis as { __a11y?: { renderA11yLabels: (labels: A11yLabel[]) => number; hideA11yLabels: () => void } }).__a11y =
238
- {
239
- renderA11yLabels,
240
- hideA11yLabels,
241
- }
@@ -1,311 +0,0 @@
1
- import { describe, it, expect, beforeAll, afterAll } from 'vitest'
2
- import http from 'node:http'
3
- import net from 'node:net'
4
- import { Page } from '@xmorse/playwright-core'
5
- import fs from 'node:fs'
6
- import path from 'node:path'
7
- import { getAriaSnapshot } from './aria-snapshot.js'
8
- import { getCdpUrl } from './utils.js'
9
- import { getCDPSessionForPage } from './cdp-session.js'
10
- import { setupTestContext, cleanupTestContext, getExtensionServiceWorker, type TestContext } from './test-utils.js'
11
-
12
- const TEST_PORT = 19986
13
- const SNAPSHOTS_DIR = path.join(import.meta.dirname, 'aria-snapshots')
14
- const AX_DEBUG_DIR = path.join(import.meta.dirname, '__snapshots__', 'ax-debug')
15
- const SHOULD_DUMP_AX = process.env.PLAYWRITER_DUMP_AX === '1'
16
-
17
- type HtmlServer = {
18
- baseUrl: string
19
- close: () => Promise<void>
20
- }
21
-
22
- async function createHtmlServer({ htmlByPath }: { htmlByPath: Record<string, string> }): Promise<HtmlServer> {
23
- const openSockets: Set<net.Socket> = new Set()
24
- const server = http.createServer((req, res) => {
25
- const requestUrl = req.url || '/'
26
- const html = htmlByPath[requestUrl]
27
- if (!html) {
28
- res.writeHead(404, { 'Content-Type': 'text/plain' })
29
- res.end('Not found')
30
- return
31
- }
32
- res.writeHead(200, { 'Content-Type': 'text/html' })
33
- res.end(html)
34
- })
35
-
36
- server.on('connection', (socket) => {
37
- openSockets.add(socket)
38
- socket.on('close', () => {
39
- openSockets.delete(socket)
40
- })
41
- })
42
-
43
- await new Promise<void>((resolve) => {
44
- server.listen(0, '127.0.0.1', resolve)
45
- })
46
-
47
- const address = server.address()
48
- if (!address || typeof address === 'string') {
49
- throw new Error('Failed to bind test server')
50
- }
51
-
52
- return {
53
- baseUrl: `http://127.0.0.1:${address.port}`,
54
- close: () => {
55
- for (const socket of openSockets) {
56
- socket.destroy()
57
- }
58
- return new Promise((resolve, reject) => {
59
- server.close((error) => {
60
- if (error) {
61
- reject(error)
62
- return
63
- }
64
- resolve()
65
- })
66
- })
67
- },
68
- }
69
- }
70
-
71
- describe('aria-snapshot', () => {
72
- let ctx: TestContext
73
- let page: Page
74
-
75
- beforeAll(async () => {
76
- ctx = await setupTestContext({ port: TEST_PORT, tempDirPrefix: 'aria-snapshot-test-', toggleExtension: true })
77
- page = await ctx.browserContext.newPage()
78
- const serviceWorker = await getExtensionServiceWorker(ctx.browserContext)
79
- await page.goto('about:blank')
80
- await serviceWorker.evaluate(async () => {
81
- await (globalThis as any).toggleExtensionForActiveTab()
82
- })
83
- if (!fs.existsSync(SNAPSHOTS_DIR)) {
84
- fs.mkdirSync(SNAPSHOTS_DIR, { recursive: true })
85
- }
86
- if (SHOULD_DUMP_AX && !fs.existsSync(AX_DEBUG_DIR)) {
87
- fs.mkdirSync(AX_DEBUG_DIR, { recursive: true })
88
- }
89
- }, 60000)
90
-
91
- afterAll(async () => {
92
- await cleanupTestContext(ctx)
93
- })
94
-
95
- const sites = [
96
- { name: 'hackernews', url: 'https://news.ycombinator.com' },
97
- { name: 'github', url: 'https://github.com' },
98
- { name: 'prosemirror', url: 'https://prosemirror.net/' },
99
- ]
100
-
101
- for (const site of sites) {
102
- it(`${site.name} - snapshot`, async () => {
103
- await page.goto(site.url, { waitUntil: 'domcontentloaded' })
104
- await page.waitForTimeout(1000)
105
-
106
- if (SHOULD_DUMP_AX) {
107
- const cdp = await getCDPSessionForPage({ page })
108
- try {
109
- await cdp.send('DOM.enable')
110
- await cdp.send('Accessibility.enable')
111
- const axTree = await cdp.send('Accessibility.getFullAXTree')
112
- const domTree = await cdp.send('DOM.getFlattenedDocument', { depth: -1, pierce: true })
113
- fs.writeFileSync(path.join(AX_DEBUG_DIR, `${site.name}-ax-tree.json`), JSON.stringify(axTree, null, 2))
114
- fs.writeFileSync(path.join(AX_DEBUG_DIR, `${site.name}-dom-flat.json`), JSON.stringify(domTree, null, 2))
115
- } finally {
116
- await cdp.detach()
117
- }
118
- }
119
-
120
- const { snapshot } = await getAriaSnapshot({ page })
121
- expect(snapshot.length).toBeGreaterThan(0)
122
- // Check for locator format: attribute selector or role selector
123
- expect(snapshot).toMatch(/(?:\[id="|\[data-[\w-]+="|role=)/)
124
- const wrapperLines = snapshot.split('\n').filter((line) => {
125
- const trimmed = line.trim()
126
- return /^-\s+(generic|group|none|presentation)\s*:?$/.test(trimmed)
127
- })
128
- expect(wrapperLines).toEqual([])
129
- fs.writeFileSync(path.join(SNAPSHOTS_DIR, `${site.name}-raw.txt`), snapshot)
130
- console.log(`\n📊 ${site.name.toUpperCase()} snapshot size: ${snapshot.length} bytes`)
131
-
132
- const { snapshot: interactiveSnapshot } = await getAriaSnapshot({
133
- page,
134
- interactiveOnly: true,
135
- })
136
- expect(interactiveSnapshot).not.toMatch(/^-\s+heading\b/m)
137
- // Check for locator format: attribute selector or role selector
138
- expect(interactiveSnapshot).toMatch(/(?:\[id="|\[data-[\w-]+="|role=)/)
139
- fs.writeFileSync(path.join(SNAPSHOTS_DIR, `${site.name}-interactive.txt`), interactiveSnapshot)
140
- }, 30000)
141
- }
142
-
143
- it('prosemirror editor - contenteditable appears in snapshot and is interactable', async () => {
144
- await page.goto('https://prosemirror.net/', { waitUntil: 'domcontentloaded' })
145
- await page.waitForTimeout(2000)
146
-
147
- const { snapshot: interactiveSnapshot } = await getAriaSnapshot({ page, interactiveOnly: true })
148
-
149
- fs.writeFileSync(path.join(SNAPSHOTS_DIR, 'prosemirror-interactive.txt'), interactiveSnapshot)
150
- console.log('\n--- PROSEMIRROR INTERACTIVE SNAPSHOT ---')
151
- console.log(interactiveSnapshot)
152
-
153
- // The ProseMirror editor uses a bare <div contenteditable="true"> without role="textbox".
154
- // After the contenteditable promotion fix, it should appear as a textbox.
155
- expect(interactiveSnapshot).toContain('textbox')
156
- expect(interactiveSnapshot).toContain('[contenteditable="true"]')
157
-
158
- // The generated locator should actually work in Playwright
159
- const editor = page.locator('[contenteditable="true"]')
160
- const editorCount = await editor.count()
161
- expect(editorCount).toBe(1)
162
-
163
- // Click on the editor and type content
164
- await editor.click()
165
- // Select all existing content and replace it
166
- await page.keyboard.press('ControlOrMeta+A')
167
- await page.keyboard.type('Hello from Tabwright test!')
168
-
169
- const content = await editor.innerText()
170
- expect(content).toContain('Hello from Tabwright test!')
171
-
172
- // Take full snapshot again and verify the new content is visible
173
- const { snapshot: afterSnapshot } = await getAriaSnapshot({ page })
174
- expect(afterSnapshot).toContain('Hello from Tabwright test')
175
- }, 30000)
176
-
177
- it('bare contenteditable without role=textbox shows in snapshot', async () => {
178
- // Reproduces the core issue: bare contenteditable divs (like ProseMirror uses)
179
- // have no explicit role="textbox", so Chrome's AX tree reports them as "generic".
180
- // Our fix promotes them to textbox.
181
- const htmlServer = await createHtmlServer({
182
- htmlByPath: {
183
- '/': `<!doctype html>
184
- <html>
185
- <head><meta charset="utf-8"><title>ContentEditable Test</title></head>
186
- <body>
187
- <h1>Rich Text Editor Test</h1>
188
- <div id="editor-with-id" contenteditable="true"
189
- style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
190
- <p>Editor with id, no role attribute.</p>
191
- </div>
192
- <div class="ProseMirror" contenteditable="true"
193
- style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
194
- <p>Bare ProseMirror-style editor, no role, no id.</p>
195
- </div>
196
- <div contenteditable=""
197
- style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
198
- <p>Editor with empty contenteditable attr.</p>
199
- </div>
200
- <div contenteditable="plaintext-only"
201
- style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
202
- <p>Plaintext-only editor.</p>
203
- </div>
204
- <div contenteditable="true" role="textbox" aria-label="Labeled editor"
205
- style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
206
- <p>Editor with explicit role=textbox.</p>
207
- </div>
208
- <input type="text" placeholder="Normal input" />
209
- </body>
210
- </html>`,
211
- },
212
- })
213
-
214
- try {
215
- await page.goto(htmlServer.baseUrl, { waitUntil: 'domcontentloaded' })
216
- await page.waitForTimeout(500)
217
-
218
- const { snapshot: interactiveSnapshot } = await getAriaSnapshot({ page, interactiveOnly: true })
219
- console.log('\n--- CONTENTEDITABLE INTERACTIVE SNAPSHOT ---')
220
- console.log(interactiveSnapshot)
221
-
222
- // All contenteditable divs should appear as textbox
223
- const textboxLines = interactiveSnapshot.split('\n').filter((line) => {
224
- return line.includes('textbox')
225
- })
226
- // 5 contenteditable (id, bare, empty-attr, plaintext-only, explicit-role) + 1 input = 6
227
- expect(textboxLines.length).toBeGreaterThanOrEqual(6)
228
-
229
- // The editor with id should use [id="editor-with-id"] as locator
230
- expect(interactiveSnapshot).toContain('[id="editor-with-id"]')
231
-
232
- // The bare contenteditable without id/role should use [contenteditable="true"]
233
- expect(interactiveSnapshot).toContain('[contenteditable="true"]')
234
-
235
- // Try clicking and typing in the bare contenteditable (no role, no id)
236
- const bareEditors = page.locator('[contenteditable="true"]')
237
- const bareCount = await bareEditors.count()
238
- expect(bareCount).toBeGreaterThanOrEqual(2) // at least the 2 bare ones
239
-
240
- // Click the first bare contenteditable and type
241
- await bareEditors.first().click()
242
- await page.keyboard.press('ControlOrMeta+A')
243
- await page.keyboard.type('Typed via locator!')
244
-
245
- const content = await bareEditors.first().innerText()
246
- expect(content).toContain('Typed via locator!')
247
- } finally {
248
- await htmlServer.close()
249
- }
250
- }, 30000)
251
-
252
- it('scopes snapshot to cross-origin iframe locator', async () => {
253
- const iframeServer = await createHtmlServer({
254
- htmlByPath: {
255
- '/iframe.html': `<!doctype html>
256
- <html>
257
- <head>
258
- <meta charset="utf-8" />
259
- <title>Iframe Content</title>
260
- </head>
261
- <body>
262
- <h1>Iframe Heading</h1>
263
- <button data-testid="iframe-button">Iframe Button</button>
264
- </body>
265
- </html>`,
266
- },
267
- })
268
-
269
- const outerServer = await createHtmlServer({
270
- htmlByPath: {
271
- '/': `<!doctype html>
272
- <html>
273
- <head>
274
- <meta charset="utf-8" />
275
- <title>Outer Page</title>
276
- </head>
277
- <body>
278
- <h1>Outer Heading</h1>
279
- <iframe data-testid="external-iframe" src="${iframeServer.baseUrl}/iframe.html"></iframe>
280
- </body>
281
- </html>`,
282
- },
283
- })
284
-
285
- try {
286
- await page.goto(outerServer.baseUrl, { waitUntil: 'domcontentloaded', timeout: 10000 })
287
- await page.locator('[data-testid="external-iframe"]').waitFor({ timeout: 5000 })
288
- await page
289
- .frameLocator('[data-testid="external-iframe"]')
290
- .locator('[data-testid="iframe-button"]')
291
- .waitFor({ timeout: 5000 })
292
-
293
- // Convert iframe Locator to Frame
294
- const iframeHandle = await page.locator('[data-testid="external-iframe"]').elementHandle()
295
- const iframeFrame = await iframeHandle!.contentFrame()
296
-
297
- const { snapshot } = await getAriaSnapshot({
298
- page,
299
- frame: iframeFrame!,
300
- })
301
-
302
- expect(snapshot).toContain('Iframe Heading')
303
- // TODO we seem to be using name with higher priority than test id for some reason in snapshots
304
- // expect(snapshot).toContain('[data-testid="iframe-button"]')
305
- expect(snapshot).not.toContain('Outer Heading')
306
- } finally {
307
- await outerServer.close()
308
- await iframeServer.close()
309
- }
310
- }, 30000)
311
- })