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