testdriverai 7.3.1 → 7.3.3

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 (362) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +4 -0
  3. package/.github/workflows/acceptance-linux-scheduled.yaml +45 -0
  4. package/.github/workflows/acceptance-windows-scheduled.yaml +54 -0
  5. package/.github/workflows/acceptance.yaml +106 -0
  6. package/.github/workflows/publish.yaml +75 -0
  7. package/.github/workflows/test-init.yml +157 -0
  8. package/.github/workflows/testdriver.yml +170 -0
  9. package/.github/workflows/windows-self-hosted.yaml +82 -0
  10. package/.prettierignore +4 -0
  11. package/.prettierrc +1 -0
  12. package/CHANGELOG.md +158 -0
  13. package/SKILLs.md +17 -0
  14. package/agent/index.js +32 -3
  15. package/ai/.claude-plugin/plugin.json +9 -0
  16. package/docs/GITHUB_COMMENTS.md +330 -0
  17. package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
  18. package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
  19. package/docs/TEST-GITHUB-COMMENTS.md +129 -0
  20. package/docs/_scripts/generate-skills.js +149 -0
  21. package/docs/_scripts/link-replacer.js +164 -0
  22. package/docs/_scripts/upload-docs-to-openai.js +284 -0
  23. package/docs/claude-mcp-plugin.mdx +160 -0
  24. package/docs/docs.json +394 -0
  25. package/docs/github-integration-setup.md +266 -0
  26. package/docs/guide/best-practices-polling.mdx +154 -0
  27. package/docs/images/content/account/newprojectsettings.png +0 -0
  28. package/docs/images/content/account/projectpage.png +0 -0
  29. package/docs/images/content/account/projectreplays.png +0 -0
  30. package/docs/images/content/account/team-manage.png +0 -0
  31. package/docs/images/content/account/teampage.png +0 -0
  32. package/docs/images/content/extension/cursor.svg +1 -0
  33. package/docs/images/content/extension/vscode.svg +57 -0
  34. package/docs/images/content/extension/windsurf.svg +3 -0
  35. package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
  36. package/docs/images/content/side-by-side.png +0 -0
  37. package/docs/images/content/vscode/ide-full.png +0 -0
  38. package/docs/images/content/vscode/running.png +0 -0
  39. package/docs/images/content/vscode/vscode-2-assert.png +0 -0
  40. package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
  41. package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
  42. package/docs/images/content/vscode/vscode-file-creation.png +0 -0
  43. package/docs/images/content/vscode/vscode-install.png +0 -0
  44. package/docs/images/content/vscode/vscode-overview.png +0 -0
  45. package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
  46. package/docs/images/content/vscode/vscode-stopchat.png +0 -0
  47. package/docs/images/content/vscode/vscode-stoptest.png +0 -0
  48. package/docs/images/content/vscode/vscode-tdservice.png +0 -0
  49. package/docs/images/content/vscode/vscode-test-output.png +0 -0
  50. package/docs/images/content/vscode/vscode-testhistory.png +0 -0
  51. package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
  52. package/docs/images/content/vscode/vscode-testpane.png +0 -0
  53. package/docs/images/template/dark.png +0 -0
  54. package/docs/images/template/icon.png +0 -0
  55. package/docs/images/template/light.png +0 -0
  56. package/docs/snippets/calendar-link.mdx +4 -0
  57. package/docs/snippets/gitignore-warning.mdx +7 -0
  58. package/docs/snippets/lifecycle-warning.mdx +6 -0
  59. package/docs/snippets/test-prereqs.mdx +12 -0
  60. package/docs/snippets/tests/assert-replay.mdx +7 -0
  61. package/docs/snippets/tests/assert-yaml.mdx +8 -0
  62. package/docs/snippets/tests/exec-js-replay.mdx +7 -0
  63. package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
  64. package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
  65. package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
  66. package/docs/snippets/tests/hover-image-replay.mdx +7 -0
  67. package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
  68. package/docs/snippets/tests/hover-text-replay.mdx +7 -0
  69. package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
  70. package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
  71. package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
  72. package/docs/snippets/tests/match-image-replay.mdx +7 -0
  73. package/docs/snippets/tests/match-image-yaml.mdx +17 -0
  74. package/docs/snippets/tests/press-keys-replay.mdx +7 -0
  75. package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
  76. package/docs/snippets/tests/remember-replay.mdx +7 -0
  77. package/docs/snippets/tests/remember-yaml.mdx +28 -0
  78. package/docs/snippets/tests/scroll-replay.mdx +7 -0
  79. package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
  80. package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
  81. package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
  82. package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
  83. package/docs/snippets/tests/scroll-yaml.mdx +30 -0
  84. package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
  85. package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
  86. package/docs/snippets/tests/type-replay.mdx +7 -0
  87. package/docs/snippets/tests/type-yaml.mdx +28 -0
  88. package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
  89. package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
  90. package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
  91. package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
  92. package/docs/snippets/tests/wait-replay.mdx +7 -0
  93. package/docs/snippets/tests/wait-yaml.mdx +13 -0
  94. package/docs/styles.css +65 -0
  95. package/docs/v6/account/dashboard.mdx +16 -0
  96. package/docs/v6/account/enterprise.mdx +110 -0
  97. package/docs/v6/account/pricing.mdx +33 -0
  98. package/docs/v6/account/projects.mdx +33 -0
  99. package/docs/v6/account/team.mdx +35 -0
  100. package/docs/v6/action/ami.mdx +109 -0
  101. package/docs/v6/action/performance.mdx +105 -0
  102. package/docs/v6/action/secrets.mdx +93 -0
  103. package/docs/v6/apps/chrome-extensions.mdx +48 -0
  104. package/docs/v6/apps/desktop-apps.mdx +93 -0
  105. package/docs/v6/apps/mobile-apps.mdx +26 -0
  106. package/docs/v6/apps/static-websites.mdx +54 -0
  107. package/docs/v6/apps/tauri-apps.mdx +361 -0
  108. package/docs/v6/bugs/jira.mdx +232 -0
  109. package/docs/v6/cli/overview.mdx +66 -0
  110. package/docs/v6/commands/assert.mdx +45 -0
  111. package/docs/v6/commands/exec.mdx +282 -0
  112. package/docs/v6/commands/focus-application.mdx +44 -0
  113. package/docs/v6/commands/hover-image.mdx +69 -0
  114. package/docs/v6/commands/hover-text.mdx +47 -0
  115. package/docs/v6/commands/if.mdx +53 -0
  116. package/docs/v6/commands/match-image.mdx +67 -0
  117. package/docs/v6/commands/press-keys.mdx +87 -0
  118. package/docs/v6/commands/remember.mdx +49 -0
  119. package/docs/v6/commands/run.mdx +44 -0
  120. package/docs/v6/commands/scroll-until-image.mdx +66 -0
  121. package/docs/v6/commands/scroll-until-text.mdx +60 -0
  122. package/docs/v6/commands/scroll.mdx +69 -0
  123. package/docs/v6/commands/type.mdx +45 -0
  124. package/docs/v6/commands/wait-for-image.mdx +54 -0
  125. package/docs/v6/commands/wait-for-text.mdx +48 -0
  126. package/docs/v6/commands/wait.mdx +45 -0
  127. package/docs/v6/exporting/junit.mdx +218 -0
  128. package/docs/v6/exporting/playwright.mdx +197 -0
  129. package/docs/v6/features/auto-healing.mdx +144 -0
  130. package/docs/v6/features/generation.mdx +116 -0
  131. package/docs/v6/features/parallel-testing.mdx +151 -0
  132. package/docs/v6/features/reusable-snippets.mdx +131 -0
  133. package/docs/v6/features/selectorless.mdx +80 -0
  134. package/docs/v6/features/visual-assertions.mdx +139 -0
  135. package/docs/v6/getting-started/ci.mdx +146 -0
  136. package/docs/v6/getting-started/cli.mdx +91 -0
  137. package/docs/v6/getting-started/editing.mdx +100 -0
  138. package/docs/v6/getting-started/playwright.mdx +342 -0
  139. package/docs/v6/getting-started/running.mdx +48 -0
  140. package/docs/v6/getting-started/self-hosting.mdx +408 -0
  141. package/docs/v6/getting-started/vscode.mdx +88 -0
  142. package/docs/v6/guide/assertions.mdx +189 -0
  143. package/docs/v6/guide/authentication.mdx +136 -0
  144. package/docs/v6/guide/code.mdx +65 -0
  145. package/docs/v6/guide/dashcam.mdx +118 -0
  146. package/docs/v6/guide/environment-variables.mdx +26 -0
  147. package/docs/v6/guide/lifecycle.mdx +242 -0
  148. package/docs/v6/guide/locating.mdx +141 -0
  149. package/docs/v6/guide/protips.mdx +43 -0
  150. package/docs/v6/guide/variables.mdx +143 -0
  151. package/docs/v6/guide/waiting.mdx +130 -0
  152. package/docs/v6/importing/csv.mdx +196 -0
  153. package/docs/v6/importing/gherkin.mdx +143 -0
  154. package/docs/v6/importing/jira.mdx +164 -0
  155. package/docs/v6/importing/testrail.mdx +162 -0
  156. package/docs/v6/integrations/electron.mdx +146 -0
  157. package/docs/v6/integrations/netlify.mdx +100 -0
  158. package/docs/v6/integrations/vercel.mdx +125 -0
  159. package/docs/v6/interactive/explore.mdx +99 -0
  160. package/docs/v6/interactive/run.mdx +52 -0
  161. package/docs/v6/interactive/save.mdx +63 -0
  162. package/docs/v6/overview/comparison.mdx +101 -0
  163. package/docs/v6/overview/faq.mdx +162 -0
  164. package/docs/v6/overview/performance.mdx +52 -0
  165. package/docs/v6/overview/quickstart.mdx +137 -0
  166. package/docs/v6/overview/what-is-testdriver.mdx +85 -0
  167. package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
  168. package/docs/v6/scenarios/cookie-banner.mdx +32 -0
  169. package/docs/v6/scenarios/file-upload.mdx +33 -0
  170. package/docs/v6/scenarios/form-filling.mdx +32 -0
  171. package/docs/v6/scenarios/log-in.mdx +75 -0
  172. package/docs/v6/scenarios/pdf-generation.mdx +25 -0
  173. package/docs/v6/scenarios/spell-check.mdx +22 -0
  174. package/docs/v6/security/action.mdx +84 -0
  175. package/docs/v6/security/agent.mdx +73 -0
  176. package/docs/v6/security/platform.mdx +77 -0
  177. package/docs/v6/tutorials/advanced-test.mdx +81 -0
  178. package/docs/v6/tutorials/basic-test.mdx +45 -0
  179. package/docs/v7/_drafts/agents.mdx +852 -0
  180. package/docs/v7/_drafts/architecture.mdx +399 -0
  181. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  182. package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
  183. package/docs/v7/_drafts/best-practices.mdx +486 -0
  184. package/docs/v7/_drafts/caching-ai.mdx +215 -0
  185. package/docs/v7/_drafts/caching-selectors.mdx +424 -0
  186. package/docs/v7/_drafts/caching.mdx +366 -0
  187. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
  188. package/docs/v7/_drafts/commands/assert.mdx +45 -0
  189. package/docs/v7/_drafts/commands/exec.mdx +282 -0
  190. package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
  191. package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
  192. package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
  193. package/docs/v7/_drafts/commands/if.mdx +53 -0
  194. package/docs/v7/_drafts/commands/match-image.mdx +67 -0
  195. package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
  196. package/docs/v7/_drafts/commands/remember.mdx +49 -0
  197. package/docs/v7/_drafts/commands/run.mdx +44 -0
  198. package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
  199. package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
  200. package/docs/v7/_drafts/commands/scroll.mdx +69 -0
  201. package/docs/v7/_drafts/commands/type.mdx +45 -0
  202. package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
  203. package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
  204. package/docs/v7/_drafts/commands/wait.mdx +45 -0
  205. package/docs/v7/_drafts/configuration.mdx +378 -0
  206. package/docs/v7/_drafts/contributing.mdx +174 -0
  207. package/docs/v7/_drafts/core.mdx +458 -0
  208. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  209. package/docs/v7/_drafts/debugging.mdx +349 -0
  210. package/docs/v7/_drafts/error-handling.mdx +501 -0
  211. package/docs/v7/_drafts/faq.mdx +393 -0
  212. package/docs/v7/_drafts/hooks.mdx +360 -0
  213. package/docs/v7/_drafts/init-command.mdx +95 -0
  214. package/docs/v7/_drafts/installation.mdx +420 -0
  215. package/docs/v7/_drafts/migration.mdx +562 -0
  216. package/docs/v7/_drafts/observable.mdx +604 -0
  217. package/docs/v7/_drafts/playwright.mdx +342 -0
  218. package/docs/v7/_drafts/plugin-migration.mdx +220 -0
  219. package/docs/v7/_drafts/powerful.mdx +419 -0
  220. package/docs/v7/_drafts/presets.mdx +210 -0
  221. package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
  222. package/docs/v7/_drafts/prompt-cache.mdx +200 -0
  223. package/docs/v7/_drafts/provision.mdx +390 -0
  224. package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
  225. package/docs/v7/_drafts/readme.mdx +135 -0
  226. package/docs/v7/_drafts/reports.mdx +414 -0
  227. package/docs/v7/_drafts/scalable.mdx +754 -0
  228. package/docs/v7/_drafts/screenshot.mdx +155 -0
  229. package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
  230. package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
  231. package/docs/v7/_drafts/sdk-migration.mdx +474 -0
  232. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  233. package/docs/v7/_drafts/self-hosting.mdx +369 -0
  234. package/docs/v7/_drafts/test-recording.mdx +382 -0
  235. package/docs/v7/_drafts/troubleshooting.mdx +526 -0
  236. package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
  237. package/docs/v7/_drafts/vitest.mdx +535 -0
  238. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  239. package/{ai/skills/testdriver:ai/SKILL.md → docs/v7/ai.mdx} +4 -3
  240. package/{ai/skills/testdriver:assert/SKILL.md → docs/v7/assert.mdx} +4 -3
  241. package/{ai/skills/testdriver:aws-setup/SKILL.md → docs/v7/aws-setup.mdx} +4 -3
  242. package/{ai/skills/testdriver:caching/SKILL.md → docs/v7/caching.mdx} +7 -3
  243. package/{ai/skills/testdriver:captcha/SKILL.md → docs/v7/captcha.mdx} +4 -3
  244. package/{ai/skills/testdriver:ci-cd/SKILL.md → docs/v7/ci-cd.mdx} +4 -3
  245. package/{ai/skills/testdriver:click/SKILL.md → docs/v7/click.mdx} +4 -3
  246. package/{ai/skills/testdriver:client/SKILL.md → docs/v7/client.mdx} +8 -3
  247. package/{ai/skills/testdriver:cloud/SKILL.md → docs/v7/cloud.mdx} +4 -3
  248. package/{ai/skills/testdriver:customizing-devices/SKILL.md → docs/v7/customizing-devices.mdx} +3 -3
  249. package/{ai/skills/testdriver:dashcam/SKILL.md → docs/v7/dashcam.mdx} +4 -3
  250. package/docs/v7/debugging-with-screenshots.mdx +402 -0
  251. package/{ai/skills/testdriver:device-config/SKILL.md → docs/v7/device-config.mdx} +3 -3
  252. package/{ai/skills/testdriver:double-click/SKILL.md → docs/v7/double-click.mdx} +3 -3
  253. package/{ai/skills/testdriver:elements/SKILL.md → docs/v7/elements.mdx} +4 -3
  254. package/{ai/skills/testdriver:enterprise/SKILL.md → docs/v7/enterprise.mdx} +5 -3
  255. package/docs/v7/examples.mdx +5 -0
  256. package/{ai/skills/testdriver:exec/SKILL.md → docs/v7/exec.mdx} +4 -3
  257. package/{ai/skills/testdriver:find/SKILL.md → docs/v7/find.mdx} +4 -3
  258. package/{ai/skills/testdriver:focus-application/SKILL.md → docs/v7/focus-application.mdx} +4 -3
  259. package/{ai/skills/testdriver:generating-tests/SKILL.md → docs/v7/generating-tests.mdx} +3 -3
  260. package/{ai/skills/testdriver:hover/SKILL.md → docs/v7/hover.mdx} +4 -3
  261. package/{ai/skills/testdriver:locating-elements/SKILL.md → docs/v7/locating-elements.mdx} +3 -3
  262. package/{ai/skills/testdriver:making-assertions/SKILL.md → docs/v7/making-assertions.mdx} +3 -3
  263. package/{ai/skills/testdriver:mouse-down/SKILL.md → docs/v7/mouse-down.mdx} +3 -3
  264. package/{ai/skills/testdriver:mouse-up/SKILL.md → docs/v7/mouse-up.mdx} +3 -3
  265. package/docs/v7/ocr.mdx +236 -0
  266. package/{ai/skills/testdriver:performing-actions/SKILL.md → docs/v7/performing-actions.mdx} +3 -3
  267. package/{ai/skills/testdriver:press-keys/SKILL.md → docs/v7/press-keys.mdx} +4 -3
  268. package/{ai/skills/testdriver:quickstart/SKILL.md → docs/v7/quickstart.mdx} +6 -20
  269. package/{ai/skills/testdriver:reusable-code/SKILL.md → docs/v7/reusable-code.mdx} +3 -3
  270. package/{ai/skills/testdriver:right-click/SKILL.md → docs/v7/right-click.mdx} +3 -3
  271. package/{ai/skills/testdriver:running-tests/SKILL.md → docs/v7/running-tests.mdx} +7 -3
  272. package/{ai/skills/testdriver:screenshot/SKILL.md → docs/v7/screenshot.mdx} +88 -6
  273. package/{ai/skills/testdriver:scroll/SKILL.md → docs/v7/scroll.mdx} +40 -3
  274. package/{ai/skills/testdriver:secrets/SKILL.md → docs/v7/secrets.mdx} +3 -3
  275. package/{ai/skills/testdriver:self-hosted/SKILL.md → docs/v7/self-hosted.mdx} +4 -3
  276. package/{ai/skills/testdriver:type/SKILL.md → docs/v7/type.mdx} +4 -3
  277. package/{ai/skills/testdriver:variables/SKILL.md → docs/v7/variables.mdx} +3 -3
  278. package/{ai/skills/testdriver:waiting-for-elements/SKILL.md → docs/v7/waiting-for-elements.mdx} +3 -3
  279. package/{ai/skills/testdriver:what-is-testdriver/SKILL.md → docs/v7/what-is-testdriver.mdx} +3 -3
  280. package/eslint.config.js +67 -0
  281. package/examples/ai.test.mjs +30 -0
  282. package/examples/assert.test.mjs +47 -0
  283. package/examples/captcha-api.test.mjs +50 -0
  284. package/examples/chrome-extension.test.mjs +94 -0
  285. package/examples/drag-and-drop.test.mjs +58 -0
  286. package/examples/element-not-found.test.mjs +26 -0
  287. package/examples/exec-output.test.mjs +59 -0
  288. package/examples/exec-pwsh.test.mjs +57 -0
  289. package/examples/focus-window.test.mjs +36 -0
  290. package/examples/formatted-logging.test.mjs +26 -0
  291. package/examples/hover-image.test.mjs +52 -0
  292. package/examples/hover-text-with-description.test.mjs +56 -0
  293. package/examples/hover-text.test.mjs +27 -0
  294. package/examples/installer.test.mjs +49 -0
  295. package/examples/launch-vscode-linux.test.mjs +54 -0
  296. package/examples/match-image.test.mjs +54 -0
  297. package/examples/no-provision.test.mjs +23 -0
  298. package/examples/press-keys.test.mjs +50 -0
  299. package/examples/prompt.test.mjs +33 -0
  300. package/examples/scroll-keyboard.test.mjs +37 -0
  301. package/examples/scroll-until-image.test.mjs +39 -0
  302. package/examples/scroll-until-text.test.mjs +67 -0
  303. package/examples/scroll.test.mjs +41 -0
  304. package/examples/type.test.mjs +45 -0
  305. package/examples/windows-installer.test.mjs +53 -0
  306. package/jsconfig.json +26 -0
  307. package/lib/vitest/hooks.mjs +3 -0
  308. package/manual/test-init-command.js +223 -0
  309. package/mcp-server/README.md +312 -0
  310. package/mcp-server/mcp-app.html +28 -0
  311. package/mcp-server/mcp-config.example.json +19 -0
  312. package/mcp-server/package-lock.json +4018 -0
  313. package/mcp-server/package.json +29 -0
  314. package/mcp-server/src/codegen.ts +189 -0
  315. package/mcp-server/src/mcp-app.css +360 -0
  316. package/mcp-server/src/mcp-app.ts +547 -0
  317. package/mcp-server/src/provision-types.ts +209 -0
  318. package/mcp-server/src/server.ts +2313 -0
  319. package/mcp-server/src/session.ts +194 -0
  320. package/mcp-server/tsconfig.json +16 -0
  321. package/mcp-server/vite.config.ts +23 -0
  322. package/package.json +2 -17
  323. package/scripts/generate-skills.js +94 -0
  324. package/sdk.js +3 -0
  325. package/setup/aws/cloudformation.yaml +470 -0
  326. package/setup/aws/spawn-runner.sh +190 -0
  327. package/test/api-resilience.test.mjs +0 -0
  328. package/test/captcha-solver.test.mjs +152 -0
  329. package/test/chrome-remote-debugging.test.mjs +66 -0
  330. package/test/duckduckgo/experiment.test.mjs +28 -0
  331. package/test/duckduckgo/setup.test.mjs +29 -0
  332. package/test/manual/debug-locate-response.js +82 -0
  333. package/test/manual/reconnect-provision.test.mjs +49 -0
  334. package/test/manual/test-console-logs.test.mjs +42 -0
  335. package/test/manual/test-find-api.js +73 -0
  336. package/test/manual/test-init.sh +54 -0
  337. package/test/manual/test-prompt-cache.js +97 -0
  338. package/test/manual/test-provision-auth.mjs +22 -0
  339. package/test/manual/test-sandbox-render.js +29 -0
  340. package/test/manual/test-sdk-methods.js +15 -0
  341. package/test/manual/test-sdk-refactor.js +53 -0
  342. package/test/manual/test-stack-trace.mjs +57 -0
  343. package/test/manual/verify-element-api.js +89 -0
  344. package/test/manual/verify-types.js +0 -0
  345. package/test/manual-unawaited-promise.test.mjs +31 -0
  346. package/test-ide-preview.mjs +17 -0
  347. package/tests/airbnb-booking.test.mjs +39 -0
  348. package/tests/airbnb-search.test.mjs +43 -0
  349. package/tests/example.test.js +33 -0
  350. package/tests/login.js +28 -0
  351. package/vitest.config.mjs +24 -0
  352. package/vscode-extension/.vscodeignore +12 -0
  353. package/vscode-extension/README.md +94 -0
  354. package/vscode-extension/media/icon.png +0 -0
  355. package/vscode-extension/package-lock.json +4126 -0
  356. package/vscode-extension/package.json +86 -0
  357. package/vscode-extension/src/extension.ts +829 -0
  358. package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
  359. package/vscode-extension/tsconfig.json +16 -0
  360. package/ai/skills/testdriver:examples/SKILL.md +0 -7
  361. package/ai/skills/testdriver:mcp-workflow/SKILL.md +0 -410
  362. package/ai/skills/testdriver:testdriver/SKILL.md +0 -523
