@testdriverai/agent 7.8.0-canary.10

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 (528) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +4 -0
  3. package/.prettierignore +4 -0
  4. package/.prettierrc +1 -0
  5. package/CHANGELOG.md +953 -0
  6. package/README.md +81 -0
  7. package/agent/events.js +135 -0
  8. package/agent/index.js +2450 -0
  9. package/agent/interface.js +35 -0
  10. package/agent/lib/analytics.js +22 -0
  11. package/agent/lib/censorship.js +75 -0
  12. package/agent/lib/commander.js +246 -0
  13. package/agent/lib/commands.js +1684 -0
  14. package/agent/lib/config.js +60 -0
  15. package/agent/lib/generator.js +91 -0
  16. package/agent/lib/http.js +144 -0
  17. package/agent/lib/logger.js +56 -0
  18. package/agent/lib/outputs.js +29 -0
  19. package/agent/lib/parser.js +209 -0
  20. package/agent/lib/redraw.js +386 -0
  21. package/agent/lib/resources/cursor-2.png +0 -0
  22. package/agent/lib/sandbox.js +1104 -0
  23. package/agent/lib/sdk.js +633 -0
  24. package/agent/lib/session.js +25 -0
  25. package/agent/lib/source-mapper.js +342 -0
  26. package/agent/lib/subimage/index.js +77 -0
  27. package/agent/lib/subimage/opencv.js +69 -0
  28. package/agent/lib/system.js +204 -0
  29. package/agent/lib/theme.js +14 -0
  30. package/agent/lib/valid-version.js +21 -0
  31. package/agent/lib/validation.js +169 -0
  32. package/ai/.claude-plugin/plugin.json +9 -0
  33. package/ai/agents/testdriver.md +638 -0
  34. package/ai/skills/testdriver-ai/SKILL.md +204 -0
  35. package/ai/skills/testdriver-assert/SKILL.md +315 -0
  36. package/ai/skills/testdriver-aws-setup/SKILL.md +448 -0
  37. package/ai/skills/testdriver-cache/SKILL.md +221 -0
  38. package/ai/skills/testdriver-caching/SKILL.md +124 -0
  39. package/ai/skills/testdriver-captcha/SKILL.md +158 -0
  40. package/ai/skills/testdriver-ci-cd/SKILL.md +602 -0
  41. package/ai/skills/testdriver-click/SKILL.md +286 -0
  42. package/ai/skills/testdriver-client/SKILL.md +477 -0
  43. package/ai/skills/testdriver-cloud/SKILL.md +119 -0
  44. package/ai/skills/testdriver-customizing-devices/SKILL.md +319 -0
  45. package/ai/skills/testdriver-dashcam/SKILL.md +418 -0
  46. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +401 -0
  47. package/ai/skills/testdriver-device-config/SKILL.md +317 -0
  48. package/ai/skills/testdriver-double-click/SKILL.md +102 -0
  49. package/ai/skills/testdriver-elements/SKILL.md +605 -0
  50. package/ai/skills/testdriver-enterprise/SKILL.md +114 -0
  51. package/ai/skills/testdriver-errors/SKILL.md +246 -0
  52. package/ai/skills/testdriver-events/SKILL.md +356 -0
  53. package/ai/skills/testdriver-examples/SKILL.md +7 -0
  54. package/ai/skills/testdriver-exec/SKILL.md +317 -0
  55. package/ai/skills/testdriver-find/SKILL.md +829 -0
  56. package/ai/skills/testdriver-focus-application/SKILL.md +293 -0
  57. package/ai/skills/testdriver-generating-tests/SKILL.md +36 -0
  58. package/ai/skills/testdriver-hover/SKILL.md +278 -0
  59. package/ai/skills/testdriver-locating-elements/SKILL.md +71 -0
  60. package/ai/skills/testdriver-making-assertions/SKILL.md +32 -0
  61. package/ai/skills/testdriver-mcp/SKILL.md +7 -0
  62. package/ai/skills/testdriver-mcp-workflow/SKILL.md +410 -0
  63. package/ai/skills/testdriver-mouse-down/SKILL.md +161 -0
  64. package/ai/skills/testdriver-mouse-up/SKILL.md +164 -0
  65. package/ai/skills/testdriver-parse/SKILL.md +236 -0
  66. package/ai/skills/testdriver-performing-actions/SKILL.md +54 -0
  67. package/ai/skills/testdriver-press-keys/SKILL.md +348 -0
  68. package/ai/skills/testdriver-provision/SKILL.md +331 -0
  69. package/ai/skills/testdriver-quickstart/SKILL.md +144 -0
  70. package/ai/skills/testdriver-redraw/SKILL.md +214 -0
  71. package/ai/skills/testdriver-reusable-code/SKILL.md +249 -0
  72. package/ai/skills/testdriver-right-click/SKILL.md +123 -0
  73. package/ai/skills/testdriver-running-tests/SKILL.md +185 -0
  74. package/ai/skills/testdriver-screenshot/SKILL.md +248 -0
  75. package/ai/skills/testdriver-screenshots/SKILL.md +184 -0
  76. package/ai/skills/testdriver-scroll/SKILL.md +335 -0
  77. package/ai/skills/testdriver-secrets/SKILL.md +115 -0
  78. package/ai/skills/testdriver-self-hosted/SKILL.md +65 -0
  79. package/ai/skills/testdriver-test-writer/SKILL.md +448 -0
  80. package/ai/skills/testdriver-testdriver/SKILL.md +628 -0
  81. package/ai/skills/testdriver-testdriver-mechanic/SKILL.md +165 -0
  82. package/ai/skills/testdriver-type/SKILL.md +357 -0
  83. package/ai/skills/testdriver-variables/SKILL.md +111 -0
  84. package/ai/skills/testdriver-wait/SKILL.md +50 -0
  85. package/ai/skills/testdriver-waiting-for-elements/SKILL.md +90 -0
  86. package/ai/skills/testdriver-what-is-testdriver/SKILL.md +54 -0
  87. package/bin/testdriverai.js +22 -0
  88. package/debugger/bg.png +0 -0
  89. package/debugger/icon.png +0 -0
  90. package/debugger/index.html +469 -0
  91. package/debugger/td.png +0 -0
  92. package/debugger/tray-buffered.png +0 -0
  93. package/debugger/tray.png +0 -0
  94. package/docs/GITHUB_COMMENTS.md +330 -0
  95. package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
  96. package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
  97. package/docs/TEST-GITHUB-COMMENTS.md +129 -0
  98. package/docs/_data/examples-manifest.json +177 -0
  99. package/docs/_data/examples-manifest.schema.json +41 -0
  100. package/docs/_scripts/extract-example-urls.js +165 -0
  101. package/docs/_scripts/generate-examples.js +560 -0
  102. package/docs/_scripts/generate-skills.js +154 -0
  103. package/docs/_scripts/link-replacer.js +164 -0
  104. package/docs/_scripts/upload-docs-to-openai.js +284 -0
  105. package/docs/changelog.mdx +161 -0
  106. package/docs/claude-mcp-plugin.mdx +160 -0
  107. package/docs/docs.json +442 -0
  108. package/docs/github-integration-setup.md +266 -0
  109. package/docs/guide/best-practices-polling.mdx +174 -0
  110. package/docs/images/content/account/newprojectsettings.png +0 -0
  111. package/docs/images/content/account/projectpage.png +0 -0
  112. package/docs/images/content/account/projectreplays.png +0 -0
  113. package/docs/images/content/account/team-manage.png +0 -0
  114. package/docs/images/content/account/teampage.png +0 -0
  115. package/docs/images/content/extension/cursor.svg +1 -0
  116. package/docs/images/content/extension/vscode.svg +57 -0
  117. package/docs/images/content/extension/windsurf.svg +3 -0
  118. package/docs/images/content/parse/output.png +0 -0
  119. package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
  120. package/docs/images/content/side-by-side.png +0 -0
  121. package/docs/images/content/vscode/ide-full.png +0 -0
  122. package/docs/images/content/vscode/running.png +0 -0
  123. package/docs/images/content/vscode/v7-chat.png +0 -0
  124. package/docs/images/content/vscode/v7-choose-agent.png +0 -0
  125. package/docs/images/content/vscode/v7-full.png +0 -0
  126. package/docs/images/content/vscode/v7-onboarding.png +0 -0
  127. package/docs/images/content/vscode/vscode-2-assert.png +0 -0
  128. package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
  129. package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
  130. package/docs/images/content/vscode/vscode-file-creation.png +0 -0
  131. package/docs/images/content/vscode/vscode-install.png +0 -0
  132. package/docs/images/content/vscode/vscode-overview.png +0 -0
  133. package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
  134. package/docs/images/content/vscode/vscode-stopchat.png +0 -0
  135. package/docs/images/content/vscode/vscode-stoptest.png +0 -0
  136. package/docs/images/content/vscode/vscode-tdservice.png +0 -0
  137. package/docs/images/content/vscode/vscode-test-output.png +0 -0
  138. package/docs/images/content/vscode/vscode-testhistory.png +0 -0
  139. package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
  140. package/docs/images/content/vscode/vscode-testpane.png +0 -0
  141. package/docs/images/template/dark.png +0 -0
  142. package/docs/images/template/icon.png +0 -0
  143. package/docs/images/template/light.png +0 -0
  144. package/docs/snippets/calendar-link.mdx +4 -0
  145. package/docs/snippets/gitignore-warning.mdx +7 -0
  146. package/docs/snippets/lifecycle-warning.mdx +6 -0
  147. package/docs/snippets/test-prereqs.mdx +12 -0
  148. package/docs/snippets/tests/assert-replay.mdx +7 -0
  149. package/docs/snippets/tests/assert-yaml.mdx +8 -0
  150. package/docs/snippets/tests/exec-js-replay.mdx +7 -0
  151. package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
  152. package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
  153. package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
  154. package/docs/snippets/tests/hover-image-replay.mdx +7 -0
  155. package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
  156. package/docs/snippets/tests/hover-text-replay.mdx +7 -0
  157. package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
  158. package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
  159. package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
  160. package/docs/snippets/tests/match-image-replay.mdx +7 -0
  161. package/docs/snippets/tests/match-image-yaml.mdx +17 -0
  162. package/docs/snippets/tests/press-keys-replay.mdx +7 -0
  163. package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
  164. package/docs/snippets/tests/remember-replay.mdx +7 -0
  165. package/docs/snippets/tests/remember-yaml.mdx +28 -0
  166. package/docs/snippets/tests/scroll-replay.mdx +7 -0
  167. package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
  168. package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
  169. package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
  170. package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
  171. package/docs/snippets/tests/scroll-yaml.mdx +30 -0
  172. package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
  173. package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
  174. package/docs/snippets/tests/type-replay.mdx +7 -0
  175. package/docs/snippets/tests/type-yaml.mdx +28 -0
  176. package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
  177. package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
  178. package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
  179. package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
  180. package/docs/snippets/tests/wait-replay.mdx +7 -0
  181. package/docs/snippets/tests/wait-yaml.mdx +13 -0
  182. package/docs/styles.css +65 -0
  183. package/docs/v6/account/dashboard.mdx +16 -0
  184. package/docs/v6/account/enterprise.mdx +110 -0
  185. package/docs/v6/account/pricing.mdx +33 -0
  186. package/docs/v6/account/projects.mdx +33 -0
  187. package/docs/v6/account/team.mdx +35 -0
  188. package/docs/v6/action/ami.mdx +109 -0
  189. package/docs/v6/action/performance.mdx +105 -0
  190. package/docs/v6/action/secrets.mdx +93 -0
  191. package/docs/v6/apps/chrome-extensions.mdx +48 -0
  192. package/docs/v6/apps/desktop-apps.mdx +93 -0
  193. package/docs/v6/apps/mobile-apps.mdx +26 -0
  194. package/docs/v6/apps/static-websites.mdx +54 -0
  195. package/docs/v6/apps/tauri-apps.mdx +361 -0
  196. package/docs/v6/bugs/jira.mdx +232 -0
  197. package/docs/v6/cli/overview.mdx +66 -0
  198. package/docs/v6/commands/assert.mdx +45 -0
  199. package/docs/v6/commands/exec.mdx +276 -0
  200. package/docs/v6/commands/focus-application.mdx +44 -0
  201. package/docs/v6/commands/hover-image.mdx +69 -0
  202. package/docs/v6/commands/hover-text.mdx +47 -0
  203. package/docs/v6/commands/if.mdx +53 -0
  204. package/docs/v6/commands/match-image.mdx +67 -0
  205. package/docs/v6/commands/press-keys.mdx +87 -0
  206. package/docs/v6/commands/remember.mdx +49 -0
  207. package/docs/v6/commands/run.mdx +44 -0
  208. package/docs/v6/commands/scroll-until-image.mdx +66 -0
  209. package/docs/v6/commands/scroll-until-text.mdx +60 -0
  210. package/docs/v6/commands/scroll.mdx +69 -0
  211. package/docs/v6/commands/type.mdx +45 -0
  212. package/docs/v6/commands/wait-for-image.mdx +54 -0
  213. package/docs/v6/commands/wait-for-text.mdx +48 -0
  214. package/docs/v6/commands/wait.mdx +45 -0
  215. package/docs/v6/exporting/junit.mdx +218 -0
  216. package/docs/v6/exporting/playwright.mdx +197 -0
  217. package/docs/v6/features/auto-healing.mdx +144 -0
  218. package/docs/v6/features/generation.mdx +116 -0
  219. package/docs/v6/features/parallel-testing.mdx +151 -0
  220. package/docs/v6/features/reusable-snippets.mdx +131 -0
  221. package/docs/v6/features/selectorless.mdx +80 -0
  222. package/docs/v6/features/visual-assertions.mdx +139 -0
  223. package/docs/v6/getting-started/ci.mdx +146 -0
  224. package/docs/v6/getting-started/cli.mdx +91 -0
  225. package/docs/v6/getting-started/editing.mdx +100 -0
  226. package/docs/v6/getting-started/playwright.mdx +342 -0
  227. package/docs/v6/getting-started/running.mdx +48 -0
  228. package/docs/v6/getting-started/self-hosting.mdx +408 -0
  229. package/docs/v6/getting-started/vscode.mdx +88 -0
  230. package/docs/v6/guide/assertions.mdx +189 -0
  231. package/docs/v6/guide/authentication.mdx +136 -0
  232. package/docs/v6/guide/code.mdx +65 -0
  233. package/docs/v6/guide/dashcam.mdx +118 -0
  234. package/docs/v6/guide/environment-variables.mdx +26 -0
  235. package/docs/v6/guide/lifecycle.mdx +242 -0
  236. package/docs/v6/guide/locating.mdx +141 -0
  237. package/docs/v6/guide/protips.mdx +43 -0
  238. package/docs/v6/guide/variables.mdx +143 -0
  239. package/docs/v6/guide/waiting.mdx +130 -0
  240. package/docs/v6/importing/csv.mdx +196 -0
  241. package/docs/v6/importing/gherkin.mdx +143 -0
  242. package/docs/v6/importing/jira.mdx +164 -0
  243. package/docs/v6/importing/testrail.mdx +162 -0
  244. package/docs/v6/integrations/electron.mdx +146 -0
  245. package/docs/v6/integrations/netlify.mdx +100 -0
  246. package/docs/v6/integrations/vercel.mdx +125 -0
  247. package/docs/v6/interactive/explore.mdx +99 -0
  248. package/docs/v6/interactive/run.mdx +52 -0
  249. package/docs/v6/interactive/save.mdx +63 -0
  250. package/docs/v6/overview/comparison.mdx +101 -0
  251. package/docs/v6/overview/faq.mdx +162 -0
  252. package/docs/v6/overview/performance.mdx +52 -0
  253. package/docs/v6/overview/quickstart.mdx +137 -0
  254. package/docs/v6/overview/what-is-testdriver.mdx +85 -0
  255. package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
  256. package/docs/v6/scenarios/cookie-banner.mdx +32 -0
  257. package/docs/v6/scenarios/file-upload.mdx +33 -0
  258. package/docs/v6/scenarios/form-filling.mdx +32 -0
  259. package/docs/v6/scenarios/log-in.mdx +75 -0
  260. package/docs/v6/scenarios/pdf-generation.mdx +25 -0
  261. package/docs/v6/scenarios/spell-check.mdx +22 -0
  262. package/docs/v6/security/action.mdx +84 -0
  263. package/docs/v6/security/agent.mdx +73 -0
  264. package/docs/v6/security/platform.mdx +77 -0
  265. package/docs/v6/tutorials/advanced-test.mdx +81 -0
  266. package/docs/v6/tutorials/basic-test.mdx +45 -0
  267. package/docs/v7/_drafts/agents.mdx +843 -0
  268. package/docs/v7/_drafts/architecture.mdx +399 -0
  269. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  270. package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
  271. package/docs/v7/_drafts/best-practices.mdx +486 -0
  272. package/docs/v7/_drafts/caching-ai.mdx +215 -0
  273. package/docs/v7/_drafts/caching-selectors.mdx +424 -0
  274. package/docs/v7/_drafts/caching.mdx +366 -0
  275. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
  276. package/docs/v7/_drafts/commands/assert.mdx +45 -0
  277. package/docs/v7/_drafts/commands/exec.mdx +276 -0
  278. package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
  279. package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
  280. package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
  281. package/docs/v7/_drafts/commands/if.mdx +53 -0
  282. package/docs/v7/_drafts/commands/match-image.mdx +67 -0
  283. package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
  284. package/docs/v7/_drafts/commands/remember.mdx +49 -0
  285. package/docs/v7/_drafts/commands/run.mdx +44 -0
  286. package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
  287. package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
  288. package/docs/v7/_drafts/commands/scroll.mdx +69 -0
  289. package/docs/v7/_drafts/commands/type.mdx +45 -0
  290. package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
  291. package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
  292. package/docs/v7/_drafts/commands/wait.mdx +45 -0
  293. package/docs/v7/_drafts/configuration.mdx +378 -0
  294. package/docs/v7/_drafts/contributing.mdx +174 -0
  295. package/docs/v7/_drafts/core.mdx +458 -0
  296. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  297. package/docs/v7/_drafts/debugging.mdx +349 -0
  298. package/docs/v7/_drafts/error-handling.mdx +501 -0
  299. package/docs/v7/_drafts/faq.mdx +393 -0
  300. package/docs/v7/_drafts/hooks.mdx +360 -0
  301. package/docs/v7/_drafts/init-command.mdx +95 -0
  302. package/docs/v7/_drafts/installation.mdx +420 -0
  303. package/docs/v7/_drafts/migration.mdx +562 -0
  304. package/docs/v7/_drafts/observable.mdx +604 -0
  305. package/docs/v7/_drafts/playwright.mdx +342 -0
  306. package/docs/v7/_drafts/plugin-migration.mdx +220 -0
  307. package/docs/v7/_drafts/powerful.mdx +419 -0
  308. package/docs/v7/_drafts/presets.mdx +210 -0
  309. package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
  310. package/docs/v7/_drafts/prompt-cache.mdx +200 -0
  311. package/docs/v7/_drafts/provision.mdx +390 -0
  312. package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
  313. package/docs/v7/_drafts/readme.mdx +135 -0
  314. package/docs/v7/_drafts/reports.mdx +414 -0
  315. package/docs/v7/_drafts/scalable.mdx +763 -0
  316. package/docs/v7/_drafts/screenshot.mdx +155 -0
  317. package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
  318. package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
  319. package/docs/v7/_drafts/sdk-migration.mdx +474 -0
  320. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  321. package/docs/v7/_drafts/self-hosting.mdx +369 -0
  322. package/docs/v7/_drafts/test-recording.mdx +382 -0
  323. package/docs/v7/_drafts/troubleshooting.mdx +526 -0
  324. package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
  325. package/docs/v7/_drafts/vitest.mdx +535 -0
  326. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  327. package/docs/v7/ai.mdx +205 -0
  328. package/docs/v7/assert.mdx +316 -0
  329. package/docs/v7/aws-setup.mdx +449 -0
  330. package/docs/v7/cache.mdx +223 -0
  331. package/docs/v7/caching.mdx +128 -0
  332. package/docs/v7/captcha.mdx +159 -0
  333. package/docs/v7/ci-cd.mdx +603 -0
  334. package/docs/v7/click.mdx +287 -0
  335. package/docs/v7/client.mdx +478 -0
  336. package/docs/v7/copilot/auto-healing.mdx +265 -0
  337. package/docs/v7/copilot/creating-tests.mdx +156 -0
  338. package/docs/v7/copilot/github.mdx +143 -0
  339. package/docs/v7/copilot/running-tests.mdx +149 -0
  340. package/docs/v7/copilot/setup.mdx +143 -0
  341. package/docs/v7/customizing-devices.mdx +319 -0
  342. package/docs/v7/dashcam.mdx +419 -0
  343. package/docs/v7/debugging-with-screenshots.mdx +402 -0
  344. package/docs/v7/device-config.mdx +317 -0
  345. package/docs/v7/double-click.mdx +102 -0
  346. package/docs/v7/elements.mdx +606 -0
  347. package/docs/v7/enterprise.mdx +9 -0
  348. package/docs/v7/errors.mdx +248 -0
  349. package/docs/v7/events.mdx +358 -0
  350. package/docs/v7/examples/ai.mdx +72 -0
  351. package/docs/v7/examples/assert.mdx +72 -0
  352. package/docs/v7/examples/captcha-api.mdx +92 -0
  353. package/docs/v7/examples/chrome-extension.mdx +132 -0
  354. package/docs/v7/examples/drag-and-drop.mdx +100 -0
  355. package/docs/v7/examples/element-not-found.mdx +67 -0
  356. package/docs/v7/examples/exec-output.mdx +85 -0
  357. package/docs/v7/examples/exec-pwsh.mdx +83 -0
  358. package/docs/v7/examples/focus-window.mdx +62 -0
  359. package/docs/v7/examples/hover-image.mdx +94 -0
  360. package/docs/v7/examples/hover-text.mdx +69 -0
  361. package/docs/v7/examples/installer.mdx +91 -0
  362. package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
  363. package/docs/v7/examples/match-image.mdx +96 -0
  364. package/docs/v7/examples/press-keys.mdx +92 -0
  365. package/docs/v7/examples/scroll-keyboard.mdx +79 -0
  366. package/docs/v7/examples/scroll-until-image.mdx +81 -0
  367. package/docs/v7/examples/scroll-until-text.mdx +109 -0
  368. package/docs/v7/examples/scroll.mdx +81 -0
  369. package/docs/v7/examples/type.mdx +92 -0
  370. package/docs/v7/examples/windows-installer.mdx +89 -0
  371. package/docs/v7/exec.mdx +318 -0
  372. package/docs/v7/find.mdx +830 -0
  373. package/docs/v7/focus-application.mdx +294 -0
  374. package/docs/v7/generating-tests.mdx +36 -0
  375. package/docs/v7/hosted.mdx +158 -0
  376. package/docs/v7/hover.mdx +279 -0
  377. package/docs/v7/locating-elements.mdx +71 -0
  378. package/docs/v7/making-assertions.mdx +32 -0
  379. package/docs/v7/mcp.mdx +9 -0
  380. package/docs/v7/mouse-down.mdx +161 -0
  381. package/docs/v7/mouse-up.mdx +164 -0
  382. package/docs/v7/parse.mdx +237 -0
  383. package/docs/v7/performing-actions.mdx +54 -0
  384. package/docs/v7/press-keys.mdx +349 -0
  385. package/docs/v7/provision.mdx +333 -0
  386. package/docs/v7/quickstart.mdx +173 -0
  387. package/docs/v7/redraw.mdx +216 -0
  388. package/docs/v7/reusable-code.mdx +249 -0
  389. package/docs/v7/right-click.mdx +123 -0
  390. package/docs/v7/running-tests.mdx +185 -0
  391. package/docs/v7/screenshot.mdx +249 -0
  392. package/docs/v7/screenshots.mdx +186 -0
  393. package/docs/v7/scroll.mdx +336 -0
  394. package/docs/v7/secrets.mdx +115 -0
  395. package/docs/v7/self-hosted.mdx +149 -0
  396. package/docs/v7/type.mdx +358 -0
  397. package/docs/v7/variables.mdx +111 -0
  398. package/docs/v7/wait.mdx +52 -0
  399. package/docs/v7/waiting-for-elements.mdx +90 -0
  400. package/docs/v7/what-is-testdriver.mdx +54 -0
  401. package/eslint.config.js +67 -0
  402. package/examples/ai.test.mjs +31 -0
  403. package/examples/assert.test.mjs +47 -0
  404. package/examples/chrome-extension.test.mjs +97 -0
  405. package/examples/config.mjs +5 -0
  406. package/examples/element-not-found.test.mjs +27 -0
  407. package/examples/exec-output.test.mjs +60 -0
  408. package/examples/exec-pwsh.test.mjs +58 -0
  409. package/examples/findall-coffee-icons.test.mjs +42 -0
  410. package/examples/focus-window.test.mjs +37 -0
  411. package/examples/formatted-logging.test.mjs +27 -0
  412. package/examples/hover-image.test.mjs +53 -0
  413. package/examples/hover-text-with-description.test.mjs +57 -0
  414. package/examples/hover-text.test.mjs +28 -0
  415. package/examples/installer.test.mjs +50 -0
  416. package/examples/launch-vscode-linux.test.mjs +55 -0
  417. package/examples/match-image.test.mjs +55 -0
  418. package/examples/parse.test.mjs +19 -0
  419. package/examples/press-keys.test.mjs +44 -0
  420. package/examples/prompt.test.mjs +34 -0
  421. package/examples/scroll-keyboard.test.mjs +38 -0
  422. package/examples/scroll-until-image.test.mjs +40 -0
  423. package/examples/scroll.test.mjs +42 -0
  424. package/examples/type.test.mjs +46 -0
  425. package/examples/windows-installer.test.mjs +54 -0
  426. package/index.js +2 -0
  427. package/interfaces/cli/commands/init.js +438 -0
  428. package/interfaces/cli/commands/setup.js +382 -0
  429. package/interfaces/cli/lib/base.js +285 -0
  430. package/interfaces/cli.js +20 -0
  431. package/interfaces/junit-reporter.js +290 -0
  432. package/interfaces/logger.js +388 -0
  433. package/interfaces/readline.js +234 -0
  434. package/interfaces/shared-test-state.mjs +64 -0
  435. package/interfaces/vitest-plugin.d.ts +115 -0
  436. package/interfaces/vitest-plugin.mjs +1698 -0
  437. package/lib/captcha/solver.js +358 -0
  438. package/lib/core/Dashcam.js +533 -0
  439. package/lib/core/index.d.ts +172 -0
  440. package/lib/core/index.js +12 -0
  441. package/lib/environments.json +18 -0
  442. package/lib/github-comment-formatter.js +263 -0
  443. package/lib/github-comment.mjs +452 -0
  444. package/lib/init-project.js +575 -0
  445. package/lib/presets/index.mjs +331 -0
  446. package/lib/resolve-channel.js +46 -0
  447. package/lib/sentry.js +417 -0
  448. package/lib/vitest/hooks.d.ts +57 -0
  449. package/lib/vitest/hooks.mjs +674 -0
  450. package/lib/vitest/setup-aws.mjs +247 -0
  451. package/lib/vitest/setup-self-hosted.mjs +151 -0
  452. package/lib/vitest/setup.mjs +46 -0
  453. package/manual/captcha-api.test.mjs +51 -0
  454. package/manual/drag-and-drop.test.mjs +59 -0
  455. package/manual/flake-diffthreshold-001.test.mjs +9 -0
  456. package/manual/flake-diffthreshold-01.test.mjs +9 -0
  457. package/manual/flake-diffthreshold-05.test.mjs +9 -0
  458. package/manual/flake-noredraw-cache.test.mjs +9 -0
  459. package/manual/flake-noredraw-nocache.test.mjs +9 -0
  460. package/manual/flake-redraw-cache.test.mjs +9 -0
  461. package/manual/flake-redraw-nocache.test.mjs +9 -0
  462. package/manual/flake-rocket-match.test.mjs +30 -0
  463. package/manual/flake-shared.mjs +51 -0
  464. package/manual/no-provision.test.mjs +31 -0
  465. package/manual/packer-hover-image.test.mjs +176 -0
  466. package/manual/scroll-until-text.test.mjs +68 -0
  467. package/manual/test-init-command.js +223 -0
  468. package/mcp-server/README.md +322 -0
  469. package/mcp-server/dist/codegen.d.ts +9 -0
  470. package/mcp-server/dist/codegen.js +165 -0
  471. package/mcp-server/dist/mcp-app.html +114 -0
  472. package/mcp-server/dist/package.json +1 -0
  473. package/mcp-server/dist/provision-types.d.ts +290 -0
  474. package/mcp-server/dist/provision-types.js +174 -0
  475. package/mcp-server/dist/server.d.ts +6 -0
  476. package/mcp-server/dist/server.mjs +1925 -0
  477. package/mcp-server/dist/session.d.ts +85 -0
  478. package/mcp-server/dist/session.js +152 -0
  479. package/mcp-server/mcp-app.html +28 -0
  480. package/mcp-server/mcp-config.example.json +19 -0
  481. package/mcp-server/package-lock.json +4027 -0
  482. package/mcp-server/package.json +31 -0
  483. package/mcp-server/src/codegen.ts +189 -0
  484. package/mcp-server/src/mcp-app.css +360 -0
  485. package/mcp-server/src/mcp-app.ts +547 -0
  486. package/mcp-server/src/provision-types.ts +209 -0
  487. package/mcp-server/src/server.ts +2391 -0
  488. package/mcp-server/src/session.ts +194 -0
  489. package/mcp-server/tsconfig.json +16 -0
  490. package/mcp-server/vite.config.ts +23 -0
  491. package/package.json +158 -0
  492. package/schema.json +1046 -0
  493. package/scripts/generate-skills.js +94 -0
  494. package/sdk-log-formatter.js +1157 -0
  495. package/sdk.d.ts +1486 -0
  496. package/sdk.js +4336 -0
  497. package/setup/aws/cloudformation.yaml +463 -0
  498. package/setup/aws/disable-defender.sh +42 -0
  499. package/setup/aws/install-dev-runner.sh +79 -0
  500. package/setup/aws/spawn-runner.sh +289 -0
  501. package/test/captcha-solver.test.mjs +152 -0
  502. package/test/chrome-remote-debugging.test.mjs +66 -0
  503. package/test/duckduckgo/experiment.test.mjs +28 -0
  504. package/test/duckduckgo/setup.test.mjs +29 -0
  505. package/test/manual/debug-locate-response.js +82 -0
  506. package/test/manual/reconnect-provision.test.mjs +49 -0
  507. package/test/manual/test-console-logs.test.mjs +42 -0
  508. package/test/manual/test-find-api.js +73 -0
  509. package/test/manual/test-init.sh +54 -0
  510. package/test/manual/test-prompt-cache.js +97 -0
  511. package/test/manual/test-provision-auth.mjs +22 -0
  512. package/test/manual/test-sandbox-render.js +29 -0
  513. package/test/manual/test-sdk-methods.js +15 -0
  514. package/test/manual/test-sdk-refactor.js +53 -0
  515. package/test/manual/test-stack-trace.mjs +57 -0
  516. package/test/manual/verify-element-api.js +89 -0
  517. package/test/manual/verify-types.js +0 -0
  518. package/test/manual-unawaited-promise.test.mjs +31 -0
  519. package/vitest.config.mjs +58 -0
  520. package/vitest.runner.config.mjs +33 -0
  521. package/vscode-extension/.vscodeignore +12 -0
  522. package/vscode-extension/README.md +94 -0
  523. package/vscode-extension/media/icon.png +0 -0
  524. package/vscode-extension/package-lock.json +4126 -0
  525. package/vscode-extension/package.json +86 -0
  526. package/vscode-extension/src/extension.ts +829 -0
  527. package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
  528. package/vscode-extension/tsconfig.json +16 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Shared test logic for popup-loading variants.
