@testdriverai/agent 7.8.0-test.38

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,843 @@
1
+ # TestDriver AI SDK - Agent Guide
2
+
3
+ This guide is designed for AI agents to understand how to use the TestDriver SDK for automated testing.
4
+
5
+ ## Table of Contents
6
+ - [Quick Setup](#quick-setup)
7
+ - [Authentication](#authentication)
8
+ - [Provision Methods](#provision-methods)
9
+ - [Core API Methods](#core-api-methods)
10
+ - [Reconnection and Debugging](#reconnection-and-debugging)
11
+ - [Best Practices](#best-practices)
12
+
13
+ ---
14
+
15
+ ## Quick Setup
16
+
17
+ ### 1. Install Dependencies
18
+
19
+ ```bash
20
+ npm install --save-dev testdriverai vitest
21
+ ```
22
+
23
+ ### 2. Configure Vitest Project
24
+
25
+ Create or update `vitest.config.mjs`:
26
+
27
+ ```javascript
28
+ import { defineConfig } from 'vitest/config';
29
+
30
+ export default defineConfig({
31
+ test: {
32
+ testTimeout: 120000, // 2 minutes (TestDriver tests can take longer)
33
+ hookTimeout: 120000,
34
+ },
35
+ });
36
+ ```
37
+
38
+ ### 3. Create Test File
39
+
40
+ Create a test file (e.g., `test.test.js`):
41
+
42
+ ```javascript
43
+ import { test } from 'vitest';
44
+ import { chrome } from 'testdriverai/presets';
45
+
46
+ test('my first test', async (context) => {
47
+ const { testdriver } = await chrome(context, {
48
+ url: 'https://example.com',
49
+ apiKey: process.env.TD_API_KEY
50
+ });
51
+
52
+ await testdriver.find('More information link').click();
53
+ await testdriver.assert('IANA page is visible');
54
+ });
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Authentication
60
+
61
+ ### Getting an API Key
62
+
63
+ 1. Go to [console.testdriver.ai](https://console.testdriver.ai)
64
+ 2. Sign up or log in
65
+ 3. Navigate to your account settings
66
+ 4. Generate a new API key (format: `tdai-1234567890abcdef`)
67
+
68
+ ### Using API Keys
69
+
70
+ **Recommended: Environment Variables**
71
+
72
+ Create `.env` file (add to `.gitignore`):
73
+ ```bash
74
+ TD_API_KEY=tdai-1234567890abcdef
75
+ ```
76
+
77
+ Then use in tests:
78
+ ```javascript
79
+ const { testdriver } = await chrome(context, {
80
+ url: 'https://example.com'
81
+ // apiKey automatically read from process.env.TD_API_KEY
82
+ });
83
+ ```
84
+
85
+ **Alternative: Direct in Code (Not Recommended)**
86
+ ```javascript
87
+ const { testdriver } = await chrome(context, {
88
+ url: 'https://example.com',
89
+ apiKey: 'tdai-1234567890abcdef' // DON'T commit to version control!
90
+ });
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Provision Methods
96
+
97
+ TestDriver provides presets to automatically provision different application types.
98
+
99
+ ### chrome() - Web Applications
100
+
101
+ Automatically launches Chrome browser and navigates to a URL.
102
+
103
+ ```javascript
104
+ import { chrome } from 'testdriverai/presets';
105
+
106
+ test('web app test', async (context) => {
107
+ const { testdriver, dashcam } = await chrome(context, {
108
+ url: 'https://myapp.com',
109
+ maximized: true, // Start maximized (default: true)
110
+ guest: true, // Use incognito mode (default: true)
111
+ dashcam: true, // Enable recording (default: true)
112
+ os: 'linux', // OS: 'linux', 'mac', 'windows' (default: 'linux')
113
+ apiKey: process.env.TD_API_KEY
114
+ });
115
+
116
+ // Your test code
117
+ });
118
+ ```
119
+
120
+ ### vscode() - VS Code Extensions
121
+
122
+ Automatically launches VS Code with specified workspace and extensions.
123
+
124
+ ```javascript
125
+ import { vscode } from 'testdriverai/presets';
126
+
127
+ test('vscode extension test', async (context) => {
128
+ const { testdriver, dashcam } = await vscode(context, {
129
+ workspace: '/tmp/test-project',
130
+ extensions: ['ms-python.python', 'dbaeumer.vscode-eslint'],
131
+ dashcam: true,
132
+ os: 'linux',
133
+ apiKey: process.env.TD_API_KEY
134
+ });
135
+
136
+ // Your test code
137
+ });
138
+ ```
139
+
140
+ ### electron() - Desktop Applications
141
+
142
+ Automatically launches Electron applications.
143
+
144
+ ```javascript
145
+ import { electron } from 'testdriverai/presets';
146
+
147
+ test('electron app test', async (context) => {
148
+ const { app, dashcam } = await electron(context, {
149
+ appPath: './dist/my-app',
150
+ args: ['--debug'], // Additional CLI args (optional)
151
+ dashcam: true,
152
+ os: 'linux',
153
+ apiKey: process.env.TD_API_KEY
154
+ });
155
+
156
+ // Your test code (app is alias for testdriver)
157
+ });
158
+ ```
159
+
160
+ ### Advanced: TestDriver() Hook + provision
161
+
162
+ For more control, use the direct API (recommended for v7.1+):
163
+
164
+ ```javascript
165
+ import { TestDriver } from 'testdriverai/vitest/hooks';
166
+
167
+ test('my test', async (context) => {
168
+ const testdriver = TestDriver(context, {
169
+ apiKey: process.env.TD_API_KEY
170
+ });
171
+
172
+ // Provision Chrome
173
+ await testdriver.provision.chrome({ url: 'https://example.com' });
174
+
175
+ // Or provision VS Code
176
+ await testdriver.provision.vscode({
177
+ workspace: '/tmp/project',
178
+ extensions: ['ms-python.python']
179
+ });
180
+
181
+ // Or provision Electron
182
+ await testdriver.provision.electron({ appPath: './dist/app' });
183
+
184
+ // Your test code
185
+ });
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Core API Methods
191
+
192
+ All methods use AI-powered natural language descriptions.
193
+
194
+ ### find(description) - Locate Elements
195
+
196
+ Find a single element using natural language.
197
+
198
+ ```javascript
199
+ // Basic finding
200
+ const button = await testdriver.find('submit button');
201
+ const input = await testdriver.find('email input field');
202
+ const link = await testdriver.find('Contact Us link');
203
+
204
+ // With context
205
+ const field = await testdriver.find('username input in the login form');
206
+ const deleteBtn = await testdriver.find('delete button in the top right corner');
207
+
208
+ // Chainable syntax (recommended)
209
+ await testdriver.find('submit button').click();
210
+ await testdriver.find('email input').type('user@example.com');
211
+ ```
212
+
213
+ **Returns:** `Element` object with properties:
214
+ - `coordinates` - Position `{x, y, centerX, centerY}`
215
+ - `text` - Text content (if available)
216
+ - `confidence` - AI confidence score
217
+ - `screenshot` - Base64 screenshot (if available)
218
+
219
+ ### findAll(description) - Find Multiple Elements
220
+
221
+ Find all matching elements.
222
+
223
+ ```javascript
224
+ const items = await testdriver.findAll('product card');
225
+ console.log(`Found ${items.length} products`);
226
+
227
+ // Interact with each
228
+ for (const item of items) {
229
+ await item.click();
230
+ // Do something
231
+ }
232
+ ```
233
+
234
+ **Returns:** `Array<Element>`
235
+
236
+ ### click(x?, y?, action?) - Click Elements or Coordinates
237
+
238
+ ```javascript
239
+ // Element click (chainable)
240
+ await testdriver.find('Login button').click();
241
+
242
+ // Coordinate click
243
+ await testdriver.click(500, 300);
244
+
245
+ // Different click types
246
+ await element.click(); // Regular click
247
+ await element.click('double-click'); // Double-click
248
+ await element.click('right-click'); // Right-click
249
+ await element.click('mouseDown'); // Press and hold
250
+ await element.click('mouseUp'); // Release
251
+
252
+ // Or use dedicated methods
253
+ await element.doubleClick();
254
+ await element.rightClick();
255
+ await element.mouseDown();
256
+ await element.mouseUp();
257
+ ```
258
+
259
+ ### type(text, options) - Type Text
260
+
261
+ Type text into the currently focused input.
262
+
263
+ ```javascript
264
+ // Basic typing
265
+ await testdriver.find('email input').click();
266
+ await testdriver.type('user@example.com');
267
+
268
+ // Type with delay between keystrokes
269
+ await testdriver.type('slow typing', { delay: 500 }); // 500ms between chars
270
+
271
+ // ⚠️ IMPORTANT: Always use secret: true for passwords and sensitive data
272
+ await testdriver.find('password input').click();
273
+ await testdriver.type('MySecureP@ssw0rd', { secret: true });
274
+ // This prevents logging in dashcam, debug info, and console
275
+
276
+ // Type numbers
277
+ await testdriver.type(12345);
278
+ ```
279
+
280
+ **Options:**
281
+ - `delay` (number) - Delay between keystrokes in ms (default: 250)
282
+ - `secret` (boolean) - Mark as sensitive data, won't be logged (default: false)
283
+
284
+ ### hover(x?, y?) - Hover Over Elements
285
+
286
+ ```javascript
287
+ // Element hover
288
+ const menu = await testdriver.find('Products menu');
289
+ await menu.hover();
290
+ await testdriver.find('Laptops submenu item').click();
291
+
292
+ // Coordinate hover
293
+ await testdriver.hover(500, 300);
294
+ ```
295
+
296
+ ### assert(assertion) - AI-Powered Assertions
297
+
298
+ Verify screen state using natural language.
299
+
300
+ ```javascript
301
+ // Verify elements
302
+ await testdriver.assert('the login page is displayed');
303
+ await testdriver.assert('submit button is visible');
304
+
305
+ // Verify content
306
+ await testdriver.assert('the page title is "Welcome"');
307
+ await testdriver.assert('success message says "Account created"');
308
+
309
+ // Verify state
310
+ await testdriver.assert('the checkbox is checked');
311
+ await testdriver.assert('the form is empty');
312
+
313
+ // Verify visual appearance
314
+ await testdriver.assert('the button is blue');
315
+ await testdriver.assert('the loading spinner is displayed');
316
+ ```
317
+
318
+ **Returns:** `Promise<boolean>` - `true` if passes, throws error if fails
319
+
320
+ ### pressKeys(keys) - Keyboard Shortcuts
321
+
322
+ Press one or more keys simultaneously.
323
+
324
+ ```javascript
325
+ // Navigation
326
+ await testdriver.pressKeys(['tab']);
327
+ await testdriver.pressKeys(['shift', 'tab']);
328
+ await testdriver.pressKeys(['enter']);
329
+
330
+ // Keyboard shortcuts
331
+ await testdriver.pressKeys(['ctrl', 'c']); // Copy
332
+ await testdriver.pressKeys(['ctrl', 'v']); // Paste
333
+ await testdriver.pressKeys(['ctrl', 's']); // Save
334
+ await testdriver.pressKeys(['ctrl', 'a']); // Select all
335
+
336
+ // Arrow keys
337
+ await testdriver.pressKeys(['up']);
338
+ await testdriver.pressKeys(['down']);
339
+ await testdriver.pressKeys(['left']);
340
+ await testdriver.pressKeys(['right']);
341
+
342
+ // Special keys
343
+ await testdriver.pressKeys(['escape']);
344
+ await testdriver.pressKeys(['backspace']);
345
+ await testdriver.pressKeys(['delete']);
346
+ await testdriver.pressKeys(['home']);
347
+ await testdriver.pressKeys(['end']);
348
+ ```
349
+
350
+ ### scroll(direction, amount, method) - Scroll Pages
351
+
352
+ ```javascript
353
+ // Scroll down (default)
354
+ await testdriver.scroll();
355
+ await testdriver.scroll('down', 500);
356
+
357
+ // Scroll up
358
+ await testdriver.scroll('up', 300);
359
+
360
+ // Horizontal scrolling
361
+ await testdriver.scroll('right', 300);
362
+ await testdriver.scroll('left', 300);
363
+
364
+ // Scroll methods
365
+ await testdriver.scroll('down', 300, 'mouse'); // Mouse wheel (smooth)
366
+ await testdriver.scroll('down', 300, 'keyboard'); // Page Down key
367
+
368
+ // Scroll until text appears
369
+ await testdriver.scrollUntilText('Contact Us');
370
+ await testdriver.scrollUntilText('Footer', 'down', 5000);
371
+ ```
372
+
373
+ ### exec(language, code, timeout, silent) - Execute Code
374
+
375
+ Execute shell or PowerShell in the sandbox.
376
+
377
+ ```javascript
378
+ // Shell execution (Linux sandbox)
379
+ const output = await testdriver.exec('sh', 'ls -la', 5000);
380
+
381
+ // PowerShell execution (Windows sandbox)
382
+ await testdriver.exec('pwsh', 'npm install -g http-server', 30000);
383
+ await testdriver.exec('pwsh', 'Start-Process notepad.exe', 5000);
384
+ ```
385
+
386
+ ### focusApplication(appName) - Switch Applications
387
+
388
+ Focus a different application window.
389
+
390
+ ```javascript
391
+ await testdriver.focusApplication('Chrome');
392
+ await testdriver.focusApplication('VS Code');
393
+ await testdriver.focusApplication('Notepad');
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Reconnection and Debugging
399
+
400
+ ### Reconnecting to a Sandbox
401
+
402
+ If a test fails or you need to try different selectors, you can reconnect to the same sandbox instance.
403
+
404
+ **Automatic Sandbox Tracking:** TestDriver automatically saves the last sandbox ID to `.testdriver/last-sandbox` in your project directory. You can use this to reconnect without manually tracking the ID.
405
+
406
+ **Manual Tracking:** You can also explicitly save the `sandboxId` from the initial connection:
407
+
408
+ ```javascript
409
+ import { test } from 'vitest';
410
+ import { TestDriver } from 'testdriverai';
411
+
412
+ test('initial attempt', async () => {
413
+ const testdriver = new TestDriver({
414
+ apiKey: process.env.TD_API_KEY
415
+ });
416
+
417
+ const instance = await testdriver.connect();
418
+ console.log('Sandbox ID:', instance.instanceId);
419
+ // Output: Sandbox ID: i-0abc123def456789
420
+
421
+ // Your test code that might fail
422
+ try {
423
+ await testdriver.find('difficult selector').click();
424
+ } catch (error) {
425
+ console.error('Failed:', error);
426
+ // Don't disconnect yet - keep sandbox alive for debugging
427
+ }
428
+ });
429
+
430
+ test('reconnect to same sandbox', async () => {
431
+ const testdriver = new TestDriver({
432
+ apiKey: process.env.TD_API_KEY
433
+ });
434
+
435
+ // Option 1: Read from saved file
436
+ const lastSandboxId = testdriver.getLastSandboxId();
437
+
438
+ // Option 2: Use the ID from previous test (manual tracking)
439
+ // const sandboxId = 'i-0abc123def456789';
440
+
441
+ // Reconnect using the sandbox ID
442
+ await testdriver.connect({
443
+ sandboxId: lastSandboxId, // or use manually saved ID
444
+ newSandbox: false
445
+ });
446
+
447
+ // Try different selector on the same sandbox state
448
+ try {
449
+ await testdriver.find('alternative selector description').click();
450
+ } catch (error) {
451
+ console.error('Alternative also failed:', error);
452
+ }
453
+
454
+ await testdriver.disconnect();
455
+ });
456
+ ```
457
+
458
+ ### Debugging Failed Finds
459
+
460
+ When `find()` fails, TestDriver provides detailed debug information:
461
+
462
+ ```javascript
463
+ try {
464
+ await testdriver.find('non-existent button').click();
465
+ } catch (error) {
466
+ // error.name === 'ElementNotFoundError'
467
+ console.log('Element not found:', error.message);
468
+ console.log('Similarity score:', error.similarity); // How close the match was
469
+ console.log('Debug screenshot:', error.debugScreenshot); // Base64 image
470
+ console.log('Cache info:', error.cacheInfo); // Cache diagnostics
471
+
472
+ // Try alternative description
473
+ await testdriver.find('button with different description').click();
474
+ }
475
+ ```
476
+
477
+ ### Keep Sandbox Alive for Multiple Attempts
478
+
479
+ ```javascript
480
+ test('iterative debugging', async (context) => {
481
+ const testdriver = new TestDriver({
482
+ apiKey: process.env.TD_API_KEY
483
+ });
484
+
485
+ const instance = await testdriver.connect();
486
+ const sandboxId = instance.instanceId;
487
+
488
+ // Try multiple selectors
489
+ const selectors = [
490
+ 'submit button',
491
+ 'blue submit button',
492
+ 'submit button in bottom right',
493
+ 'button with "Submit" text'
494
+ ];
495
+
496
+ for (const selector of selectors) {
497
+ try {
498
+ console.log(`Trying: ${selector}`);
499
+ const element = await testdriver.find(selector);
500
+ console.log(`✓ Found with: ${selector}`);
501
+ await element.click();
502
+ break; // Success!
503
+ } catch (error) {
504
+ console.log(`✗ Failed with: ${selector}`);
505
+ console.log(` Similarity: ${error.similarity}`);
506
+ }
507
+ }
508
+
509
+ // Clean up
510
+ await testdriver.disconnect();
511
+ });
512
+ ```
513
+
514
+ ### Using Vitest Hooks for Reconnection
515
+
516
+ ```javascript
517
+ import { test, beforeAll, afterAll } from 'vitest';
518
+ import { TestDriver } from 'testdriverai';
519
+
520
+ let testdriver;
521
+ let sandboxId;
522
+
523
+ beforeAll(async () => {
524
+ testdriver = new TestDriver({
525
+ apiKey: process.env.TD_API_KEY
526
+ });
527
+ const instance = await testdriver.connect();
528
+ sandboxId = instance.instanceId;
529
+ console.log('Sandbox started:', sandboxId);
530
+ });
531
+
532
+ afterAll(async () => {
533
+ await testdriver.disconnect();
534
+ });
535
+
536
+ test('first attempt', async () => {
537
+ await testdriver.find('selector v1').click();
538
+ });
539
+
540
+ test('second attempt - same sandbox', async () => {
541
+ // Continues in same sandbox session
542
+ await testdriver.find('selector v2').click();
543
+ });
544
+ ```
545
+
546
+ ---
547
+
548
+ ## Best Practices
549
+
550
+ ### 1. Use Descriptive Selectors
551
+
552
+ ```javascript
553
+ // ❌ Too vague
554
+ await testdriver.find('button');
555
+
556
+ // ✅ Specific
557
+ await testdriver.find('blue submit button below the login form');
558
+ ```
559
+
560
+ ### 2. Always Use secret: true for Sensitive Data
561
+
562
+ ```javascript
563
+ // ❌ Password will be logged
564
+ await testdriver.type('MyPassword123');
565
+
566
+ // ✅ Protected from logging
567
+ await testdriver.type('MyPassword123', { secret: true });
568
+ ```
569
+
570
+ ### 3. Prefer Chainable Syntax
571
+
572
+ ```javascript
573
+ // ❌ More verbose
574
+ const button = await testdriver.find('submit button');
575
+ await button.click();
576
+
577
+ // ✅ Cleaner
578
+ await testdriver.find('submit button').click();
579
+ ```
580
+
581
+ ### 4. Use Environment Variables for API Keys
582
+
583
+ ```javascript
584
+ // ❌ Hardcoded (security risk)
585
+ apiKey: 'tdai-1234567890abcdef'
586
+
587
+ // ✅ From environment
588
+ apiKey: process.env.TD_API_KEY
589
+ ```
590
+
591
+ ### 5. Set Appropriate Timeouts
592
+
593
+ ```javascript
594
+ // vitest.config.mjs
595
+ export default defineConfig({
596
+ test: {
597
+ testTimeout: 120000, // 2 minutes for TestDriver tests
598
+ hookTimeout: 120000,
599
+ },
600
+ });
601
+ ```
602
+
603
+ ### 6. Handle Errors Gracefully
604
+
605
+ ```javascript
606
+ try {
607
+ await testdriver.find('optional element').click();
608
+ } catch (error) {
609
+ console.log('Element not found, continuing...');
610
+ // Try alternative path
611
+ }
612
+ ```
613
+
614
+ ### 7. Use Assertions for Verification
615
+
616
+ ```javascript
617
+ // After action, verify result
618
+ await testdriver.find('submit button').click();
619
+ await testdriver.assert('success message is displayed');
620
+ ```
621
+
622
+ ### 8. Clean Up Resources
623
+
624
+ ```javascript
625
+ // Always disconnect when done
626
+ test('my test', async (context) => {
627
+ const { testdriver } = await chrome(context, { url: 'https://example.com' });
628
+
629
+ try {
630
+ // Your test code
631
+ } finally {
632
+ await testdriver.disconnect();
633
+ }
634
+ });
635
+
636
+ // Or use presets which auto-cleanup
637
+ ```
638
+
639
+ ### 9. Save Sandbox IDs for Debugging
640
+
641
+ ```javascript
642
+ const instance = await testdriver.connect();
643
+ console.log('Sandbox ID for debugging:', instance.instanceId);
644
+ // Save this ID to reconnect later if test fails
645
+ ```
646
+
647
+ ### 10. Use findAll() for Lists
648
+
649
+ ```javascript
650
+ // ❌ Finding one at a time
651
+ const item1 = await testdriver.find('first product card');
652
+ const item2 = await testdriver.find('second product card');
653
+
654
+ // ✅ Find all at once
655
+ const items = await testdriver.findAll('product card');
656
+ for (const item of items) {
657
+ await item.click();
658
+ }
659
+ ```
660
+
661
+ ---
662
+
663
+ ## Common Patterns
664
+
665
+ ### Login Flow
666
+
667
+ ```javascript
668
+ test('user login', async (context) => {
669
+ const { testdriver } = await chrome(context, {
670
+ url: 'https://myapp.com/login'
671
+ });
672
+
673
+ await testdriver.find('email input').type('user@example.com');
674
+ await testdriver.find('password input').type('SecurePass123', { secret: true });
675
+ await testdriver.find('Login button').click();
676
+
677
+ await testdriver.assert('Welcome message is visible');
678
+ });
679
+ ```
680
+
681
+ ### Form Filling
682
+
683
+ ```javascript
684
+ test('contact form', async (context) => {
685
+ const { testdriver } = await chrome(context, {
686
+ url: 'https://example.com/contact'
687
+ });
688
+
689
+ await testdriver.find('name input').type('John Doe');
690
+ await testdriver.find('email input').type('john@example.com');
691
+ await testdriver.find('message textarea').type('Hello, this is a test message.');
692
+ await testdriver.find('submit button').click();
693
+
694
+ await testdriver.assert('Thank you message appears');
695
+ });
696
+ ```
697
+
698
+ ### Navigation
699
+
700
+ ```javascript
701
+ test('multi-page navigation', async (context) => {
702
+ const { testdriver } = await chrome(context, {
703
+ url: 'https://example.com'
704
+ });
705
+
706
+ await testdriver.find('About link').click();
707
+ await testdriver.assert('About page heading is visible');
708
+
709
+ await testdriver.find('Contact link').click();
710
+ await testdriver.assert('Contact form is displayed');
711
+ });
712
+ ```
713
+
714
+ ### Working with Dropdowns
715
+
716
+ ```javascript
717
+ test('dropdown selection', async (context) => {
718
+ const { testdriver } = await chrome(context, {
719
+ url: 'https://example.com/form'
720
+ });
721
+
722
+ await testdriver.find('country dropdown').click();
723
+ await testdriver.find('United States option').click();
724
+
725
+ await testdriver.assert('United States is selected');
726
+ });
727
+ ```
728
+
729
+ ---
730
+
731
+ ## Environment Variables
732
+
733
+ TestDriver supports these environment variables:
734
+
735
+ - `TD_API_KEY` - Your TestDriver API key (recommended)
736
+ - `TD_NO_CACHE` - Set to `"true"` to disable caching
737
+ - `DASHCAM_API_KEY` - Dashcam API key (usually same as TD_API_KEY)
738
+ - `TESTDRIVER_SANDBOX_ID` - Reuse an existing sandbox instance (see Sandbox Management below)
739
+
740
+ ---
741
+
742
+ ## Sandbox Management
743
+
744
+ TestDriver allows you to create long-running sandbox instances that can be reused across multiple test runs.
745
+
746
+ ### Creating a Sandbox
747
+
748
+ Use the CLI to spawn a new sandbox:
749
+
750
+ ```bash
751
+ # Spawn a Linux sandbox (default)
752
+ testdriver sandbox spawn
753
+
754
+ # Spawn with a 2-hour lifetime (in milliseconds)
755
+ testdriver sandbox spawn --timeout 7200000
756
+
757
+ # Spawn a Windows sandbox
758
+ testdriver sandbox spawn --os windows
759
+
760
+ # Spawn with custom instance type (requires permission)
761
+ testdriver sandbox spawn --instance-type c5.xlarge
762
+ ```
763
+
764
+ The command will output the instance ID and instructions for using it.
765
+
766
+ ### Listing Sandboxes
767
+
768
+ View all your team's sandboxes:
769
+
770
+ ```bash
771
+ # List all sandboxes
772
+ testdriver sandbox list
773
+
774
+ # List only ready sandboxes
775
+ testdriver sandbox list --status ready
776
+ ```
777
+
778
+ ### Using a Sandbox in Tests
779
+
780
+ Set the `TESTDRIVER_SANDBOX_ID` environment variable to connect to an existing sandbox:
781
+
782
+ ```bash
783
+ export TESTDRIVER_SANDBOX_ID=i-0abc123def456789
784
+ vitest
785
+ ```
786
+
787
+ This will:
788
+ - Skip creating a new sandbox
789
+ - Connect to the specified sandbox instance
790
+ - Track which tests run on that sandbox
791
+ - Keep the sandbox alive after tests finish
792
+
793
+ ### Stopping a Sandbox
794
+
795
+ When you're done with a sandbox, stop it to avoid unnecessary costs:
796
+
797
+ ```bash
798
+ testdriver sandbox stop i-0abc123def456789
799
+ ```
800
+
801
+ This will:
802
+ - Terminate the EC2 instance
803
+ - Calculate the total runtime and cost
804
+ - Send billing data to your team
805
+
806
+ ### Sandbox Benefits
807
+
808
+ Using explicit sandboxes provides:
809
+ - **Faster test runs** - No sandbox creation time
810
+ - **Clear cost tracking** - Lifetime-based billing
811
+ - **Better debugging** - Keep sandbox alive to investigate failures
812
+ - **Team visibility** - See all active sandboxes in dashboard
813
+
814
+ ---
815
+
816
+ ## Resources
817
+
818
+ - **Documentation:** [docs.testdriver.ai](https://docs.testdriver.ai)
819
+ - **Dashboard:** [console.testdriver.ai](https://console.testdriver.ai)
820
+ - **API Reference:** Full method documentation in `/docs/v7/api/`
821
+ - **Examples:** See `/examples/` directory in the SDK package
822
+
823
+ ---
824
+
825
+ ## Quick Reference
826
+
827
+ | Method | Purpose | Example |
828
+ |--------|---------|---------|
829
+ | `find(desc)` | Locate single element | `await testdriver.find('submit button')` |
830
+ | `findAll(desc)` | Find all matching elements | `await testdriver.findAll('list item')` |
831
+ | `click()` | Click element/coordinates | `await element.click()` |
832
+ | `type(text, opts)` | Type text | `await testdriver.type('text', { secret: true })` |
833
+ | `hover()` | Hover over element | `await element.hover()` |
834
+ | `assert(text)` | Verify state | `await testdriver.assert('button is visible')` |
835
+ | `pressKeys(keys)` | Keyboard shortcuts | `await testdriver.pressKeys(['ctrl', 'c'])` |
836
+ | `scroll(dir, amt)` | Scroll page | `await testdriver.scroll('down', 500)` |
837
+ | `exec(lang, code)` | Execute code | `await testdriver.exec('sh', 'ls -la', 5000)` |
838
+ | `connect(opts)` | Connect to sandbox | `await testdriver.connect({ sandboxId: 'i-123' })` |
839
+ | `disconnect()` | Close connection | `await testdriver.disconnect()` |
840
+
841
+ ---
842
+
843
+ **Last Updated:** December 2, 2025