@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,829 @@
1
+ ---
2
+ name: testdriver:find
3
+ description: Locate UI elements using natural language
4
+ ---
5
+ <!-- Generated from find.mdx. DO NOT EDIT. -->
6
+
7
+ ## Overview
8
+
9
+ Locate UI elements on screen using AI-powered natural language descriptions. Returns an `Element` object that can be interacted with.
10
+
11
+ ## Syntax
12
+
13
+ ```javascript
14
+ const element = await testdriver.find(description)
15
+ const element = await testdriver.find(description, options)
16
+ ```
17
+
18
+ ## Parameters
19
+
20
+ <ParamField path="description" type="string" required>
21
+ Natural language description of the element to find
22
+ </ParamField>
23
+
24
+ <ParamField path="options" type="object | number">
25
+ Optional configuration for finding and caching
26
+
27
+ <Expandable title="properties">
28
+ <ParamField path="cacheKey" type="string">
29
+ Custom cache key for storing element location. Use this to prevent cache pollution when using dynamic variables in prompts, or to share cache across tests.
30
+ </ParamField>
31
+
32
+ <ParamField path="cacheThreshold" type="number" default={0.05}>
33
+ Similarity threshold (0-1) for cache matching. Lower values require more similarity. Set to -1 to disable cache.
34
+ </ParamField>
35
+
36
+ <ParamField path="timeout" type="number" default={10000}>
37
+ Maximum time in milliseconds to poll for the element. Retries every 5 seconds until found or timeout expires. Defaults to `10000` (10 seconds). Set to `0` to disable polling and make a single attempt.
38
+ </ParamField>
39
+
40
+ <ParamField path="confidence" type="number">
41
+ Minimum confidence threshold (0-1). If the AI's confidence score for the found element is below this value, the find will be treated as a failure (`element.found()` returns `false`). Useful for ensuring high-quality matches in critical test steps.
42
+ </ParamField>
43
+
44
+ <ParamField path="type" type="string">
45
+ Element type hint that wraps the description for better matching. Accepted values:
46
+ - `"text"` — Wraps the prompt as `The text "..."`
47
+ - `"image"` — Wraps the prompt as `The image "..."`
48
+ - `"ui"` — Wraps the prompt as `The UI element "..."`
49
+ - `"any"` — No wrapping, uses the description as-is (default behavior)
50
+ </ParamField>
51
+
52
+ <ParamField path="zoom" type="boolean" default={false}>
53
+ Enable two-phase zoom mode for better precision in crowded UIs with many similar elements.
54
+ </ParamField>
55
+
56
+ <ParamField path="ai" type="object">
57
+ AI sampling configuration for this find call (overrides global `ai` config from constructor).
58
+
59
+ <Expandable title="properties">
60
+ <ParamField path="temperature" type="number">
61
+ Controls randomness. `0` = deterministic. Default: `0` for find verification.
62
+ </ParamField>
63
+
64
+ <ParamField path="top" type="object">
65
+ Sampling parameters
66
+
67
+ <Expandable title="properties">
68
+ <ParamField path="p" type="number">
69
+ Top-P (nucleus sampling). Range: 0-1.
70
+ </ParamField>
71
+
72
+ <ParamField path="k" type="number">
73
+ Top-K sampling. `1` = most deterministic.
74
+ </ParamField>
75
+ </Expandable>
76
+ </ParamField>
77
+ </Expandable>
78
+ </ParamField>
79
+ </Expandable>
80
+ </ParamField>
81
+
82
+ ## Returns
83
+
84
+ `Promise<Element>` - Element instance that has been automatically located
85
+
86
+ ## Examples
87
+
88
+ ### Basic Element Finding
89
+
90
+ ```javascript
91
+ // Find by role
92
+ const button = await testdriver.find('submit button');
93
+ const input = await testdriver.find('email input field');
94
+
95
+ // Find by text content
96
+ const link = await testdriver.find('Contact Us link');
97
+ const heading = await testdriver.find('Welcome heading');
98
+
99
+ // Find by visual appearance
100
+ const icon = await testdriver.find('red warning icon');
101
+ const image = await testdriver.find('company logo image');
102
+ ```
103
+
104
+ ### Finding with Context
105
+
106
+ ```javascript
107
+ // Provide location context
108
+ const field = await testdriver.find('username input in the login form');
109
+ const button = await testdriver.find('delete button in the top right corner');
110
+
111
+ // Describe nearby elements
112
+ const input = await testdriver.find('input field below the email label');
113
+ const checkbox = await testdriver.find('checkbox next to "Remember me"');
114
+
115
+ // Describe visual position
116
+ const menu = await testdriver.find('hamburger menu icon in the top left');
117
+ ```
118
+
119
+ ### Interacting with Found Elements
120
+
121
+ ```javascript
122
+ // Find and click
123
+ const submitBtn = await testdriver.find('submit button');
124
+ await submitBtn.click();
125
+
126
+ // Find and verify
127
+ const message = await testdriver.find('success message');
128
+ if (message.found()) {
129
+ console.log('Success message appeared');
130
+ }
131
+
132
+ // Find and extract info
133
+ const price = await testdriver.find('product price');
134
+ console.log('Price location:', price.coordinates);
135
+ console.log('Price text:', price.text);
136
+ ```
137
+
138
+ ## Element Object
139
+
140
+ The returned `Element` object provides:
141
+
142
+ ### Methods
143
+
144
+ - `found()` - Check if element was located
145
+ - `click(action)` - Click the element
146
+ - `hover()` - Hover over the element
147
+ - `doubleClick()` - Double-click the element
148
+ - `rightClick()` - Right-click the element
149
+ - `find(newDescription)` - Re-locate with optional new description
150
+
151
+ ### Properties
152
+
153
+ - `coordinates` - Element position `{x, y, centerX, centerY}`
154
+ - `x`, `y` - Top-left coordinates
155
+ - `centerX`, `centerY` - Center coordinates
156
+ - `text` - Text content (if available)
157
+ - `screenshot` - Base64 screenshot (if available)
158
+ - `confidence` - AI confidence score
159
+ - `width`, `height` - Element dimensions
160
+ - `boundingBox` - Complete bounding box
161
+
162
+ See [Elements Reference](/v7/elements) for complete details.
163
+
164
+ ### JSON Serialization
165
+
166
+ Elements can be safely serialized using `JSON.stringify()` for logging and debugging. Circular references are automatically removed:
167
+
168
+ ```javascript
169
+ const element = await testdriver.find('login button');
170
+
171
+ // Safe to stringify - no circular reference errors
172
+ console.log(JSON.stringify(element, null, 2));
173
+
174
+ // Output includes useful debugging info:
175
+ // {
176
+ // "description": "login button",
177
+ // "coordinates": { "x": 100, "y": 200, "centerX": 150, "centerY": 225 },
178
+ // "found": true,
179
+ // "threshold": 0.01,
180
+ // "x": 100,
181
+ // "y": 200,
182
+ // "cache": {
183
+ // "hit": true,
184
+ // "strategy": "pixel-diff",
185
+ // "createdAt": "2025-12-09T10:30:00Z",
186
+ // "diffPercent": 0.0023,
187
+ // "imageUrl": "https://..."
188
+ // },
189
+ // "similarity": 0.98,
190
+ // "confidence": 0.95,
191
+ // "selector": "button#login",
192
+ // "aiResponse": "Found the blue login button..."
193
+ // }
194
+ ```
195
+
196
+ This is useful for:
197
+ - Debugging element detection issues
198
+ - Logging test execution details
199
+ - Sharing element information across processes
200
+ - Analyzing cache performance
201
+
202
+ ## Best Practices
203
+
204
+ <Check>
205
+ **Be specific in descriptions**
206
+
207
+ More specific descriptions improve accuracy:
208
+
209
+ ```javascript
210
+ // ✅ Good
211
+ await testdriver.find('blue submit button below the email field');
212
+
213
+ // ❌ Too vague
214
+ await testdriver.find('button');
215
+ ```
216
+ </Check>
217
+
218
+ <Check>
219
+ **Always check if found**
220
+
221
+ Verify elements were located before interacting:
222
+
223
+ ```javascript
224
+ const element = await testdriver.find('login button');
225
+ if (!element.found()) {
226
+ throw new Error('Login button not found');
227
+ }
228
+ await element.click();
229
+ ```
230
+ </Check>
231
+
232
+ <Check>
233
+ **Include visual or positional context**
234
+
235
+ ```javascript
236
+ // Include color
237
+ await testdriver.find('red error icon');
238
+
239
+ // Include position
240
+ await testdriver.find('search button in the top navigation bar');
241
+
242
+ // Include nearby text
243
+ await testdriver.find('checkbox next to "I agree to terms"');
244
+ ```
245
+ </Check>
246
+
247
+ ## Confidence Threshold
248
+
249
+ Require a minimum AI confidence score for element matches. If the confidence is below the threshold, `find()` treats the result as not found:
250
+
251
+ ```javascript
252
+ // Require at least 90% confidence
253
+ const element = await testdriver.find('submit button', { confidence: 0.9 });
254
+
255
+ if (!element.found()) {
256
+ // AI found something but wasn't confident enough
257
+ throw new Error('Could not confidently locate submit button');
258
+ }
259
+
260
+ await element.click();
261
+ ```
262
+
263
+ This is useful for:
264
+ - Critical test steps where an incorrect click could cause cascading failures
265
+ - Distinguishing between similar elements (e.g., multiple buttons)
266
+ - Failing fast when the UI has changed unexpectedly
267
+
268
+ ```javascript
269
+ // Combine with timeout for robust polling with confidence gate
270
+ const element = await testdriver.find('success notification', {
271
+ confidence: 0.85,
272
+ timeout: 15000,
273
+ });
274
+ ```
275
+
276
+ <Tip>
277
+ The `confidence` value is a float between 0 and 1 (e.g., `0.9` = 90%). The AI returns its confidence with each find result, which you can also read from `element.confidence` after a successful find.
278
+ </Tip>
279
+ ## Element Type
280
+
281
+ Use the `type` option to hint what kind of element you're looking for. This wraps your description into a more specific prompt for the AI, improving match accuracy — especially when users provide short or ambiguous descriptions.
282
+
283
+ ```javascript
284
+ // Find text on the page
285
+ const label = await testdriver.find('Sign In', { type: 'text' });
286
+ // AI prompt becomes: The text "Sign In"
287
+
288
+ // Find an image
289
+ const logo = await testdriver.find('company logo', { type: 'image' });
290
+ // AI prompt becomes: The image "company logo"
291
+
292
+ // Find a UI element (button, input, checkbox, etc.)
293
+ const btn = await testdriver.find('Submit', { type: 'ui' });
294
+ // AI prompt becomes: The UI element "Submit"
295
+
296
+ // No wrapping — same as omitting the option
297
+ const el = await testdriver.find('the blue submit button', { type: 'any' });
298
+ ```
299
+
300
+ | Type | Prompt sent to AI |
301
+ |------|----|
302
+ | `"text"` | `The text "..."` |
303
+ | `"image"` | `The image "..."` |
304
+ | `"ui"` | `The UI element "..."` |
305
+ | `"any"` | Original description (no wrapping) |
306
+
307
+ <Tip>
308
+ This is particularly useful for short descriptions like `"Submit"` or `"Login"` where the AI may not know whether to look for a button, a link, or visible text. Specifying `type` removes the ambiguity.
309
+ </Tip>
310
+ ## Polling for Dynamic Elements
311
+
312
+ By default, `find()` polls for up to 10 seconds (retrying every 5 seconds) until the element is found. You can customize this with the `timeout` option:
313
+
314
+ ```javascript
315
+ // Uses default 10s timeout - polls every 5 seconds
316
+ const element = await testdriver.find('login button');
317
+ await element.click();
318
+
319
+ // Custom timeout - wait up to 30 seconds
320
+ const element = await testdriver.find('login button', { timeout: 30000 });
321
+ await element.click();
322
+
323
+ // Disable polling - single attempt only
324
+ const element = await testdriver.find('login button', { timeout: 0 });
325
+ ```
326
+
327
+ The `timeout` option:
328
+ - Defaults to `10000` (10 seconds)
329
+ - Retries finding the element every 5 seconds
330
+ - Stops when the element is found or the timeout expires
331
+ - Logs progress during polling
332
+ - Returns the element (check `element.found()` if not throwing on failure)
333
+ - Set to `0` to disable polling and make a single attempt
334
+
335
+ ## Zoom Mode for Crowded UIs
336
+
337
+ When dealing with many similar icons or elements clustered together (like browser toolbars), enable `zoom` mode for better precision:
338
+
339
+ ```javascript
340
+ // Enable zoom for better precision in crowded UIs
341
+ const extensionsBtn = await testdriver.find('extensions puzzle icon in Chrome toolbar', { zoom: true });
342
+ await extensionsBtn.click();
343
+ ```
344
+
345
+ ### How Zoom Mode Works
346
+
347
+ 1. **Phase 1**: AI identifies the approximate location of the element
348
+ 2. **Phase 2**: A 30% crop of the screen is created around that location
349
+ 3. **Phase 3**: AI performs precise location on the zoomed/cropped image
350
+ 4. **Result**: Coordinates are converted back to absolute screen position
351
+
352
+ This two-phase approach gives the AI a higher-resolution view of the target area, improving accuracy when multiple similar elements are close together.
353
+
354
+ <Tip>
355
+ Use `zoom: true` when:
356
+ - Clicking small icons in toolbars
357
+ - Selecting from a grid of similar items
358
+ - Targeting elements in dense UI areas
359
+ - The default locate is clicking the wrong similar element
360
+ - You get an AI verification rejection like "The crosshair is located in the empty space of the browser's tab bar/title bar area" — this means the initial locate was imprecise and zoom will help the AI pinpoint the correct element
361
+ </Tip>
362
+
363
+ ```javascript
364
+ // Without zoom - may click wrong icon in toolbar
365
+ const icon = await testdriver.find('settings icon');
366
+
367
+ // With zoom - better precision for crowded areas
368
+ const icon = await testdriver.find('settings icon', { zoom: true });
369
+ ```
370
+
371
+ ## Cache Options
372
+
373
+ Control caching behavior to optimize performance, especially when using dynamic variables in prompts.
374
+
375
+ ### Custom Cache Key
376
+
377
+ Use `cacheKey` to prevent cache pollution when prompts contain variables:
378
+
379
+ ```javascript
380
+ // ❌ Without cacheKey - creates new cache entry for each email value
381
+ const email = 'user@example.com';
382
+ await testdriver.find(`input for ${email}`); // Cache miss every time
383
+
384
+ // ✅ With cacheKey - reuses cache regardless of variable
385
+ const email = 'user@example.com';
386
+ await testdriver.find(`input for ${email}`, {
387
+ cacheKey: 'email-input'
388
+ });
389
+
390
+ // Also useful for dynamic IDs, names, or other changing data
391
+ const orderId = generateOrderId();
392
+ await testdriver.find(`order ${orderId} status`, {
393
+ cacheKey: 'order-status' // Same cache for all orders
394
+ });
395
+ ```
396
+
397
+ ### Cache Threshold
398
+
399
+ Control how similar a cached result must be to reuse it:
400
+
401
+ ```javascript
402
+ // Default: 95% similarity required
403
+ await testdriver.find('submit button');
404
+
405
+ // Strict threshold - 99% similarity required
406
+ await testdriver.find('submit button', {
407
+ cacheThreshold: 0.01
408
+ });
409
+
410
+ // Disable cache entirely for this call
411
+ await testdriver.find('submit button', {
412
+ cacheThreshold: -1
413
+ });
414
+
415
+ // Combine cacheKey with threshold
416
+ await testdriver.find('submit button', {
417
+ cacheKey: 'submit-btn',
418
+ cacheThreshold: 0.01
419
+ });
420
+ ```
421
+
422
+ <Tip>
423
+ By default, TestDriver auto-generates a cache key from the SHA-256 hash of your test file. When you modify your test file, the hash changes automatically, invalidating stale cache entries.
424
+ </Tip>
425
+
426
+ ### Manual Polling (Alternative)
427
+
428
+ If you need custom polling logic:
429
+
430
+ ```javascript
431
+ async function waitForElement(testdriver, description, timeout = 30000) {
432
+ const startTime = Date.now();
433
+
434
+ while (Date.now() - startTime < timeout) {
435
+ const element = await testdriver.find(description);
436
+ if (element.found()) return element;
437
+ await new Promise(r => setTimeout(r, 1000));
438
+ }
439
+
440
+ throw new Error(`Element "${description}" not found after ${timeout}ms`);
441
+ }
442
+
443
+ // Usage
444
+ const button = await waitForElement(testdriver, 'submit button', 10000);
445
+ await button.click();
446
+ ```
447
+
448
+ ## Use Cases
449
+
450
+ <AccordionGroup>
451
+ <Accordion title="Form Fields">
452
+ ```javascript
453
+ const emailField = await testdriver.find('email input field');
454
+ await emailField.click();
455
+ await testdriver.type('user@example.com');
456
+
457
+ const passwordField = await testdriver.find('password input');
458
+ await passwordField.click();
459
+ await testdriver.type('MyP@ssw0rd');
460
+ ```
461
+ </Accordion>
462
+
463
+ <Accordion title="Buttons and Links">
464
+ ```javascript
465
+ const submitBtn = await testdriver.find('submit button');
466
+ await submitBtn.click();
467
+
468
+ const cancelLink = await testdriver.find('cancel link');
469
+ await cancelLink.click();
470
+
471
+ const menuIcon = await testdriver.find('hamburger menu icon');
472
+ await menuIcon.click();
473
+ ```
474
+ </Accordion>
475
+
476
+ <Accordion title="Dynamic Content">
477
+ ```javascript
478
+ // Wait for loading to complete
479
+ let content;
480
+ for (let i = 0; i < 30; i++) {
481
+ content = await testdriver.find('results table');
482
+ if (content.found()) break;
483
+ await new Promise(r => setTimeout(r, 1000));
484
+ }
485
+
486
+ // Interact with loaded content
487
+ const firstRow = await testdriver.find('first row in the results table');
488
+ await firstRow.click();
489
+ ```
490
+ </Accordion>
491
+
492
+ <Accordion title="Complex UI Elements">
493
+ ```javascript
494
+ // Modals and dialogs
495
+ const modal = await testdriver.find('confirmation dialog');
496
+ if (modal.found()) {
497
+ const confirmBtn = await testdriver.find('confirm button in the dialog');
498
+ await confirmBtn.click();
499
+ }
500
+
501
+ // Dropdown menus
502
+ const dropdown = await testdriver.find('country dropdown');
503
+ await dropdown.click();
504
+
505
+ const option = await testdriver.find('United States option');
506
+ await option.click();
507
+ ```
508
+ </Accordion>
509
+ </AccordionGroup>
510
+
511
+ ## Complete Example
512
+
513
+ ```javascript
514
+ import { beforeAll, afterAll, describe, it, expect } from 'vitest';
515
+ import TestDriver from 'testdriverai';
516
+
517
+ describe('Element Finding', () => {
518
+ let testdriver;
519
+
520
+ beforeAll(async () => {
521
+ client = new TestDriver(process.env.TD_API_KEY);
522
+ await testdriver.auth();
523
+ await testdriver.connect();
524
+ });
525
+
526
+ afterAll(async () => {
527
+ await testdriver.disconnect();
528
+ });
529
+
530
+ it('should find and interact with elements', async () => {
531
+ await testdriver.focusApplication('Google Chrome');
532
+
533
+ // Find login form elements
534
+ const usernameField = await testdriver.find('username input field');
535
+ expect(usernameField.found()).toBe(true);
536
+
537
+ await usernameField.click();
538
+ await testdriver.type('testuser');
539
+
540
+ // Find with context
541
+ const passwordField = await testdriver.find('password input below username');
542
+ await passwordField.click();
543
+ await testdriver.type('password123');
544
+
545
+ // Find button
546
+ const submitBtn = await testdriver.find('green submit button');
547
+ expect(submitBtn.found()).toBe(true);
548
+
549
+ console.log('Button location:', submitBtn.centerX, submitBtn.centerY);
550
+
551
+ await submitBtn.click();
552
+
553
+ // Wait for success message
554
+ let successMsg;
555
+ for (let i = 0; i < 10; i++) {
556
+ successMsg = await testdriver.find('success notification');
557
+ if (successMsg.found()) break;
558
+ await new Promise(r => setTimeout(r, 1000));
559
+ }
560
+
561
+ expect(successMsg.found()).toBe(true);
562
+ });
563
+ });
564
+ ```
565
+
566
+ ## Related Methods
567
+
568
+ - [`click()`](/v7/click) - Click on found elements
569
+ - [`hover()`](/v7/hover) - Hover over elements
570
+ - [`assert()`](/v7/assert) - Verify element states
571
+ - [Elements Reference](/v7/elements) - Complete Element API
572
+
573
+ ---
574
+
575
+ ## findAll()
576
+
577
+ Locate **all elements** matching a description, rather than just one.
578
+
579
+ ### Syntax
580
+
581
+ ```javascript
582
+ const elements = await testdriver.findAll(description, options)
583
+ ```
584
+
585
+ ### Parameters
586
+
587
+ <ParamField path="description" type="string" required>
588
+ Natural language description of elements to find
589
+ </ParamField>
590
+
591
+ <ParamField path="options" type="object | number">
592
+ Optional cache options (same as `find()`)
593
+
594
+ <Expandable title="properties">
595
+ <ParamField path="cacheKey" type="string">
596
+ Cache key for storing element location
597
+ </ParamField>
598
+
599
+ <ParamField path="cacheThreshold" type="number" default={-1}>
600
+ Similarity threshold (0-1) for cache matching. Set to -1 to disable cache.
601
+ </ParamField>
602
+ </Expandable>
603
+ </ParamField>
604
+
605
+ ### Returns
606
+
607
+ `Promise<Element[]>` - Array of Element instances
608
+
609
+ ### Examples
610
+
611
+ #### Basic Usage
612
+
613
+ ```javascript
614
+ // Find all matching elements
615
+ const buttons = await testdriver.findAll('button');
616
+ console.log(`Found ${buttons.length} buttons`);
617
+
618
+ // Interact with specific element
619
+ if (buttons.length > 0) {
620
+ await buttons[0].click(); // Click first button
621
+ }
622
+
623
+ // Iterate over all
624
+ for (const button of buttons) {
625
+ console.log(`Button at (${button.x}, ${button.y})`);
626
+ }
627
+ ```
628
+
629
+ #### Finding Multiple Items
630
+
631
+ ```javascript
632
+ // Find all list items
633
+ const items = await testdriver.findAll('list item');
634
+
635
+ // Find specific item by index
636
+ const thirdItem = items[2];
637
+ await thirdItem.click();
638
+
639
+ // Check all items
640
+ for (let i = 0; i < items.length; i++) {
641
+ console.log(`Item ${i + 1}: ${items[i].text || 'No text'}`);
642
+ }
643
+ ```
644
+
645
+ #### With Caching
646
+
647
+ ```javascript
648
+ // Cache element locations for faster subsequent runs
649
+ const menuItems = await testdriver.findAll('menu item', {
650
+ cacheKey: 'main-menu-items'
651
+ });
652
+
653
+ // First run: ~2-3 seconds (AI call)
654
+ // Subsequent runs: ~100ms (cache hit)
655
+ ```
656
+
657
+ #### Empty Results
658
+
659
+ ```javascript
660
+ // Returns empty array if nothing found (doesn't throw error)
661
+ const errors = await testdriver.findAll('error message');
662
+
663
+ if (errors.length === 0) {
664
+ console.log('No errors found - test passed!');
665
+ } else {
666
+ console.log(`Found ${errors.length} errors`);
667
+ }
668
+ ```
669
+
670
+ ### Differences from find()
671
+
672
+ | Feature | find() | findAll() |
673
+ |---------|--------|-----------|
674
+ | Return type | Single `Element` | Array of `Element[]` |
675
+ | If nothing found | Throws `ElementNotFoundError` | Returns empty array `[]` |
676
+ | Chainable | ✅ Yes: `await find('button').click()` | ❌ No (returns array) |
677
+ | Use case | One specific element | Multiple similar elements |
678
+ | Cache support | ✅ Yes | ✅ Yes |
679
+
680
+ ### Use Cases
681
+
682
+ <AccordionGroup>
683
+ <Accordion title="Table Rows">
684
+ ```javascript
685
+ // Find all rows in a table
686
+ const rows = await testdriver.findAll('table row');
687
+
688
+ // Click every row
689
+ for (const row of rows) {
690
+ await row.click();
691
+ await new Promise(r => setTimeout(r, 500)); // Wait between clicks
692
+ }
693
+
694
+ // Or click specific row
695
+ await rows[2].click(); // Click third row
696
+ ```
697
+ </Accordion>
698
+
699
+ <Accordion title="Checkboxes/Radio Buttons">
700
+ ```javascript
701
+ // Find all checkboxes
702
+ const checkboxes = await testdriver.findAll('checkbox');
703
+
704
+ // Check all boxes
705
+ for (const checkbox of checkboxes) {
706
+ await checkbox.click();
707
+ }
708
+
709
+ // Or select first unchecked
710
+ const unchecked = checkboxes[0];
711
+ await unchecked.click();
712
+ ```
713
+ </Accordion>
714
+
715
+ <Accordion title="Navigation Links">
716
+ ```javascript
717
+ // Find all navigation links
718
+ const navLinks = await testdriver.findAll('navigation link');
719
+
720
+ // Validate all are present
721
+ expect(navLinks.length).toBeGreaterThan(0);
722
+
723
+ // Click specific link by text
724
+ const homeLink = navLinks.find(link =>
725
+ link.text?.toLowerCase().includes('home')
726
+ );
727
+
728
+ if (homeLink) {
729
+ await homeLink.click();
730
+ }
731
+ ```
732
+ </Accordion>
733
+
734
+ <Accordion title="Conditional Interactions">
735
+ ```javascript
736
+ // Check if any error messages exist
737
+ const errors = await testdriver.findAll('error message');
738
+
739
+ if (errors.length > 0) {
740
+ console.log(`Found ${errors.length} validation errors`);
741
+
742
+ // Log each error location
743
+ errors.forEach((error, i) => {
744
+ console.log(`Error ${i + 1} at (${error.x}, ${error.y})`);
745
+ });
746
+ } else {
747
+ console.log('Form validation passed!');
748
+ }
749
+ ```
750
+ </Accordion>
751
+ </AccordionGroup>
752
+
753
+ ### Complete Example
754
+
755
+ ```javascript
756
+ import { test, expect } from 'vitest';
757
+ import { chrome } from 'testdriverai/presets';
758
+
759
+ test('select multiple items from list', async (context) => {
760
+ const { testdriver } = await chrome(context, {
761
+ url: 'https://example.com/products'
762
+ });
763
+
764
+ // Find all product cards
765
+ const products = await testdriver.findAll('product card');
766
+
767
+ expect(products.length).toBeGreaterThan(0);
768
+ console.log(`Found ${products.length} products`);
769
+
770
+ // Click first 3 products
771
+ const productsToSelect = Math.min(3, products.length);
772
+
773
+ for (let i = 0; i < productsToSelect; i++) {
774
+ await products[i].click();
775
+ console.log(`Selected product ${i + 1}`);
776
+ await new Promise(r => setTimeout(r, 500)); // Brief pause
777
+ }
778
+
779
+ // Verify selections
780
+ const selectedBadges = await testdriver.findAll('selected badge');
781
+ expect(selectedBadges.length).toBe(productsToSelect);
782
+ });
783
+ ```
784
+
785
+ ### Best Practices
786
+
787
+ <Check>
788
+ **Handle empty arrays gracefully**
789
+
790
+ ```javascript
791
+ // ✅ Good - check length first
792
+ const items = await testdriver.findAll('list item');
793
+ if (items.length > 0) {
794
+ await items[0].click();
795
+ }
796
+
797
+ // ❌ Bad - may throw error
798
+ const items = await testdriver.findAll('list item');
799
+ await items[0].click(); // Error if array is empty!
800
+ ```
801
+ </Check>
802
+
803
+ <Check>
804
+ **Use find() for single elements**
805
+
806
+ ```javascript
807
+ // ✅ Use find() when you need exactly one
808
+ const submitBtn = await testdriver.find('submit button');
809
+ await submitBtn.click();
810
+
811
+ // ❌ Unnecessary - findAll() returns array
812
+ const buttons = await testdriver.findAll('submit button');
813
+ await buttons[0].click(); // Extra array handling
814
+ ```
815
+ </Check>
816
+
817
+ <Check>
818
+ **Cache for performance**
819
+
820
+ ```javascript
821
+ // First run - slow (AI call)
822
+ const items = await testdriver.findAll('menu item', {
823
+ cacheKey: 'menu-items'
824
+ });
825
+
826
+ // Subsequent runs - fast (cache hit)
827
+ // ~10-20x faster than without cache
828
+ ```
829
+ </Check>