3
+ * Each variant file imports this and calls it with specific options.
4
+ */
5
+ import { describe, expect, it } from "vitest";
6
+ import { TestDriver } from "../lib/vitest/hooks.mjs";
7
+
8
+ export function popupLoadingTest(label, options = {}) {
9
+ describe(`Popup with Loading (${label})`, () => {
10
+ it("should accept cookies and wait for completion", async (context) => {
11
+ const testdriver = TestDriver(context, {
12
+ preview: 'ide',
13
+ ip: context.ip || process.env.TD_IP,
14
+ ...options,
15
+ });
16
+
17
+ await testdriver.provision.chrome({
18
+ url: "https://v0-popup-with-loading-bar.vercel.app/",
19
+ });
20
+ await testdriver.screenshot();
21
+
22
+ // Accept the cookie banner to trigger the loading process
23
+ let acceptButton = await testdriver.find("Accept All button on the cookie banner", {timeout: 10000});
24
+
25
+ if (await acceptButton.found()) {
26
+ await acceptButton.click();
27
+ } else {
28
+ console.log('no cookie banner found, proceeding without accepting cookies');
29
+ }
30
+
31
+ await testdriver.find('Start button').click();
32
+
33
+ // Wait for "All done!" to appear with 120s timeout
34
+ const allDone = await testdriver.find("All done! text or heading in a modal or popup", { timeout: 120000 });
35
+ await testdriver.screenshot();
36
+
37
+ const result = await testdriver.assert("The text 'All done!' is visible on the page");
38
+ expect(result).toBeTruthy();
39
+
40
+ // Click Continue to proceed to the image grid
41
+ await testdriver.find("Continue button in the modal").click();
42
+
43
+ // Wait for the 5x5 grid of images to fully load (up to 60s) and click the rocket
44
+ await testdriver.find("The icon of a rocket in the 5x5 grid of images", { timeout: 60000, zoom: true }).click();
45
+
46
+ // Assert the success message appears
47
+ const rocketResult = await testdriver.assert("The text 'You found the rocket!' is visible on the page");
48
+ expect(rocketResult).toBeTruthy();
49
+ });
50
+ });
51
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * TestDriver SDK - No-Provision Test with Dashcam (Vitest)
3
+ *
4
+ * Demonstrates manual dashcam control without using provision methods.
5
+ * When not using provision.chrome(), provision.vscode(), etc., you need
6
+ * to manually start and stop dashcam recording.
7
+ */
8
+
9
+ import { describe, it } from "vitest";
10
+ import { TestDriver } from "../lib/vitest/hooks.mjs";
11
+ import { getDefaults } from "./config.mjs";
12
+
13
+ describe("No-Provision with Dashcam", () => {
14
+ it("should record dashcam while asserting desktop is visible", async (context) => {
15
+ const testdriver = TestDriver(context, { ...getDefaults(context) });
16
+
17
+ // Start dashcam recording manually (provision methods do this automatically)
18
+ await testdriver.dashcam.start();
19
+
20
+ await testdriver.exec('sh', 'gedit >/dev/null 2>&1 &'); // Example command to keep the test running for a bit
21
+
22
+ await testdriver.assert('untitled document is visible');
23
+
24
+ // Stop dashcam and get the recording URL
25
+ const dashcamUrl = await testdriver.dashcam.stop();
26
+ if (dashcamUrl) {
27
+ console.log(`๐ŸŽฅ Dashcam recording: ${dashcamUrl}`);
28
+ }
29
+ });
30
+ });
31
+
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Packer AMI Integration Test
3
+ *
4
+ * Builds a fresh AMI via `packer build`, then runs the hover-image test suite
5
+ * against it. This is an end-to-end validation that a newly built runner image
6
+ * can provision a sandbox, execute commands, and interact with a browser.
7
+ *
8
+ * Usage:
9
+ * TD_API_ROOT=http://localhost:1337 \
10
+ * TD_API_KEY=<key> \
11
+ * npx vitest run examples/packer-hover-image.test.mjs
12
+ *
13
+ * The packer build takes ~25 minutes, and the hover-image test ~5-10 minutes,
14
+ * so the overall test timeout is set to 60 minutes.
15
+ *
16
+ * Set TD_SANDBOX_AMI to skip the packer build and use an existing AMI.
17
+ */
18
+
19
+ import { describe, expect, it, beforeAll, afterAll } from "vitest";
20
+ import { TestDriver } from "../lib/vitest/hooks.mjs";
21
+ import { getDefaults } from "../examples/config.mjs";
22
+ import { execSync } from "child_process";
23
+ import path from "path";
24
+ import { fileURLToPath } from "url";
25
+
26
+ const __filename = fileURLToPath(import.meta.url);
27
+ const __dirname = path.dirname(__filename);
28
+ const PACKER_DIR = path.resolve(__dirname, "../../runner/packer");
29
+
30
+ // 60 minute timeout for the entire suite (packer build + test)
31
+ const SUITE_TIMEOUT = 60 * 60 * 1000;
32
+
33
+ /**
34
+ * Build a fresh AMI using packer.
35
+ * Returns the AMI ID string (e.g. "ami-0337d8cd7cff854a4").
36
+ */
37
+ function buildAmi() {
38
+ console.log("[packer] Starting AMI build โ€” this takes ~25 minutes...");
39
+ const startTime = Date.now();
40
+
41
+ // packer build outputs "us-east-2: ami-XXXX" on the last relevant line
42
+ // Use -machine-readable for reliable parsing
43
+ const output = execSync("packer build -machine-readable .", {
44
+ cwd: PACKER_DIR,
45
+ encoding: "utf-8",
46
+ timeout: 45 * 60 * 1000, // 45 minute hard limit on packer
47
+ stdio: ["ignore", "pipe", "pipe"],
48
+ env: { ...process.env },
49
+ });
50
+
51
+ // Machine-readable output has lines like:
52
+ // timestamp,target,type,data
53
+ // ...,artifact,0,id,us-east-2:ami-XXXXXXXXXXXX
54
+ const amiMatch = output.match(/,artifact,\d+,id,[\w-]+:(ami-[a-f0-9]+)/);
55
+ if (!amiMatch) {
56
+ // Fallback: try human-readable format
57
+ const humanMatch = output.match(/[\w-]+:\s*(ami-[a-f0-9]+)/);
58
+ if (!humanMatch) {
59
+ console.error("[packer] Build output (last 2000 chars):", output.slice(-2000));
60
+ throw new Error("Failed to extract AMI ID from packer build output");
61
+ }
62
+ const elapsed = ((Date.now() - startTime) / 1000 / 60).toFixed(1);
63
+ console.log(`[packer] AMI built: ${humanMatch[1]} (${elapsed} min)`);
64
+ return humanMatch[1];
65
+ }
66
+
67
+ const amiId = amiMatch[1];
68
+ const elapsed = ((Date.now() - startTime) / 1000 / 60).toFixed(1);
69
+ console.log(`[packer] AMI built: ${amiId} (${elapsed} min)`);
70
+ return amiId;
71
+ }
72
+
73
+ /**
74
+ * Deregister an AMI and delete its backing snapshot.
75
+ * Best-effort โ€” failures are logged but don't fail the test.
76
+ */
77
+ function cleanupAmi(amiId) {
78
+ if (!amiId) return;
79
+ try {
80
+ console.log(`[cleanup] Deregistering AMI ${amiId}...`);
81
+ // Get snapshot IDs before deregistering
82
+ const describeOutput = execSync(
83
+ `aws ec2 describe-images --image-ids ${amiId} --query "Images[0].BlockDeviceMappings[*].Ebs.SnapshotId" --output text`,
84
+ { encoding: "utf-8", timeout: 15000 },
85
+ ).trim();
86
+
87
+ execSync(`aws ec2 deregister-image --image-id ${amiId}`, {
88
+ timeout: 15000,
89
+ });
90
+
91
+ // Delete backing snapshots
92
+ if (describeOutput && describeOutput !== "None") {
93
+ for (const snapId of describeOutput.split(/\s+/)) {
94
+ if (snapId.startsWith("snap-")) {
95
+ console.log(`[cleanup] Deleting snapshot ${snapId}...`);
96
+ execSync(`aws ec2 delete-snapshot --snapshot-id ${snapId}`, {
97
+ timeout: 15000,
98
+ });
99
+ }
100
+ }
101
+ }
102
+ console.log(`[cleanup] AMI ${amiId} cleaned up`);
103
+ } catch (err) {
104
+ console.warn(`[cleanup] Failed to clean up AMI ${amiId}: ${err.message}`);
105
+ }
106
+ }
107
+
108
+ // โ”€โ”€ Hover-Image login helper โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
109
+
110
+ async function performLogin(client, username = "standard_user") {
111
+ await client.focusApplication("Google Chrome");
112
+ const password = await client.extract("the password");
113
+ const usernameField = await client.find("username input");
114
+ await usernameField.click();
115
+ await client.type(username);
116
+ await client.pressKeys(["tab"]);
117
+ await client.type(password, { secret: true });
118
+ await client.pressKeys(["tab"]);
119
+ await client.pressKeys(["enter"]);
120
+ }
121
+
122
+ // โ”€โ”€ Test Suite โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
123
+
124
+ describe("Packer AMI โ†’ Hover Image", { timeout: SUITE_TIMEOUT }, () => {
125
+ let amiId;
126
+ let builtAmi = false;
127
+
128
+ beforeAll(() => {
129
+ // If TD_SANDBOX_AMI is set, skip the packer build
130
+ if (process.env.TD_SANDBOX_AMI) {
131
+ amiId = process.env.TD_SANDBOX_AMI;
132
+ console.log(`[packer] Using existing AMI: ${amiId}`);
133
+ } else {
134
+ amiId = buildAmi();
135
+ builtAmi = true;
136
+ }
137
+ });
138
+
139
+ afterAll(() => {
140
+ // Only clean up AMIs we built (don't delete pre-existing ones)
141
+ if (builtAmi && amiId && process.env.TD_PACKER_CLEANUP !== "false") {
142
+ cleanupAmi(amiId);
143
+ }
144
+ });
145
+
146
+ it(
147
+ "should click on shopping cart icon and verify empty cart",
148
+ { timeout: SUITE_TIMEOUT },
149
+ async (context) => {
150
+ const testdriver = TestDriver(context, {
151
+ ...getDefaults(context),
152
+ os: "windows",
153
+ sandboxAmi: amiId,
154
+ });
155
+
156
+ // Provision Chrome on the freshly-built AMI
157
+ await testdriver.provision.chrome({
158
+ url: "http://testdriver-sandbox.vercel.app/login",
159
+ });
160
+
161
+ // Perform login
162
+ await performLogin(testdriver);
163
+
164
+ // Click on the shopping cart icon
165
+ await testdriver.focusApplication("Google Chrome");
166
+ const cartIcon = await testdriver.find(
167
+ "shopping cart icon next to the Cart text in the top right corner",
168
+ );
169
+ await cartIcon.click();
170
+
171
+ // Assert that you see an empty shopping cart
172
+ const result = await testdriver.assert("Your cart is empty");
173
+ expect(result).toBeTruthy();
174
+ },
175
+ );
176
+ });
@@ -0,0 +1,68 @@
1
+ /**
2
+ * TestDriver SDK - Scroll Until Text Test (Vitest)
3
+ * Converted from: testdriver/acceptance/scroll-until-text.yaml
4
+ */
5
+
6
+ import { describe, expect, it } from "vitest";
7
+ import { TestDriver } from "../lib/vitest/hooks.mjs";
8
+ import { getDefaults } from "./config.mjs";
9
+
10
+ /**
11
+ * Perform login flow for SauceLabs demo app
12
+ * @param {TestDriver} client - TestDriver client
13
+ * @param {string} username - Username (default: 'standard_user')
14
+ */
15
+ async function performLogin(client, username = "standard_user") {
16
+ await client.focusApplication("Google Chrome");
17
+ const password = await client.extract("the password");
18
+ const usernameField = await client.find(
19
+ "username input",
20
+ );
21
+ await usernameField.click();
22
+ await client.type(username);
23
+ await client.pressKeys(["tab"]);
24
+ await client.type(password, { secret: true });
25
+ await client.pressKeys(["tab"]);
26
+ await client.pressKeys(["enter"]);
27
+ }
28
+
29
+ describe("Scroll Until Text Test", () => {
30
+ it('should scroll until "testdriver socks" appears', async (context) => {
31
+ const testdriver = TestDriver(context, { ...getDefaults(context), headless: true });
32
+ await testdriver.provision.chrome({ url: 'http://testdriver-sandbox.vercel.app/login' });
33
+
34
+ //
35
+ // Perform login first
36
+ await performLogin(testdriver);
37
+
38
+ // Scroll until text appears
39
+ await testdriver.focusApplication("Google Chrome");
40
+
41
+ await testdriver.find('TestDriver.ai Sandbox heading').click();
42
+
43
+ // Scroll until text appears
44
+ let found = false;
45
+ let scrollCount = 0;
46
+ const maxScrolls = 10;
47
+
48
+ while (!found && scrollCount < maxScrolls) {
49
+ const findResult = await testdriver.find("testdriver socks product text is fully visible");
50
+
51
+ if (findResult.found()) {
52
+ found = true;
53
+ } else {
54
+ await testdriver.scroll();
55
+ scrollCount++;
56
+ }
57
+ }
58
+
59
+ if (!found) {
60
+ throw new Error(`Failed to find "testdriver socks" after ${maxScrolls} scrolls`);
61
+ }
62
+
63
+ // Assert testdriver socks appears on screen
64
+ await testdriver.focusApplication("Google Chrome");
65
+ const result = await testdriver.assert("TestDriver Socks appears on screen");
66
+ expect(result).toBeTruthy();
67
+ });
68
+ });
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Test Init Command
5
+ *
6
+ * This script tests the `testdriverai init` command by:
7
+ * 1. Creating a temporary test project
8
+ * 2. Running the init command
9
+ * 3. Verifying all files were created correctly
10
+ * 4. Running the generated test
11
+ * 5. Cleaning up
12
+ *
13
+ * Usage:
14
+ * node manual/test-init-command.js
15
+ *
16
+ * Requirements:
17
+ * - TD_API_KEY environment variable must be set
18
+ */
19
+
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+ const { execSync } = require('child_process');
23
+ const os = require('os');
24
+
25
+ // Colors for terminal output
26
+ const colors = {
27
+ reset: '\x1b[0m',
28
+ green: '\x1b[32m',
29
+ red: '\x1b[31m',
30
+ cyan: '\x1b[36m',
31
+ yellow: '\x1b[33m',
32
+ gray: '\x1b[90m',
33
+ };
34
+
35
+ function log(message, color = 'reset') {
36
+ console.log(`${colors[color]}${message}${colors.reset}`);
37
+ }
38
+
39
+ function success(message) {
40
+ log(`โœ“ ${message}`, 'green');
41
+ }
42
+
43
+ function error(message) {
44
+ log(`โœ— ${message}`, 'red');
45
+ }
46
+
47
+ function info(message) {
48
+ log(message, 'cyan');
49
+ }
50
+
51
+ function step(message) {
52
+ log(`\n${message}`, 'cyan');
53
+ }
54
+
55
+ // Main test function
56
+ async function testInitCommand() {
57
+ // Check for API key
58
+ if (!process.env.TD_API_KEY) {
59
+ error('TD_API_KEY environment variable is required');
60
+ process.exit(1);
61
+ }
62
+
63
+ const testDir = path.join(os.tmpdir(), `test-init-${Date.now()}`);
64
+ const cliPath = path.join(__dirname, '..');
65
+
66
+ try {
67
+ step('๐Ÿ“ฆ Creating test directory...');
68
+ fs.mkdirSync(testDir, { recursive: true });
69
+ success(`Created: ${testDir}`);
70
+
71
+ step('๐Ÿ”ง Setting up .env file...');
72
+ const envContent = `TD_API_KEY=${process.env.TD_API_KEY}\n`;
73
+ fs.writeFileSync(path.join(testDir, '.env'), envContent);
74
+ success('Created .env with API key');
75
+
76
+ step('๐Ÿš€ Running init command...');
77
+ try {
78
+ execSync(`node ${path.join(cliPath, 'bin/testdriverai.js')} init`, {
79
+ cwd: testDir,
80
+ stdio: 'inherit',
81
+ env: { ...process.env, TD_API_KEY: process.env.TD_API_KEY }
82
+ });
83
+ success('Init command completed');
84
+ } catch (err) {
85
+ error('Init command failed');
86
+ throw err;
87
+ }
88
+
89
+ step('๐Ÿ” Verifying project structure...');
90
+
91
+ const expectedFiles = [
92
+ 'package.json',
93
+ 'vitest.config.js',
94
+ 'tests/example.test.js',
95
+ 'tests/login.js',
96
+ '.env',
97
+ '.gitignore',
98
+ '.github/workflows/testdriver.yml'
99
+ ];
100
+
101
+ for (const file of expectedFiles) {
102
+ const filePath = path.join(testDir, file);
103
+ if (!fs.existsSync(filePath)) {
104
+ error(`Missing file: ${file}`);
105
+ throw new Error(`Expected file not found: ${file}`);
106
+ }
107
+ success(`Found: ${file}`);
108
+ }
109
+
110
+ step('๐Ÿ“ Verifying vitest.config.js contents...');
111
+ const vitestConfig = fs.readFileSync(path.join(testDir, 'vitest.config.js'), 'utf8');
112
+
113
+ if (!vitestConfig.includes('TestDriver()')) {
114
+ error('TestDriver reporter not found in vitest.config.js');
115
+ console.log(vitestConfig);
116
+ throw new Error('TestDriver reporter not configured');
117
+ }
118
+ success('TestDriver reporter is configured');
119
+
120
+ if (!vitestConfig.includes('setupFiles') || !vitestConfig.includes('testdriverai/vitest/setup')) {
121
+ error('setupFiles not configured correctly');
122
+ console.log(vitestConfig);
123
+ throw new Error('setupFiles not configured');
124
+ }
125
+ success('setupFiles is configured correctly');
126
+
127
+ if (!vitestConfig.includes('reporters')) {
128
+ error('reporters array not found');
129
+ console.log(vitestConfig);
130
+ throw new Error('reporters not configured');
131
+ }
132
+ success('reporters array includes TestDriver');
133
+
134
+ step('๐Ÿ“ Verifying example test contents...');
135
+ const testFile = fs.readFileSync(path.join(testDir, 'tests/example.test.js'), 'utf8');
136
+
137
+ if (!testFile.includes('.provision.chrome')) {
138
+ error('Test does not use .provision.chrome');
139
+ console.log(testFile);
140
+ throw new Error('Test does not use .provision pattern');
141
+ }
142
+ success('Test uses .provision.chrome');
143
+
144
+ if (!testFile.includes("from 'testdriverai/vitest/hooks'")) {
145
+ error('Test does not import from testdriverai/vitest/hooks');
146
+ console.log(testFile);
147
+ throw new Error('Test does not import TestDriver from vitest/hooks');
148
+ }
149
+ success('Test imports TestDriver from vitest/hooks');
150
+
151
+ if (!testFile.includes("from './login.js'")) {
152
+ error('Test does not import login from ./login.js');
153
+ console.log(testFile);
154
+ throw new Error('Test does not import login snippet');
155
+ }
156
+ success('Test imports login snippet');
157
+
158
+ step('๐Ÿ“ Verifying login snippet contents...');
159
+ const loginFile = fs.readFileSync(path.join(testDir, 'tests/login.js'), 'utf8');
160
+
161
+ if (!loginFile.includes('.extract(')) {
162
+ error('Login snippet does not use .extract()');
163
+ console.log(loginFile);
164
+ throw new Error('Login snippet does not demonstrate .extract()');
165
+ }
166
+ success('Login snippet demonstrates .extract()');
167
+
168
+ if (!loginFile.includes('secret: true')) {
169
+ error('Login snippet does not use secret option');
170
+ console.log(loginFile);
171
+ throw new Error('Login snippet does not demonstrate secret typing');
172
+ }
173
+ success('Login snippet demonstrates secret typing');
174
+
175
+ step('๐Ÿงช Running generated test...');
176
+ try {
177
+ execSync('npm test', {
178
+ cwd: testDir,
179
+ stdio: 'inherit',
180
+ env: { ...process.env, TD_API_KEY: process.env.TD_API_KEY }
181
+ });
182
+ success('Test execution completed successfully');
183
+ } catch (err) {
184
+ error('Test execution failed');
185
+ throw err;
186
+ }
187
+
188
+ step('โœ… All checks passed!');
189
+ log('\nTest summary:', 'green');
190
+ log(' โ€ข Init command executed successfully', 'green');
191
+ log(' โ€ข All expected files created', 'green');
192
+ log(' โ€ข Configuration files are correct', 'green');
193
+ log(' โ€ข Example test has proper patterns', 'green');
194
+ log(' โ€ข Generated test runs successfully', 'green');
195
+
196
+ } catch (err) {
197
+ step('โŒ Test failed!');
198
+ error(err.message);
199
+ if (err.stack) {
200
+ log(err.stack, 'gray');
201
+ }
202
+ process.exit(1);
203
+ } finally {
204
+ // Optional: Clean up test directory
205
+ // Commented out so you can inspect the generated files
206
+ // step('๐Ÿงน Cleaning up...');
207
+ // if (fs.existsSync(testDir)) {
208
+ // fs.rmSync(testDir, { recursive: true, force: true });
209
+ // success('Cleaned up test directory');
210
+ // }
211
+
212
+ info(`\nTest project preserved at: ${testDir}`);
213
+ info('To clean up manually, run:');
214
+ log(` rm -rf ${testDir}`, 'gray');
215
+ }
216
+ }
217
+
218
+ // Run the test
219
+ testInitCommand().catch(err => {
220
+ error('Unexpected error:');
221
+ console.error(err);
222
+ process.exit(1);
223
+ });