testdriverai 6.2.2 → 7.1.0

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 (300) hide show
  1. package/.github/workflows/acceptance-linux.yml +75 -0
  2. package/.github/workflows/acceptance-sdk-tests.yml +133 -0
  3. package/.vscode/settings.json +5 -1
  4. package/AGENTS.md +550 -0
  5. package/CODEOWNERS +0 -1
  6. package/README.md +126 -0
  7. package/{testdriver → _testdriver}/acceptance/drag-and-drop.yaml +2 -2
  8. package/{testdriver → _testdriver}/acceptance/snippets/login.yaml +1 -1
  9. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  10. package/{testdriver → _testdriver}/examples/web/lifecycle/prerun.yaml +6 -1
  11. package/{testdriver → _testdriver}/lifecycle/postrun.yaml +3 -2
  12. package/_testdriver/lifecycle/prerun.yaml +15 -0
  13. package/{testdriver → _testdriver}/lifecycle/provision.yaml +7 -2
  14. package/agent/index.js +300 -85
  15. package/agent/interface.js +15 -0
  16. package/agent/lib/cache.js +142 -0
  17. package/agent/lib/commander.js +1 -39
  18. package/agent/lib/commands.js +910 -296
  19. package/agent/lib/redraw.js +129 -41
  20. package/agent/lib/sandbox.js +29 -6
  21. package/agent/lib/sdk.js +22 -0
  22. package/agent/lib/system.js +0 -3
  23. package/agent/lib/validation.js +1 -7
  24. package/debug-locate-response.js +82 -0
  25. package/debugger/index.html +15 -4
  26. package/docs/ARCHITECTURE.md +424 -0
  27. package/docs/AWESOME_LOGS_QUICK_REF.md +100 -0
  28. package/docs/MIGRATION.md +425 -0
  29. package/docs/PRESETS.md +210 -0
  30. package/docs/QUICK_START_TEST_RECORDING.md +215 -0
  31. package/docs/SDK_AWESOME_LOGS.md +468 -0
  32. package/docs/TEST_RECORDING.md +388 -0
  33. package/docs/docs.json +286 -152
  34. package/docs/guide/best-practices-polling.mdx +154 -0
  35. package/docs/sdk-browser-rendering.md +167 -0
  36. package/docs/v6/getting-started/self-hosting.mdx +407 -0
  37. package/docs/{guide → v6/guide}/dashcam.mdx +1 -1
  38. package/docs/{guide → v6/guide}/environment-variables.mdx +4 -5
  39. package/docs/{guide → v6/guide}/lifecycle.mdx +1 -1
  40. package/docs/v6/overview/comparison.mdx +101 -0
  41. package/docs/v7/README.md +135 -0
  42. package/docs/v7/api/ai.mdx +205 -0
  43. package/docs/v7/api/assert.mdx +285 -0
  44. package/docs/v7/api/assertions.mdx +403 -0
  45. package/docs/v7/api/click.mdx +287 -0
  46. package/docs/v7/api/client.mdx +322 -0
  47. package/docs/v7/api/dashcam.mdx +497 -0
  48. package/docs/v7/api/doubleClick.mdx +102 -0
  49. package/docs/v7/api/elements.mdx +479 -0
  50. package/docs/v7/api/exec.mdx +346 -0
  51. package/docs/v7/api/find.mdx +316 -0
  52. package/docs/v7/api/focusApplication.mdx +294 -0
  53. package/docs/v7/api/hover.mdx +279 -0
  54. package/docs/v7/api/mouseDown.mdx +161 -0
  55. package/docs/v7/api/mouseUp.mdx +164 -0
  56. package/docs/v7/api/pressKeys.mdx +349 -0
  57. package/docs/v7/api/rightClick.mdx +123 -0
  58. package/docs/v7/api/sandbox.mdx +404 -0
  59. package/docs/v7/api/scroll.mdx +300 -0
  60. package/docs/v7/api/type.mdx +314 -0
  61. package/docs/v7/commands/assert.mdx +45 -0
  62. package/docs/v7/commands/exec.mdx +282 -0
  63. package/docs/v7/commands/focus-application.mdx +44 -0
  64. package/docs/v7/commands/hover-image.mdx +69 -0
  65. package/docs/v7/commands/hover-text.mdx +47 -0
  66. package/docs/v7/commands/if.mdx +53 -0
  67. package/docs/v7/commands/match-image.mdx +67 -0
  68. package/docs/v7/commands/press-keys.mdx +87 -0
  69. package/docs/v7/commands/remember.mdx +49 -0
  70. package/docs/v7/commands/run.mdx +44 -0
  71. package/docs/v7/commands/scroll-until-image.mdx +66 -0
  72. package/docs/v7/commands/scroll-until-text.mdx +60 -0
  73. package/docs/v7/commands/scroll.mdx +69 -0
  74. package/docs/v7/commands/type.mdx +45 -0
  75. package/docs/v7/commands/wait-for-image.mdx +54 -0
  76. package/docs/v7/commands/wait-for-text.mdx +48 -0
  77. package/docs/v7/commands/wait.mdx +45 -0
  78. package/docs/v7/getting-started/configuration.mdx +380 -0
  79. package/docs/v7/getting-started/quickstart.mdx +332 -0
  80. package/docs/v7/guides/best-practices.mdx +486 -0
  81. package/docs/v7/guides/caching-ai.mdx +215 -0
  82. package/docs/v7/guides/caching-selectors.mdx +292 -0
  83. package/docs/v7/guides/caching.mdx +366 -0
  84. package/docs/v7/guides/ci-cd/azure.mdx +587 -0
  85. package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
  86. package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
  87. package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
  88. package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
  89. package/docs/v7/guides/ci-cd/travis.mdx +438 -0
  90. package/docs/v7/guides/debugging.mdx +349 -0
  91. package/docs/v7/guides/faq.mdx +393 -0
  92. package/docs/v7/guides/migration.mdx +562 -0
  93. package/docs/v7/guides/performance.mdx +517 -0
  94. package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
  95. package/docs/v7/guides/troubleshooting.mdx +526 -0
  96. package/docs/v7/guides/vitest-plugin.mdx +477 -0
  97. package/docs/v7/guides/vitest.mdx +535 -0
  98. package/docs/v7/platforms/linux.mdx +308 -0
  99. package/docs/v7/platforms/macos.mdx +433 -0
  100. package/docs/v7/platforms/windows.mdx +430 -0
  101. package/docs/v7/playwright.mdx +342 -0
  102. package/docs/v7/presets/chrome-extension.mdx +223 -0
  103. package/docs/v7/presets/chrome.mdx +287 -0
  104. package/docs/v7/presets/electron.mdx +435 -0
  105. package/docs/v7/presets/vscode.mdx +398 -0
  106. package/docs/v7/presets/webapp.mdx +396 -0
  107. package/docs/v7/progressive-apis/CORE.md +459 -0
  108. package/docs/v7/progressive-apis/HOOKS.md +360 -0
  109. package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
  110. package/docs/v7/progressive-apis/PROVISION.md +266 -0
  111. package/eslint.config.js +19 -1
  112. package/interfaces/cli/lib/base.js +10 -4
  113. package/interfaces/logger.js +2 -1
  114. package/interfaces/shared-test-state.mjs +69 -0
  115. package/interfaces/vitest-plugin.mjs +830 -0
  116. package/package.json +29 -5
  117. package/schema.json +8 -29
  118. package/scripts/view-test-results.mjs +96 -0
  119. package/sdk-log-formatter.js +714 -0
  120. package/sdk.d.ts +1028 -0
  121. package/sdk.js +2567 -0
  122. package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
  123. package/setup/aws/cloudformation.yaml +9 -2
  124. package/src/core/Dashcam.js +469 -0
  125. package/src/core/index.d.ts +150 -0
  126. package/src/core/index.js +12 -0
  127. package/src/presets/index.mjs +331 -0
  128. package/src/vitest/extended.mjs +108 -0
  129. package/src/vitest/hooks.d.ts +119 -0
  130. package/src/vitest/hooks.mjs +298 -0
  131. package/src/vitest/index.mjs +64 -0
  132. package/src/vitest/lifecycle.mjs +277 -0
  133. package/src/vitest/utils.mjs +150 -0
  134. package/test/dashcam.test.js +137 -0
  135. package/test/mcp-example-test.yaml +27 -0
  136. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +61 -0
  137. package/testdriver/acceptance-sdk/README.md +128 -0
  138. package/testdriver/acceptance-sdk/TEST_REPORTING.md +245 -0
  139. package/testdriver/acceptance-sdk/assert.test.mjs +26 -0
  140. package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
  141. package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
  142. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +58 -0
  143. package/testdriver/acceptance-sdk/element-not-found.test.mjs +25 -0
  144. package/testdriver/acceptance-sdk/exec-js.test.mjs +43 -0
  145. package/testdriver/acceptance-sdk/exec-output.test.mjs +59 -0
  146. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +57 -0
  147. package/testdriver/acceptance-sdk/focus-window.test.mjs +36 -0
  148. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +26 -0
  149. package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
  150. package/testdriver/acceptance-sdk/hover-image.test.mjs +34 -0
  151. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +38 -0
  152. package/testdriver/acceptance-sdk/hover-text.test.mjs +27 -0
  153. package/testdriver/acceptance-sdk/match-image.test.mjs +36 -0
  154. package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
  155. package/testdriver/acceptance-sdk/press-keys.test.mjs +50 -0
  156. package/testdriver/acceptance-sdk/prompt.test.mjs +33 -0
  157. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +38 -0
  158. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +39 -0
  159. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +28 -0
  160. package/testdriver/acceptance-sdk/scroll.test.mjs +41 -0
  161. package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
  162. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +420 -0
  163. package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
  164. package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
  165. package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
  166. package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
  167. package/testdriver/acceptance-sdk/type.test.mjs +45 -0
  168. package/verify-element-api.js +89 -0
  169. package/verify-types.js +0 -0
  170. package/vitest.config.example.js +19 -0
  171. package/vitest.config.mjs +66 -0
  172. package/vitest.config.mjs.bak +44 -0
  173. package/.github/workflows/acceptance-v6.yml +0 -169
  174. package/.vscode/mcp.json +0 -9
  175. package/docs/overview/comparison.mdx +0 -82
  176. package/testdriver/lifecycle/prerun.yaml +0 -17
  177. /package/{testdriver/examples/desktop/lifecycle/prerun.yaml → .env.example} +0 -0
  178. /package/{testdriver → _testdriver}/acceptance/assert.yaml +0 -0
  179. /package/{testdriver → _testdriver}/acceptance/dashcam.yaml +0 -0
  180. /package/{testdriver → _testdriver}/acceptance/embed.yaml +0 -0
  181. /package/{testdriver → _testdriver}/acceptance/exec-js.yaml +0 -0
  182. /package/{testdriver → _testdriver}/acceptance/exec-output.yaml +0 -0
  183. /package/{testdriver → _testdriver}/acceptance/exec-shell.yaml +0 -0
  184. /package/{testdriver → _testdriver}/acceptance/focus-window.yaml +0 -0
  185. /package/{testdriver → _testdriver}/acceptance/hover-image.yaml +0 -0
  186. /package/{testdriver → _testdriver}/acceptance/hover-text-with-description.yaml +0 -0
  187. /package/{testdriver → _testdriver}/acceptance/hover-text.yaml +0 -0
  188. /package/{testdriver → _testdriver}/acceptance/if-else.yaml +0 -0
  189. /package/{testdriver → _testdriver}/acceptance/match-image.yaml +0 -0
  190. /package/{testdriver → _testdriver}/acceptance/press-keys.yaml +0 -0
  191. /package/{testdriver → _testdriver}/acceptance/prompt.yaml +0 -0
  192. /package/{testdriver → _testdriver}/acceptance/remember.yaml +0 -0
  193. /package/{testdriver → _testdriver}/acceptance/screenshots/cart.png +0 -0
  194. /package/{testdriver → _testdriver}/acceptance/scroll-keyboard.yaml +0 -0
  195. /package/{testdriver → _testdriver}/acceptance/scroll-until-image.yaml +0 -0
  196. /package/{testdriver → _testdriver}/acceptance/scroll-until-text.yaml +0 -0
  197. /package/{testdriver → _testdriver}/acceptance/scroll.yaml +0 -0
  198. /package/{testdriver → _testdriver}/acceptance/snippets/match-cart.yaml +0 -0
  199. /package/{testdriver → _testdriver}/acceptance/type.yaml +0 -0
  200. /package/{testdriver → _testdriver}/behavior/failure.yaml +0 -0
  201. /package/{testdriver → _testdriver}/behavior/hover-text.yaml +0 -0
  202. /package/{testdriver → _testdriver}/behavior/lifecycle/postrun.yaml +0 -0
  203. /package/{testdriver → _testdriver}/behavior/lifecycle/prerun.yaml +0 -0
  204. /package/{testdriver → _testdriver}/behavior/lifecycle/provision.yaml +0 -0
  205. /package/{testdriver → _testdriver}/behavior/secrets.yaml +0 -0
  206. /package/{testdriver → _testdriver}/edge-cases/dashcam-chrome.yaml +0 -0
  207. /package/{testdriver → _testdriver}/edge-cases/exec-pwsh-multiline.yaml +0 -0
  208. /package/{testdriver → _testdriver}/edge-cases/js-exception.yaml +0 -0
  209. /package/{testdriver → _testdriver}/edge-cases/js-promise.yaml +0 -0
  210. /package/{testdriver → _testdriver}/edge-cases/lifecycle/postrun.yaml +0 -0
  211. /package/{testdriver → _testdriver}/edge-cases/prompt-in-middle.yaml +0 -0
  212. /package/{testdriver → _testdriver}/edge-cases/prompt-nested.yaml +0 -0
  213. /package/{testdriver → _testdriver}/edge-cases/success-test.yaml +0 -0
  214. /package/{testdriver → _testdriver}/examples/android/example.yaml +0 -0
  215. /package/{testdriver → _testdriver}/examples/android/lifecycle/postrun.yaml +0 -0
  216. /package/{testdriver → _testdriver}/examples/android/lifecycle/provision.yaml +0 -0
  217. /package/{testdriver → _testdriver}/examples/android/readme.md +0 -0
  218. /package/{testdriver → _testdriver}/examples/chrome-extension/lifecycle/provision.yaml +0 -0
  219. /package/{testdriver → _testdriver}/examples/desktop/lifecycle/provision.yaml +0 -0
  220. /package/{testdriver → _testdriver}/examples/vscode-extension/lifecycle/provision.yaml +0 -0
  221. /package/{testdriver → _testdriver}/examples/web/lifecycle/postrun.yaml +0 -0
  222. /package/docs/{account → v6/account}/dashboard.mdx +0 -0
  223. /package/docs/{account → v6/account}/enterprise.mdx +0 -0
  224. /package/docs/{account → v6/account}/pricing.mdx +0 -0
  225. /package/docs/{account → v6/account}/projects.mdx +0 -0
  226. /package/docs/{account → v6/account}/team.mdx +0 -0
  227. /package/docs/{action → v6/action}/ami.mdx +0 -0
  228. /package/docs/{action → v6/action}/performance.mdx +0 -0
  229. /package/docs/{action → v6/action}/secrets.mdx +0 -0
  230. /package/docs/{apps → v6/apps}/chrome-extensions.mdx +0 -0
  231. /package/docs/{apps → v6/apps}/desktop-apps.mdx +0 -0
  232. /package/docs/{apps → v6/apps}/mobile-apps.mdx +0 -0
  233. /package/docs/{apps → v6/apps}/static-websites.mdx +0 -0
  234. /package/docs/{apps → v6/apps}/tauri-apps.mdx +0 -0
  235. /package/docs/{bugs → v6/bugs}/jira.mdx +0 -0
  236. /package/docs/{cli → v6/cli}/overview.mdx +0 -0
  237. /package/docs/{commands → v6/commands}/assert.mdx +0 -0
  238. /package/docs/{commands → v6/commands}/exec.mdx +0 -0
  239. /package/docs/{commands → v6/commands}/focus-application.mdx +0 -0
  240. /package/docs/{commands → v6/commands}/hover-image.mdx +0 -0
  241. /package/docs/{commands → v6/commands}/hover-text.mdx +0 -0
  242. /package/docs/{commands → v6/commands}/if.mdx +0 -0
  243. /package/docs/{commands → v6/commands}/match-image.mdx +0 -0
  244. /package/docs/{commands → v6/commands}/press-keys.mdx +0 -0
  245. /package/docs/{commands → v6/commands}/remember.mdx +0 -0
  246. /package/docs/{commands → v6/commands}/run.mdx +0 -0
  247. /package/docs/{commands → v6/commands}/scroll-until-image.mdx +0 -0
  248. /package/docs/{commands → v6/commands}/scroll-until-text.mdx +0 -0
  249. /package/docs/{commands → v6/commands}/scroll.mdx +0 -0
  250. /package/docs/{commands → v6/commands}/type.mdx +0 -0
  251. /package/docs/{commands → v6/commands}/wait-for-image.mdx +0 -0
  252. /package/docs/{commands → v6/commands}/wait-for-text.mdx +0 -0
  253. /package/docs/{commands → v6/commands}/wait.mdx +0 -0
  254. /package/docs/{exporting → v6/exporting}/junit.mdx +0 -0
  255. /package/docs/{exporting → v6/exporting}/playwright.mdx +0 -0
  256. /package/docs/{features → v6/features}/auto-healing.mdx +0 -0
  257. /package/docs/{features → v6/features}/generation.mdx +0 -0
  258. /package/docs/{features → v6/features}/parallel-testing.mdx +0 -0
  259. /package/docs/{features → v6/features}/reusable-snippets.mdx +0 -0
  260. /package/docs/{features → v6/features}/selectorless.mdx +0 -0
  261. /package/docs/{features → v6/features}/visual-assertions.mdx +0 -0
  262. /package/docs/{getting-started → v6/getting-started}/ci.mdx +0 -0
  263. /package/docs/{getting-started → v6/getting-started}/cli.mdx +0 -0
  264. /package/docs/{getting-started → v6/getting-started}/editing.mdx +0 -0
  265. /package/docs/{getting-started → v6/getting-started}/playwright.mdx +0 -0
  266. /package/docs/{getting-started → v6/getting-started}/running.mdx +0 -0
  267. /package/docs/{getting-started → v6/getting-started}/vscode.mdx +0 -0
  268. /package/docs/{guide → v6/guide}/assertions.mdx +0 -0
  269. /package/docs/{guide → v6/guide}/authentication.mdx +0 -0
  270. /package/docs/{guide → v6/guide}/code.mdx +0 -0
  271. /package/docs/{guide → v6/guide}/locating.mdx +0 -0
  272. /package/docs/{guide → v6/guide}/protips.mdx +0 -0
  273. /package/docs/{guide → v6/guide}/variables.mdx +0 -0
  274. /package/docs/{guide → v6/guide}/waiting.mdx +0 -0
  275. /package/docs/{importing → v6/importing}/csv.mdx +0 -0
  276. /package/docs/{importing → v6/importing}/gherkin.mdx +0 -0
  277. /package/docs/{importing → v6/importing}/jira.mdx +0 -0
  278. /package/docs/{importing → v6/importing}/testrail.mdx +0 -0
  279. /package/docs/{integrations → v6/integrations}/electron.mdx +0 -0
  280. /package/docs/{integrations → v6/integrations}/netlify.mdx +0 -0
  281. /package/docs/{integrations → v6/integrations}/vercel.mdx +0 -0
  282. /package/docs/{interactive → v6/interactive}/explore.mdx +0 -0
  283. /package/docs/{interactive → v6/interactive}/run.mdx +0 -0
  284. /package/docs/{interactive → v6/interactive}/save.mdx +0 -0
  285. /package/docs/{overview → v6/overview}/faq.mdx +0 -0
  286. /package/docs/{overview → v6/overview}/performance.mdx +0 -0
  287. /package/docs/{overview → v6/overview}/quickstart.mdx +0 -0
  288. /package/docs/{overview → v6/overview}/what-is-testdriver.mdx +0 -0
  289. /package/docs/{scenarios → v6/scenarios}/ai-chatbot.mdx +0 -0
  290. /package/docs/{scenarios → v6/scenarios}/cookie-banner.mdx +0 -0
  291. /package/docs/{scenarios → v6/scenarios}/file-upload.mdx +0 -0
  292. /package/docs/{scenarios → v6/scenarios}/form-filling.mdx +0 -0
  293. /package/docs/{scenarios → v6/scenarios}/log-in.mdx +0 -0
  294. /package/docs/{scenarios → v6/scenarios}/pdf-generation.mdx +0 -0
  295. /package/docs/{scenarios → v6/scenarios}/spell-check.mdx +0 -0
  296. /package/docs/{security → v6/security}/action.mdx +0 -0
  297. /package/docs/{security → v6/security}/agent.mdx +0 -0
  298. /package/docs/{security → v6/security}/platform.mdx +0 -0
  299. /package/docs/{tutorials → v6/tutorials}/advanced-test.mdx +0 -0
  300. /package/docs/{tutorials → v6/tutorials}/basic-test.mdx +0 -0