@@ -0,0 +1,167 @@
1
+ # 🎉 GitHub Comments Feature
2
+
3
+ ## What's New
4
+
5
+ TestDriver now automatically posts beautiful, detailed comments to your GitHub pull requests and commits with:
6
+
7
+ - ✅ **Test Results** - Pass/fail statistics at a glance
8
+ - 🎥 **Dashcam GIF Replays** - Embedded animated previews of each test
9
+ - 📊 **Detailed Statistics** - Duration, platform, branch, commit info
10
+ - ❌ **Exception Details** - Full error messages and stack traces for failures
11
+ - 🔄 **Smart Updates** - Updates existing comments instead of creating duplicates
12
+
13
+ ## Quick Start
14
+
15
+ ### 1. Add to GitHub Actions
16
+
17
+ ```yaml
18
+ - name: Run TestDriver tests
19
+ env:
20
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
21
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22
+ GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
23
+ run: npm run test:sdk
24
+ ```
25
+
26
+ ### 2. That's it!
27
+
28
+ TestDriver will automatically detect the CI environment and post comments when:
29
+ - `GITHUB_TOKEN` is present
30
+ - `GITHUB_PR_NUMBER` (for PR comments) or `GITHUB_SHA` (for commit comments) is set
31
+
32
+ ## Example Comment
33
+
34
+ ![GitHub Comment Preview](https://placeholder.com/github-comment-preview.png)
35
+
36
+ Your team will see:
37
+ - **Status badges** with pass/fail counts
38
+ - **Embedded GIF replays** directly in the comment
39
+ - **Clickable links** to full test runs and individual replays
40
+ - **Collapsible error details** with full stack traces
41
+
42
+ ## Features
43
+
44
+ ### 🎥 Dashcam Replays
45
+
46
+ Every test automatically records a dashcam replay. These appear in the GitHub comment as:
47
+ 1. **GIF preview** - Shows the test execution as an animated image
48
+ 2. **Link to full replay** - Opens the complete replay in TestDriver console
49
+ 3. **Test-specific context** - Each test has its own replay section
50
+
51
+ ### 📊 Test Statistics
52
+
53
+ The comment shows:
54
+ - Total test count
55
+ - Pass/fail/skip breakdown
56
+ - Total execution time
57
+ - Platform (Linux/Windows/Mac)
58
+ - Git branch and commit
59
+
60
+ ### ❌ Exception Handling
61
+
62
+ Failed tests include:
63
+ - Error message prominently displayed
64
+ - Collapsible stack trace
65
+ - Direct link to the failing test's replay
66
+ - File and line number information
67
+
68
+ ### 🔄 Comment Updates
69
+
70
+ TestDriver intelligently:
71
+ - **Updates existing comments** on subsequent pushes to the same PR
72
+ - **Creates new comments** only when needed
73
+ - **Identifies its own comments** using a signature
74
+
75
+ ## Configuration
76
+
77
+ ### Environment Variables
78
+
79
+ | Variable | Description | Required |
80
+ |----------|-------------|----------|
81
+ | `TD_API_KEY` | TestDriver API key | ✅ Yes |
82
+ | `GITHUB_TOKEN` | GitHub token | ✅ Yes |
83
+ | `GITHUB_PR_NUMBER` | PR number for PR comments | 📝 Recommended |
84
+ | `GITHUB_SHA` | Commit SHA (fallback) | ⚙️ Auto-detected |
85
+ | `TESTDRIVER_SKIP_GITHUB_COMMENT` | Set to 'true' to disable | ❌ No |
86
+
87
+ ### Disabling Comments
88
+
89
+ To disable GitHub comments for a specific run:
90
+
91
+ ```bash
92
+ TESTDRIVER_SKIP_GITHUB_COMMENT=true npm run test
93
+ ```
94
+
95
+ ## Documentation
96
+
97
+ For complete documentation, see:
98
+ - **[GitHub Comments Guide](./GITHUB_COMMENTS.md)** - Full setup and configuration
99
+ - **[Example Workflow](./../examples/github-actions.yml)** - Copy-paste GitHub Actions workflow
100
+ - **[Example Test](./../examples/github-comment-demo.test.mjs)** - Demo test file
101
+
102
+ ## Troubleshooting
103
+
104
+ ### Comment not appearing?
105
+
106
+ 1. **Check environment variables:**
107
+ ```bash
108
+ echo "Token: ${GITHUB_TOKEN:0:10}..."
109
+ echo "PR: $GITHUB_PR_NUMBER"
110
+ ```
111
+
112
+ 2. **Verify permissions:**
113
+ - GitHub Actions needs `pull-requests: write` or `contents: write`
114
+
115
+ 3. **Check logs:**
116
+ - Look for "Posting GitHub comment..." in test output
117
+ - Check for "GitHub token not found" warnings
118
+
119
+ ### Replays not embedded?
120
+
121
+ - Ensure tests are using `await testdriver.provision.*()`
122
+ - Check that dashcam stops successfully (look for "🎥 Dashcam URL")
123
+ - Verify replay URLs in test output
124
+
125
+ ## Examples
126
+
127
+ ### Basic Test with Comment
128
+
129
+ ```javascript
130
+ it("should login successfully", async (context) => {
131
+ const testdriver = TestDriver(context, { headless: true });
132
+
133
+ await testdriver.provision.chrome({
134
+ url: 'https://your-app.com/login',
135
+ });
136
+
137
+ // Test steps...
138
+ const result = await testdriver.assert("I'm logged in");
139
+ expect(result).toBeTruthy();
140
+
141
+ // Dashcam automatically recorded and will appear in GitHub comment!
142
+ });
143
+ ```
144
+
145
+ ### Local Testing
146
+
147
+ Run locally without posting comments:
148
+
149
+ ```bash
150
+ npm run test:sdk
151
+ ```
152
+
153
+ Run locally WITH comment posting (requires token):
154
+
155
+ ```bash
156
+ GITHUB_TOKEN=ghp_xxx GITHUB_PR_NUMBER=123 npm run test:sdk
157
+ ```
158
+
159
+ ## Support
160
+
161
+ - **Documentation:** [testdriver.ai/docs](https://testdriver.ai/docs)
162
+ - **Issues:** [GitHub Issues](https://github.com/testdriverai/testdriverai/issues)
163
+ - **Discord:** [Join our community](https://discord.gg/testdriver)
164
+
165
+ ---
166
+
167
+ Made with ❤️ by the TestDriver team
@@ -0,0 +1,84 @@
1
+ # Quick Start: GitHub Comments
2
+
3
+ ## For GitHub Actions (Easiest!)
4
+
5
+ Add this to your `.github/workflows/test.yml`:
6
+
7
+ ```yaml
8
+ name: Tests
9
+
10
+ on: pull_request
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ contents: read
17
+ pull-requests: write # ← This is all you need!
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Setup Node
23
+ uses: actions/setup-node@v4
24
+ with:
25
+ node-version: '20'
26
+
27
+ - run: npm ci
28
+
29
+ - name: Run TestDriver tests
30
+ env:
31
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
32
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Auto-provided
33
+ run: vitest run
34
+ ```
35
+
36
+ That's it! TestDriver will automatically:
37
+ - ✅ Detect the PR number
38
+ - ✅ Detect the repository
39
+ - ✅ Post beautiful comments with test results
40
+ - 🎥 Embed dashcam GIF replays
41
+ - 📊 Show pass/fail statistics
42
+ - 🔴 Display exception details
43
+
44
+ ## For Local Development
45
+
46
+ 1. **Create a GitHub Personal Access Token**
47
+ - Go to https://github.com/settings/tokens
48
+ - Click "Generate new token (classic)"
49
+ - Select scope: `repo` or `public_repo`
50
+ - Copy the token
51
+
52
+ 2. **Set environment variables**
53
+ ```bash
54
+ export GITHUB_TOKEN=ghp_your_token_here
55
+ export GITHUB_PR_NUMBER=123
56
+ vitest run
57
+ ```
58
+
59
+ ## What Gets Posted
60
+
61
+ ```markdown
62
+ # 🟢 TestDriver Test Results
63
+
64
+ **Status:** ✅ PASSED
65
+ **Duration:** 12.3s
66
+
67
+ ## 📝 Test Results
68
+ | Status | Test | Duration | Replay |
69
+ |--------|------|----------|--------|
70
+ | ✅ | Login test | 4.5s | [🎥 View](link) |
71
+
72
+ ## 🎥 Dashcam Replays
73
+ [Animated GIF embedded here]
74
+ ```
75
+
76
+ ## Disable Comments
77
+
78
+ ```bash
79
+ TESTDRIVER_SKIP_GITHUB_COMMENT=true vitest run
80
+ ```
81
+
82
+ ## Full Documentation
83
+
84
+ See [github-integration-setup.md](./github-integration-setup.md) for complete details.
@@ -0,0 +1,129 @@
1
+ # Testing GitHub Comments Feature
2
+
3
+ ## Quick Test Instructions
4
+
5
+ 1. **Ensure TD_API_KEY is set**
6
+ - Go to: https://github.com/testdriverai/testdriverai/settings/secrets/actions
7
+ - Add secret named `TD_API_KEY` with your API key from https://console.testdriver.ai/team
8
+ - If already set, you're good to go!
9
+
10
+ 2. **Create a test branch and PR**
11
+ ```bash
12
+ cd /Users/ianjennings/Development/testdriverai
13
+ git checkout -b test-github-comments
14
+
15
+ # Make a small change to trigger the workflow
16
+ echo "# Test GitHub Comments" >> test-comment.md
17
+ git add test-comment.md
18
+ git commit -m "test: trigger GitHub comment workflow"
19
+ git push origin test-github-comments
20
+ ```
21
+
22
+ 3. **Create Pull Request**
23
+ ```bash
24
+ gh pr create --title "Test: GitHub Comments Feature" \
25
+ --body "Testing automatic GitHub comments with test results and dashcam replays"
26
+ ```
27
+
28
+ Or create via web: https://github.com/testdriverai/testdriverai/compare
29
+
30
+ 4. **Watch the Magic Happen! ✨**
31
+ - The workflow will automatically run: `.github/workflows/test-with-comments.yml`
32
+ - View progress at: https://github.com/testdriverai/testdriverai/actions
33
+ - After ~30-60 seconds, you'll see a comment on your PR with:
34
+ - ✅ Test results summary
35
+ - 🎥 Embedded dashcam GIF replay
36
+ - 📊 Test statistics
37
+ - 📋 Link to full test run
38
+
39
+ ## What the Test Does
40
+
41
+ The workflow runs `examples/assert.test.mjs` which:
42
+ - Provisions a Chrome browser
43
+ - Navigates to https://saucedemo.com
44
+ - Performs login actions
45
+ - Uses TestDriver's `assert()` to verify elements
46
+ - Records a dashcam replay of the entire test
47
+ - Posts results to your PR automatically
48
+
49
+ ## Expected Comment Output
50
+
51
+ You should see a comment like:
52
+
53
+ ```markdown
54
+ # 🟢 TestDriver Test Results
55
+
56
+ **Status:** ✅ PASSED
57
+ **Duration:** 25.3s
58
+ **Platform:** linux
59
+ **Branch:** `test-github-comments`
60
+ **Commit:** `abc1234`
61
+
62
+ ## 📊 Test Summary
63
+
64
+ Total: 1
65
+ Passed: 1 ✅
66
+ Failed: 0 ❌
67
+ Skipped: 0 ⏭️
68
+
69
+ ### [📋 View Full Test Run](https://console.testdriver.ai/runs/...)
70
+
71
+ ## 📝 Test Results
72
+
73
+ | Status | Test | File | Duration | Replay |
74
+ |--------|------|------|----------|--------|
75
+ | ✅ | Assert Test | `examples/assert.test.mjs` | 25.3s | [🎥 View](https://console.testdriver.ai/replay/...) |
76
+
77
+ ## 🎥 Dashcam Replays
78
+
79
+ ### Assert Test
80
+
81
+ [![Assert Test](https://console.testdriver.ai/api/replay/.../gif)](https://console.testdriver.ai/replay/...)
82
+
83
+ [🎬 View Full Replay](https://console.testdriver.ai/replay/...)
84
+ ```
85
+
86
+ ## Troubleshooting
87
+
88
+ ### No comment appears
89
+ - Check Actions tab for errors: https://github.com/testdriverai/testdriverai/actions
90
+ - Verify `TD_API_KEY` secret is set correctly
91
+ - Ensure workflow has `pull-requests: write` permission (it does in the provided workflow)
92
+
93
+ ### Workflow doesn't run
94
+ - Make sure the workflow file is on the branch you're testing
95
+ - Check that PR is from the same repository (not a fork)
96
+
97
+ ### Test fails
98
+ - View the workflow logs for details
99
+ - Check TestDriver API status
100
+ - Verify your API key is valid
101
+
102
+ ## Manual Trigger
103
+
104
+ You can also trigger the workflow manually:
105
+ 1. Go to: https://github.com/testdriverai/testdriverai/actions/workflows/test-with-comments.yml
106
+ 2. Click "Run workflow"
107
+ 3. Select your branch
108
+ 4. Click "Run workflow"
109
+
110
+ Note: Manual triggers won't post PR comments (no PR context), but will still run tests.
111
+
112
+ ## Clean Up
113
+
114
+ After testing, delete the test branch:
115
+ ```bash
116
+ gh pr close YOUR_PR_NUMBER
117
+ git checkout main
118
+ git branch -D test-github-comments
119
+ git push origin --delete test-github-comments
120
+ rm test-comment.md # if it exists on main
121
+ ```
122
+
123
+ ## Next Steps
124
+
125
+ Once you've confirmed it works:
126
+ 1. Customize the workflow for your needs
127
+ 2. Add more test files to the run command
128
+ 3. Set up for all PRs in your repository
129
+ 4. Share with your team!
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
6
+ /**
7
+ * Script to generate MCP skills from docs/v7/*.mdx files
8
+ *
9
+ * This script reads the frontmatter from each mdx file and generates
10
+ * SKILL.md files in the skills/ output directory.
11
+ */
12
+
13
+ const DOCS_DIR = path.join(__dirname, "../v7");
14
+ const OUTPUT_DIR = path.join(__dirname, "../../skills");
15
+
16
+ // Parse YAML frontmatter from mdx content
17
+ function parseFrontmatter(content) {
18
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
19
+ if (!frontmatterMatch) {
20
+ return { frontmatter: {}, body: content };
21
+ }
22
+
23
+ const frontmatterText = frontmatterMatch[1];
24
+ const body = content.slice(frontmatterMatch[0].length).trim();
25
+
26
+ // Simple YAML parser for our use case
27
+ const frontmatter = {};
28
+ const lines = frontmatterText.split("\n");
29
+ for (const line of lines) {
30
+ const match = line.match(/^(\w+):\s*"?([^"]*)"?\s*$/);
31
+ if (match) {
32
+ frontmatter[match[1]] = match[2];
33
+ }
34
+ }
35
+
36
+ return { frontmatter, body };
37
+ }
38
+
39
+ // Get skill name from filename
40
+ function getSkillName(filename) {
41
+ return `testdriver:${filename.replace(".mdx", "")}`;
42
+ }
43
+
44
+ // Generate SKILL.md content
45
+ function generateSkillContent(filename, frontmatter, body) {
46
+ const skillName = getSkillName(filename);
47
+ const description = frontmatter.description || frontmatter.sidebarTitle || filename.replace(".mdx", "");
48
+
49
+ return `---
50
+ name: ${skillName}
51
+ description: ${description}
52
+ ---
53
+ <!-- Generated from ${filename}. DO NOT EDIT. -->
54
+
55
+ ${body}
56
+ `;
57
+ }
58
+
59
+ // Process all mdx files
60
+ function processFiles() {
61
+ // Ensure output directory exists
62
+ if (!fs.existsSync(OUTPUT_DIR)) {
63
+ fs.mkdirSync(OUTPUT_DIR, { recursive: true });
64
+ }
65
+
66
+ const files = fs.readdirSync(DOCS_DIR);
67
+ const mdxFiles = files.filter(
68
+ (file) => file.endsWith(".mdx") && !file.startsWith("_")
69
+ );
70
+
71
+ console.log(`Found ${mdxFiles.length} mdx files to process\n`);
72
+
73
+ let generated = 0;
74
+ let errors = 0;
75
+
76
+ for (const file of mdxFiles) {
77
+ const filePath = path.join(DOCS_DIR, file);
78
+ const skillName = getSkillName(file);
79
+ const outputDir = path.join(OUTPUT_DIR, skillName);
80
+ const outputPath = path.join(outputDir, "SKILL.md");
81
+
82
+ try {
83
+ const content = fs.readFileSync(filePath, "utf-8");
84
+ const { frontmatter, body } = parseFrontmatter(content);
85
+ const skillContent = generateSkillContent(file, frontmatter, body);
86
+
87
+ // Create skill directory
88
+ if (!fs.existsSync(outputDir)) {
89
+ fs.mkdirSync(outputDir, { recursive: true });
90
+ }
91
+
92
+ fs.writeFileSync(outputPath, skillContent, "utf-8");
93
+ console.log(`✅ ${skillName}`);
94
+ generated++;
95
+ } catch (error) {
96
+ console.error(`❌ ${file}: ${error.message}`);
97
+ errors++;
98
+ }
99
+ }
100
+
101
+ return { generated, errors };
102
+ }
103
+
104
+ // Main function
105
+ function main() {
106
+ console.log("🚀 Generating MCP skills from docs/v7/*.mdx files...\n");
107
+ console.log(`📂 Source: ${DOCS_DIR}`);
108
+ console.log(`📂 Output: ${OUTPUT_DIR}\n`);
109
+
110
+ const { generated, errors } = processFiles();
111
+
112
+ console.log(`\n✨ Complete!`);
113
+ console.log(` Generated: ${generated} skills`);
114
+ if (errors > 0) {
115
+ console.log(` Errors: ${errors}`);
116
+ }
117
+ console.log(`\nSkills written to: ${OUTPUT_DIR}`);
118
+ }
119
+
120
+ // Handle command line arguments
121
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
122
+ console.log(`
123
+ MCP Skills Generator
124
+
125
+ Usage: node generate-skills.js [options]
126
+
127
+ Options:
128
+ --help, -h Show this help message
129
+
130
+ Description:
131
+ This script generates MCP skill files from the docs/v7/*.mdx documentation.
132
+
133
+ Each .mdx file is converted to a SKILL.md file with:
134
+ - name: testdriver:<filename>
135
+ - description: from frontmatter
136
+ - Content: the mdx body
137
+
138
+ Output is written to the skills/ directory.
139
+ `);
140
+ process.exit(0);
141
+ }
142
+
143
+ // Run the script
144
+ try {
145
+ main();
146
+ } catch (error) {
147
+ console.error("❌ Error:", error.message);
148
+ process.exit(1);
149
+ }
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
6
+ /**
7
+ * Script to replace command references in Mintlify docs with proper links
8
+ *
9
+ * This script finds instances of command names like `hover-text`, `wait-for-text`, etc.
10
+ * and replaces them with proper Mintlify links to their documentation pages.
11
+ */
12
+
13
+ // Get all command files from the commands directory
14
+ function getCommandNames() {
15
+ const commandsDir = path.join(__dirname, "../", "commands");
16
+
17
+ if (!fs.existsSync(commandsDir)) {
18
+ console.error("Commands directory not found:", commandsDir);
19
+ process.exit(1);
20
+ }
21
+
22
+ const files = fs.readdirSync(commandsDir);
23
+ const commands = files
24
+ .filter((file) => file.endsWith(".mdx"))
25
+ .map((file) => file.replace(".mdx", ""));
26
+
27
+ console.log("Found commands:", commands);
28
+ return commands;
29
+ }
30
+
31
+ // Process a single file
32
+ function processFile(filePath, commands) {
33
+ const content = fs.readFileSync(filePath, "utf-8");
34
+ let modified = content;
35
+ let changes = 0;
36
+
37
+ commands.forEach((command) => {
38
+ // Create regex pattern to match `command-name` but not already linked commands
39
+ // This pattern looks for backtick-wrapped command names that are NOT:
40
+ // 1. Already inside a link: [` or preceded by ]( or ](/
41
+ // 2. Part of an existing link structure
42
+ const pattern = new RegExp(
43
+ `(?<!\\[)\`(${command.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")})\`(?!\\]\\(|\\)\\]|\\]\\(/commands/)`,
44
+ "g",
45
+ );
46
+
47
+ const replacement = `[\`$1\`](/commands/$1)`;
48
+ const newContent = modified.replace(pattern, replacement);
49
+
50
+ if (newContent !== modified) {
51
+ const matchCount = (modified.match(pattern) || []).length;
52
+ console.log(` - Replaced ${matchCount} instances of \`${command}\``);
53
+ changes += matchCount;
54
+ modified = newContent;
55
+ }
56
+ });
57
+
58
+ return { content: modified, changes };
59
+ }
60
+
61
+ // Process all .mdx files in a directory recursively
62
+ function processDirectory(dirPath, commands, exclude = []) {
63
+ const items = fs.readdirSync(dirPath);
64
+ let totalChanges = 0;
65
+
66
+ items.forEach((item) => {
67
+ const itemPath = path.join(dirPath, item);
68
+ const relativePath = path.relative(process.cwd(), itemPath);
69
+
70
+ // Skip excluded directories
71
+ if (exclude.some((ex) => relativePath.includes(ex))) {
72
+ return;
73
+ }
74
+
75
+ const stat = fs.statSync(itemPath);
76
+
77
+ if (stat.isDirectory()) {
78
+ totalChanges += processDirectory(itemPath, commands, exclude);
79
+ } else if (item.endsWith(".mdx")) {
80
+ console.log(`Processing: ${relativePath}`);
81
+ const result = processFile(itemPath, commands);
82
+
83
+ if (result.changes > 0) {
84
+ fs.writeFileSync(itemPath, result.content, "utf-8");
85
+ console.log(` ✅ Updated with ${result.changes} changes`);
86
+ totalChanges += result.changes;
87
+ } else {
88
+ console.log(` ⏭️ No changes needed`);
89
+ }
90
+ }
91
+ });
92
+
93
+ return totalChanges;
94
+ }
95
+
96
+ // Main function
97
+ function main() {
98
+ console.log("🚀 Starting TestDriver AI docs link replacer...\n");
99
+
100
+ // Get command names from the commands directory
101
+ const commands = getCommandNames();
102
+
103
+ if (commands.length === 0) {
104
+ console.log("No commands found. Exiting.");
105
+ return;
106
+ }
107
+
108
+ console.log(`\n📝 Processing documentation files...\n`);
109
+
110
+ // Process all .mdx files in the docs directory, excluding the commands directory itself
111
+ const docsDir = path.join(__dirname, "../");
112
+ const exclude = ["commands"]; // Don't modify the command docs themselves
113
+
114
+ const totalChanges = processDirectory(docsDir, commands, exclude);
115
+
116
+ console.log(`\n✨ Complete! Made ${totalChanges} total replacements.`);
117
+
118
+ if (totalChanges > 0) {
119
+ console.log("\n📋 Summary:");
120
+ console.log(
121
+ "- Command references like `hover-text` have been replaced with [`hover-text`](/commands/hover-text)",
122
+ );
123
+ console.log("- Only changed files that needed updates");
124
+ console.log(
125
+ "- Excluded the /commands directory to avoid self-referencing issues",
126
+ );
127
+ console.log("\nYou may want to review the changes before committing.");
128
+ } else {
129
+ console.log("\n🎉 All files are already properly linked!");
130
+ }
131
+ }
132
+
133
+ // Handle command line arguments
134
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
135
+ console.log(`
136
+ TestDriver AI Documentation Link Replacer
137
+
138
+ Usage: node link-replacer.js [options]
139
+
140
+ Options:
141
+ --help, -h Show this help message
142
+ --dry-run Show what would be changed without making actual changes (TODO)
143
+
144
+ Description:
145
+ This script finds command references like \`hover-text\` in your Mintlify
146
+ documentation and replaces them with proper links to the command reference
147
+ pages like [\`hover-text\`](/commands/hover-text).
148
+
149
+ The script:
150
+ - Scans all .mdx files in the /docs directory
151
+ - Excludes the /commands directory to avoid self-references
152
+ - Only replaces \`command-name\` patterns that aren't already linked
153
+ - Preserves existing links and formatting
154
+ `);
155
+ process.exit(0);
156
+ }
157
+
158
+ // Run the script
159
+ try {
160
+ main();
161
+ } catch (error) {
162
+ console.error("❌ Error:", error.message);
163
+ process.exit(1);
164
+ }