@@ -0,0 +1,479 @@
1
+ ---
2
+ title: "Element Finding"
3
+ sidebarTitle: "Elements"
4
+ description: "Locate and interact with UI elements using AI"
5
+ icon: "mouse-pointer"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ TestDriver's element finding system uses AI to locate elements on screen using natural language descriptions. The `find()` method returns an `Element` object that you can interact with.
11
+
12
+ ## Finding Elements
13
+
14
+ ### find()
15
+
16
+ Locate an element on screen using a natural language description.
17
+
18
+ ```javascript
19
+ const element = await testdriver.find(description)
20
+ ```
21
+
22
+ **Parameters:**
23
+ - `description` (string) - Natural language description of the element to find
24
+
25
+ **Returns:** `Promise<Element>` - Element instance that has been located
26
+
27
+ **Example:**
28
+ ```javascript
29
+ // Find a button
30
+ const submitButton = await testdriver.find('the submit button');
31
+
32
+ // Find an input field with context
33
+ const emailField = await testdriver.find('email input field in the login form');
34
+
35
+ // Find an element by visual characteristics
36
+ const redButton = await testdriver.find('red button in the top right corner');
37
+ ```
38
+
39
+ <Tip>
40
+ Be specific in your descriptions. Include visual details, location context, or nearby text to improve accuracy.
41
+ </Tip>
42
+
43
+ ## Element Class
44
+
45
+ The `Element` class represents a located (or to-be-located) UI element. It provides methods for interaction and properties for element information.
46
+
47
+ ### Methods
48
+
49
+ #### found()
50
+
51
+ Check if the element was successfully located.
52
+
53
+ ```javascript
54
+ element.found()
55
+ ```
56
+
57
+ **Returns:** `boolean` - True if element coordinates were found
58
+
59
+ **Example:**
60
+ ```javascript
61
+ const element = await testdriver.find('login button');
62
+ if (element.found()) {
63
+ await element.click();
64
+ } else {
65
+ console.log('Element not found');
66
+ }
67
+ ```
68
+
69
+ #### find()
70
+
71
+ Re-locate the element, optionally with a new description.
72
+
73
+ ```javascript
74
+ await element.find(newDescription)
75
+ ```
76
+
77
+ **Parameters:**
78
+ - `newDescription` (string, optional) - New description to search for
79
+
80
+ **Returns:** `Promise<Element>` - This element instance
81
+
82
+ **Example:**
83
+ ```javascript
84
+ // Re-locate if the UI changed
85
+ const element = await testdriver.find('submit button');
86
+ // ... page updates ...
87
+ await element.find(); // Re-locate with same description
88
+
89
+ // Or update the description
90
+ await element.find('blue submit button'); // Now looking for blue button
91
+ ```
92
+
93
+ #### click()
94
+
95
+ Click on the element.
96
+
97
+ ```javascript
98
+ await element.click(action)
99
+ ```
100
+
101
+ **Parameters:**
102
+ - `action` (string, optional) - Type of click: `'click'` (default), `'double-click'`, `'right-click'`, `'hover'`, `'mouseDown'`, `'mouseUp'`
103
+
104
+ **Returns:** `Promise<void>`
105
+
106
+ **Example:**
107
+ ```javascript
108
+ const button = await testdriver.find('submit button');
109
+ await button.click(); // Regular click
110
+
111
+ const file = await testdriver.find('document.txt');
112
+ await file.click('double-click'); // Double-click
113
+
114
+ const menu = await testdriver.find('settings icon');
115
+ await menu.click('right-click'); // Right-click
116
+ ```
117
+
118
+ <Note>
119
+ The element must be found before clicking. The `find()` method automatically locates the element.
120
+ </Note>
121
+
122
+ #### hover()
123
+
124
+ Hover over the element without clicking.
125
+
126
+ ```javascript
127
+ await element.hover()
128
+ ```
129
+
130
+ **Returns:** `Promise<void>`
131
+
132
+ **Example:**
133
+ ```javascript
134
+ const tooltip = await testdriver.find('info icon');
135
+ await tooltip.hover();
136
+ // Wait to see tooltip
137
+ await new Promise(resolve => setTimeout(resolve, 1000));
138
+ ```
139
+
140
+ #### doubleClick()
141
+
142
+ Double-click on the element.
143
+
144
+ ```javascript
145
+ await element.doubleClick()
146
+ ```
147
+
148
+ **Returns:** `Promise<void>`
149
+
150
+ **Example:**
151
+ ```javascript
152
+ const file = await testdriver.find('README.txt file icon');
153
+ await file.doubleClick();
154
+ ```
155
+
156
+ #### rightClick()
157
+
158
+ Right-click on the element to open context menu.
159
+
160
+ ```javascript
161
+ await element.rightClick()
162
+ ```
163
+
164
+ **Returns:** `Promise<void>`
165
+
166
+ **Example:**
167
+ ```javascript
168
+ const folder = await testdriver.find('Documents folder');
169
+ await folder.rightClick();
170
+ ```
171
+
172
+ #### mouseDown() / mouseUp()
173
+
174
+ Press or release mouse button on the element (for drag operations).
175
+
176
+ ```javascript
177
+ await element.mouseDown()
178
+ await element.mouseUp()
179
+ ```
180
+
181
+ **Returns:** `Promise<void>`
182
+
183
+ **Example:**
184
+ ```javascript
185
+ // Drag and drop
186
+ const item = await testdriver.find('draggable item');
187
+ await item.mouseDown();
188
+
189
+ // Move to drop target (using coordinates or another element)
190
+ const target = await testdriver.find('drop zone');
191
+ await target.hover();
192
+ await target.mouseUp();
193
+ ```
194
+
195
+ ### Properties
196
+
197
+ Element properties provide additional information about located elements:
198
+
199
+ #### coordinates
200
+
201
+ Get the element's coordinates object.
202
+
203
+ ```javascript
204
+ const coords = element.getCoordinates()
205
+ // or access directly
206
+ element.coordinates
207
+ ```
208
+
209
+ **Returns:** Object with `{ x, y, centerX, centerY }` or `null`
210
+
211
+ **Example:**
212
+ ```javascript
213
+ const button = await testdriver.find('submit button');
214
+ const coords = button.coordinates;
215
+ console.log(`Top-left: (${coords.x}, ${coords.y})`);
216
+ console.log(`Center: (${coords.centerX}, ${coords.centerY})`);
217
+ ```
218
+
219
+ #### x, y, centerX, centerY
220
+
221
+ Direct access to coordinate values.
222
+
223
+ ```javascript
224
+ element.x // Top-left X coordinate
225
+ element.y // Top-left Y coordinate
226
+ element.centerX // Center X coordinate
227
+ element.centerY // Center Y coordinate
228
+ ```
229
+
230
+ **Example:**
231
+ ```javascript
232
+ const button = await testdriver.find('submit button');
233
+ console.log(`Button center: (${button.centerX}, ${button.centerY})`);
234
+ ```
235
+
236
+ #### screenshot
237
+
238
+ Get a base64-encoded screenshot of the element (if available).
239
+
240
+ ```javascript
241
+ element.screenshot
242
+ ```
243
+
244
+ **Returns:** `string | null` - Base64-encoded image
245
+
246
+ **Example:**
247
+ ```javascript
248
+ const element = await testdriver.find('error message');
249
+ if (element.screenshot) {
250
+ console.log('Element screenshot:', element.screenshot);
251
+ }
252
+ ```
253
+
254
+ #### text
255
+
256
+ Get text content from the element (if available).
257
+
258
+ ```javascript
259
+ element.text
260
+ ```
261
+
262
+ **Returns:** `string | null`
263
+
264
+ **Example:**
265
+ ```javascript
266
+ const message = await testdriver.find('notification message');
267
+ console.log('Message text:', message.text);
268
+ ```
269
+
270
+ #### confidence
271
+
272
+ Get the AI's confidence score for the element match.
273
+
274
+ ```javascript
275
+ element.confidence
276
+ ```
277
+
278
+ **Returns:** `number | null` - Confidence score (0-1)
279
+
280
+ **Example:**
281
+ ```javascript
282
+ const element = await testdriver.find('submit button');
283
+ if (element.confidence < 0.8) {
284
+ console.warn('Low confidence match:', element.confidence);
285
+ }
286
+ ```
287
+
288
+ #### width, height
289
+
290
+ Get element dimensions (if available).
291
+
292
+ ```javascript
293
+ element.width
294
+ element.height
295
+ ```
296
+
297
+ **Returns:** `number | null`
298
+
299
+ #### boundingBox
300
+
301
+ Get the complete bounding box information.
302
+
303
+ ```javascript
304
+ element.boundingBox
305
+ ```
306
+
307
+ **Returns:** `Object | null` - Bounding box with coordinates and dimensions
308
+
309
+ #### label
310
+
311
+ Get the element's label or accessible name (if available).
312
+
313
+ ```javascript
314
+ element.label
315
+ ```
316
+
317
+ **Returns:** `string | null`
318
+
319
+ ## Polling for Elements
320
+
321
+ Use polling to wait for elements that may not be immediately visible:
322
+
323
+ ```javascript
324
+ // Poll until element appears
325
+ let loginButton;
326
+ const maxAttempts = 30;
327
+
328
+ for (let i = 0; i < maxAttempts; i++) {
329
+ loginButton = await testdriver.find('login button');
330
+ if (loginButton.found()) break;
331
+ await new Promise(resolve => setTimeout(resolve, 1000));
332
+ }
333
+
334
+ if (loginButton.found()) {
335
+ await loginButton.click();
336
+ } else {
337
+ throw new Error('Login button never appeared');
338
+ }
339
+ ```
340
+
341
+ **Helper function for polling:**
342
+ ```javascript
343
+ async function waitForElement(testdriver, description, timeout = 30000) {
344
+ const startTime = Date.now();
345
+
346
+ while (Date.now() - startTime < timeout) {
347
+ const element = await testdriver.find(description);
348
+ if (element.found()) return element;
349
+ await new Promise(resolve => setTimeout(resolve, 1000));
350
+ }
351
+
352
+ throw new Error(`Element "${description}" not found after ${timeout}ms`);
353
+ }
354
+
355
+ // Usage
356
+ const button = await waitForElement(testdriver, 'submit button', 10000);
357
+ await button.click();
358
+ ```
359
+
360
+ ## Examples
361
+
362
+ ### Basic Element Interaction
363
+
364
+ ```javascript
365
+ // Find and click
366
+ const submitButton = await testdriver.find('submit button');
367
+ await submitButton.click();
368
+
369
+ // Find, verify, then interact
370
+ const emailInput = await testdriver.find('email input field');
371
+ if (emailInput.found()) {
372
+ await emailInput.click();
373
+ await testdriver.type('user@example.com');
374
+ }
375
+ ```
376
+
377
+ ### Working with Forms
378
+
379
+ ```javascript
380
+ // Fill out a multi-field form
381
+ const nameField = await testdriver.find('name input field');
382
+ await nameField.click();
383
+ await testdriver.type('John Doe');
384
+
385
+ const emailField = await testdriver.find('email input field');
386
+ await emailField.click();
387
+ await testdriver.type('john@example.com');
388
+
389
+ const submitButton = await testdriver.find('submit button');
390
+ await submitButton.click();
391
+ ```
392
+
393
+ ### Conditional Interactions
394
+
395
+ ```javascript
396
+ // Check if element exists before interacting
397
+ const closeButton = await testdriver.find('close popup button');
398
+
399
+ if (closeButton.found()) {
400
+ await closeButton.click();
401
+ console.log('Popup closed');
402
+ } else {
403
+ console.log('No popup to close');
404
+ }
405
+ ```
406
+
407
+ ### Re-locating Dynamic Elements
408
+
409
+ ```javascript
410
+ // Element that moves or changes
411
+ const notification = await testdriver.find('success notification');
412
+
413
+ // Do something that might cause it to move
414
+ await testdriver.scroll('down', 300);
415
+
416
+ // Re-locate the element
417
+ await notification.find();
418
+
419
+ if (notification.found()) {
420
+ await notification.click();
421
+ }
422
+ ```
423
+
424
+ ## Best Practices
425
+
426
+ <AccordionGroup>
427
+ <Accordion title="Be specific with descriptions">
428
+ Include visual details, position context, and nearby text:
429
+
430
+ ```javascript
431
+ // ❌ Too vague
432
+ await testdriver.find('button');
433
+
434
+ // ✅ Specific
435
+ await testdriver.find('blue submit button below the email field');
436
+ ```
437
+ </Accordion>
438
+
439
+ <Accordion title="Check if element was found">
440
+ Always verify elements were located before interacting:
441
+
442
+ ```javascript
443
+ const element = await testdriver.find('submit button');
444
+ if (!element.found()) {
445
+ throw new Error('Submit button not found');
446
+ }
447
+ await element.click();
448
+ ```
449
+ </Accordion>
450
+
451
+ <Accordion title="Use polling for dynamic content">
452
+ Don't assume elements are immediately visible:
453
+
454
+ ```javascript
455
+ let element;
456
+ for (let i = 0; i < 30; i++) {
457
+ element = await testdriver.find('loading complete message');
458
+ if (element.found()) break;
459
+ await new Promise(resolve => setTimeout(resolve, 1000));
460
+ }
461
+ ```
462
+ </Accordion>
463
+
464
+ <Accordion title="Reuse element references when possible">
465
+ If you need to interact with the same element multiple times, reuse the reference:
466
+
467
+ ```javascript
468
+ const input = await testdriver.find('search input');
469
+ await input.click();
470
+ await testdriver.type('first search');
471
+ await testdriver.pressKeys(['enter']);
472
+
473
+ // Re-use the same element reference
474
+ await input.click();
475
+ await testdriver.pressKeys(['ctrl', 'a']); // Select all
476
+ await testdriver.type('second search');
477
+ ```
478
+ </Accordion>
479
+ </AccordionGroup>