testdriverai 6.2.2 → 7.0.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 (264) 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/MIGRATION.md +389 -0
  5. package/PLUGIN_MIGRATION.md +222 -0
  6. package/PROMPT_CACHE.md +200 -0
  7. package/SDK_LOGGING.md +222 -0
  8. package/SDK_MIGRATION.md +474 -0
  9. package/SDK_README.md +1122 -0
  10. package/{testdriver → _testdriver}/acceptance/drag-and-drop.yaml +2 -2
  11. package/{testdriver → _testdriver}/acceptance/snippets/login.yaml +1 -1
  12. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  13. package/{testdriver → _testdriver}/examples/web/lifecycle/prerun.yaml +6 -1
  14. package/{testdriver → _testdriver}/lifecycle/postrun.yaml +3 -2
  15. package/_testdriver/lifecycle/prerun.yaml +15 -0
  16. package/{testdriver → _testdriver}/lifecycle/provision.yaml +7 -2
  17. package/agent/index.js +258 -68
  18. package/agent/interface.js +15 -0
  19. package/agent/lib/cache.js +142 -0
  20. package/agent/lib/commander.js +1 -39
  21. package/agent/lib/commands.js +143 -188
  22. package/agent/lib/redraw.js +6 -3
  23. package/agent/lib/sandbox.js +19 -5
  24. package/agent/lib/sdk.js +1 -0
  25. package/agent/lib/system.js +0 -3
  26. package/agent/lib/validation.js +1 -7
  27. package/debug-locate-response.js +82 -0
  28. package/debug-screenshot-1763401388589.png +0 -0
  29. package/debugger/index.html +15 -4
  30. package/docs/ARCHITECTURE.md +424 -0
  31. package/docs/AWESOME_LOGS_QUICK_REF.md +100 -0
  32. package/docs/QUICK_START_TEST_RECORDING.md +215 -0
  33. package/docs/SDK_AWESOME_LOGS.md +468 -0
  34. package/docs/TEST_RECORDING.md +388 -0
  35. package/docs/docs.json +232 -152
  36. package/docs/sdk-browser-rendering.md +167 -0
  37. package/docs/v6/getting-started/self-hosting.mdx +407 -0
  38. package/docs/{guide → v6/guide}/dashcam.mdx +1 -1
  39. package/docs/{guide → v6/guide}/environment-variables.mdx +4 -5
  40. package/docs/{guide → v6/guide}/lifecycle.mdx +1 -1
  41. package/docs/v6/overview/comparison.mdx +101 -0
  42. package/docs/v7/README.md +135 -0
  43. package/docs/v7/api/ai.mdx +205 -0
  44. package/docs/v7/api/assert.mdx +285 -0
  45. package/docs/v7/api/assertions.mdx +403 -0
  46. package/docs/v7/api/click.mdx +287 -0
  47. package/docs/v7/api/client.mdx +322 -0
  48. package/docs/v7/api/elements.mdx +479 -0
  49. package/docs/v7/api/exec.mdx +346 -0
  50. package/docs/v7/api/find.mdx +316 -0
  51. package/docs/v7/api/focusApplication.mdx +294 -0
  52. package/docs/v7/api/hover.mdx +279 -0
  53. package/docs/v7/api/pressKeys.mdx +349 -0
  54. package/docs/v7/api/sandbox.mdx +404 -0
  55. package/docs/v7/api/scroll.mdx +300 -0
  56. package/docs/v7/api/type.mdx +314 -0
  57. package/docs/v7/commands/assert.mdx +45 -0
  58. package/docs/v7/commands/exec.mdx +282 -0
  59. package/docs/v7/commands/focus-application.mdx +44 -0
  60. package/docs/v7/commands/hover-image.mdx +69 -0
  61. package/docs/v7/commands/hover-text.mdx +47 -0
  62. package/docs/v7/commands/if.mdx +53 -0
  63. package/docs/v7/commands/match-image.mdx +67 -0
  64. package/docs/v7/commands/press-keys.mdx +87 -0
  65. package/docs/v7/commands/remember.mdx +49 -0
  66. package/docs/v7/commands/run.mdx +44 -0
  67. package/docs/v7/commands/scroll-until-image.mdx +66 -0
  68. package/docs/v7/commands/scroll-until-text.mdx +60 -0
  69. package/docs/v7/commands/scroll.mdx +69 -0
  70. package/docs/v7/commands/type.mdx +45 -0
  71. package/docs/v7/commands/wait-for-image.mdx +54 -0
  72. package/docs/v7/commands/wait-for-text.mdx +48 -0
  73. package/docs/v7/commands/wait.mdx +45 -0
  74. package/docs/v7/getting-started/quickstart.mdx +199 -0
  75. package/docs/v7/guides/migration.mdx +562 -0
  76. package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
  77. package/docs/v7/playwright.mdx +342 -0
  78. package/eslint.config.js +19 -1
  79. package/examples/run-tests-with-recording.sh +70 -0
  80. package/examples/screenshot-example.js +63 -0
  81. package/examples/sdk-awesome-logs-demo.js +177 -0
  82. package/examples/sdk-cache-thresholds.js +96 -0
  83. package/examples/sdk-element-properties.js +155 -0
  84. package/examples/sdk-simple-example.js +65 -0
  85. package/examples/test-recording-example.test.js +166 -0
  86. package/interfaces/cli/lib/base.js +10 -4
  87. package/interfaces/logger.js +2 -1
  88. package/interfaces/shared-test-state.mjs +69 -0
  89. package/interfaces/vitest-plugin.mjs +744 -0
  90. package/mcp-server/AI_GUIDELINES.md +57 -0
  91. package/package.json +18 -5
  92. package/schema.json +8 -29
  93. package/scripts/view-test-results.mjs +96 -0
  94. package/sdk-log-formatter.js +714 -0
  95. package/sdk.d.ts +735 -0
  96. package/sdk.js +1906 -0
  97. package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
  98. package/setup/aws/cloudformation.yaml +9 -2
  99. package/test/mcp-example-test.yaml +27 -0
  100. package/test-find-api.js +73 -0
  101. package/test-prompt-cache.js +96 -0
  102. package/test-sandbox-render.js +28 -0
  103. package/test-sdk-methods.js +15 -0
  104. package/test-sdk-refactor.js +53 -0
  105. package/test-stack-trace.mjs +57 -0
  106. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +61 -0
  107. package/testdriver/acceptance-sdk/README.md +128 -0
  108. package/testdriver/acceptance-sdk/TEST_REPORTING.md +245 -0
  109. package/testdriver/acceptance-sdk/assert.test.mjs +44 -0
  110. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +70 -0
  111. package/testdriver/acceptance-sdk/element-not-found.test.mjs +38 -0
  112. package/testdriver/acceptance-sdk/exec-js.test.mjs +55 -0
  113. package/testdriver/acceptance-sdk/exec-output.test.mjs +71 -0
  114. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +69 -0
  115. package/testdriver/acceptance-sdk/focus-window.test.mjs +48 -0
  116. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +41 -0
  117. package/testdriver/acceptance-sdk/hover-image.test.mjs +43 -0
  118. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +50 -0
  119. package/testdriver/acceptance-sdk/hover-text.test.mjs +41 -0
  120. package/testdriver/acceptance-sdk/match-image.test.mjs +48 -0
  121. package/testdriver/acceptance-sdk/press-keys.test.mjs +64 -0
  122. package/testdriver/acceptance-sdk/prompt.test.mjs +45 -0
  123. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +52 -0
  124. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +51 -0
  125. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +42 -0
  126. package/testdriver/acceptance-sdk/scroll.test.mjs +50 -0
  127. package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
  128. package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +239 -0
  129. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +648 -0
  130. package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
  131. package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
  132. package/testdriver/acceptance-sdk/type.test.mjs +84 -0
  133. package/verify-element-api.js +89 -0
  134. package/verify-types.js +0 -0
  135. package/vitest.config.example.js +19 -0
  136. package/vitest.config.mjs +65 -0
  137. package/vitest.config.mjs.bak +44 -0
  138. package/.github/workflows/acceptance-v6.yml +0 -169
  139. package/docs/overview/comparison.mdx +0 -82
  140. package/testdriver/lifecycle/prerun.yaml +0 -17
  141. /package/{testdriver/examples/desktop/lifecycle/prerun.yaml → .env.example} +0 -0
  142. /package/{testdriver → _testdriver}/acceptance/assert.yaml +0 -0
  143. /package/{testdriver → _testdriver}/acceptance/dashcam.yaml +0 -0
  144. /package/{testdriver → _testdriver}/acceptance/embed.yaml +0 -0
  145. /package/{testdriver → _testdriver}/acceptance/exec-js.yaml +0 -0
  146. /package/{testdriver → _testdriver}/acceptance/exec-output.yaml +0 -0
  147. /package/{testdriver → _testdriver}/acceptance/exec-shell.yaml +0 -0
  148. /package/{testdriver → _testdriver}/acceptance/focus-window.yaml +0 -0
  149. /package/{testdriver → _testdriver}/acceptance/hover-image.yaml +0 -0
  150. /package/{testdriver → _testdriver}/acceptance/hover-text-with-description.yaml +0 -0
  151. /package/{testdriver → _testdriver}/acceptance/hover-text.yaml +0 -0
  152. /package/{testdriver → _testdriver}/acceptance/if-else.yaml +0 -0
  153. /package/{testdriver → _testdriver}/acceptance/match-image.yaml +0 -0
  154. /package/{testdriver → _testdriver}/acceptance/press-keys.yaml +0 -0
  155. /package/{testdriver → _testdriver}/acceptance/prompt.yaml +0 -0
  156. /package/{testdriver → _testdriver}/acceptance/remember.yaml +0 -0
  157. /package/{testdriver → _testdriver}/acceptance/screenshots/cart.png +0 -0
  158. /package/{testdriver → _testdriver}/acceptance/scroll-keyboard.yaml +0 -0
  159. /package/{testdriver → _testdriver}/acceptance/scroll-until-image.yaml +0 -0
  160. /package/{testdriver → _testdriver}/acceptance/scroll-until-text.yaml +0 -0
  161. /package/{testdriver → _testdriver}/acceptance/scroll.yaml +0 -0
  162. /package/{testdriver → _testdriver}/acceptance/snippets/match-cart.yaml +0 -0
  163. /package/{testdriver → _testdriver}/acceptance/type.yaml +0 -0
  164. /package/{testdriver → _testdriver}/behavior/failure.yaml +0 -0
  165. /package/{testdriver → _testdriver}/behavior/hover-text.yaml +0 -0
  166. /package/{testdriver → _testdriver}/behavior/lifecycle/postrun.yaml +0 -0
  167. /package/{testdriver → _testdriver}/behavior/lifecycle/prerun.yaml +0 -0
  168. /package/{testdriver → _testdriver}/behavior/lifecycle/provision.yaml +0 -0
  169. /package/{testdriver → _testdriver}/behavior/secrets.yaml +0 -0
  170. /package/{testdriver → _testdriver}/edge-cases/dashcam-chrome.yaml +0 -0
  171. /package/{testdriver → _testdriver}/edge-cases/exec-pwsh-multiline.yaml +0 -0
  172. /package/{testdriver → _testdriver}/edge-cases/js-exception.yaml +0 -0
  173. /package/{testdriver → _testdriver}/edge-cases/js-promise.yaml +0 -0
  174. /package/{testdriver → _testdriver}/edge-cases/lifecycle/postrun.yaml +0 -0
  175. /package/{testdriver → _testdriver}/edge-cases/prompt-in-middle.yaml +0 -0
  176. /package/{testdriver → _testdriver}/edge-cases/prompt-nested.yaml +0 -0
  177. /package/{testdriver → _testdriver}/edge-cases/success-test.yaml +0 -0
  178. /package/{testdriver → _testdriver}/examples/android/example.yaml +0 -0
  179. /package/{testdriver → _testdriver}/examples/android/lifecycle/postrun.yaml +0 -0
  180. /package/{testdriver → _testdriver}/examples/android/lifecycle/provision.yaml +0 -0
  181. /package/{testdriver → _testdriver}/examples/android/readme.md +0 -0
  182. /package/{testdriver → _testdriver}/examples/chrome-extension/lifecycle/provision.yaml +0 -0
  183. /package/{testdriver → _testdriver}/examples/desktop/lifecycle/provision.yaml +0 -0
  184. /package/{testdriver → _testdriver}/examples/vscode-extension/lifecycle/provision.yaml +0 -0
  185. /package/{testdriver → _testdriver}/examples/web/lifecycle/postrun.yaml +0 -0
  186. /package/docs/{account → v6/account}/dashboard.mdx +0 -0
  187. /package/docs/{account → v6/account}/enterprise.mdx +0 -0
  188. /package/docs/{account → v6/account}/pricing.mdx +0 -0
  189. /package/docs/{account → v6/account}/projects.mdx +0 -0
  190. /package/docs/{account → v6/account}/team.mdx +0 -0
  191. /package/docs/{action → v6/action}/ami.mdx +0 -0
  192. /package/docs/{action → v6/action}/performance.mdx +0 -0
  193. /package/docs/{action → v6/action}/secrets.mdx +0 -0
  194. /package/docs/{apps → v6/apps}/chrome-extensions.mdx +0 -0
  195. /package/docs/{apps → v6/apps}/desktop-apps.mdx +0 -0
  196. /package/docs/{apps → v6/apps}/mobile-apps.mdx +0 -0
  197. /package/docs/{apps → v6/apps}/static-websites.mdx +0 -0
  198. /package/docs/{apps → v6/apps}/tauri-apps.mdx +0 -0
  199. /package/docs/{bugs → v6/bugs}/jira.mdx +0 -0
  200. /package/docs/{cli → v6/cli}/overview.mdx +0 -0
  201. /package/docs/{commands → v6/commands}/assert.mdx +0 -0
  202. /package/docs/{commands → v6/commands}/exec.mdx +0 -0
  203. /package/docs/{commands → v6/commands}/focus-application.mdx +0 -0
  204. /package/docs/{commands → v6/commands}/hover-image.mdx +0 -0
  205. /package/docs/{commands → v6/commands}/hover-text.mdx +0 -0
  206. /package/docs/{commands → v6/commands}/if.mdx +0 -0
  207. /package/docs/{commands → v6/commands}/match-image.mdx +0 -0
  208. /package/docs/{commands → v6/commands}/press-keys.mdx +0 -0
  209. /package/docs/{commands → v6/commands}/remember.mdx +0 -0
  210. /package/docs/{commands → v6/commands}/run.mdx +0 -0
  211. /package/docs/{commands → v6/commands}/scroll-until-image.mdx +0 -0
  212. /package/docs/{commands → v6/commands}/scroll-until-text.mdx +0 -0
  213. /package/docs/{commands → v6/commands}/scroll.mdx +0 -0
  214. /package/docs/{commands → v6/commands}/type.mdx +0 -0
  215. /package/docs/{commands → v6/commands}/wait-for-image.mdx +0 -0
  216. /package/docs/{commands → v6/commands}/wait-for-text.mdx +0 -0
  217. /package/docs/{commands → v6/commands}/wait.mdx +0 -0
  218. /package/docs/{exporting → v6/exporting}/junit.mdx +0 -0
  219. /package/docs/{exporting → v6/exporting}/playwright.mdx +0 -0
  220. /package/docs/{features → v6/features}/auto-healing.mdx +0 -0
  221. /package/docs/{features → v6/features}/generation.mdx +0 -0
  222. /package/docs/{features → v6/features}/parallel-testing.mdx +0 -0
  223. /package/docs/{features → v6/features}/reusable-snippets.mdx +0 -0
  224. /package/docs/{features → v6/features}/selectorless.mdx +0 -0
  225. /package/docs/{features → v6/features}/visual-assertions.mdx +0 -0
  226. /package/docs/{getting-started → v6/getting-started}/ci.mdx +0 -0
  227. /package/docs/{getting-started → v6/getting-started}/cli.mdx +0 -0
  228. /package/docs/{getting-started → v6/getting-started}/editing.mdx +0 -0
  229. /package/docs/{getting-started → v6/getting-started}/playwright.mdx +0 -0
  230. /package/docs/{getting-started → v6/getting-started}/running.mdx +0 -0
  231. /package/docs/{getting-started → v6/getting-started}/vscode.mdx +0 -0
  232. /package/docs/{guide → v6/guide}/assertions.mdx +0 -0
  233. /package/docs/{guide → v6/guide}/authentication.mdx +0 -0
  234. /package/docs/{guide → v6/guide}/code.mdx +0 -0
  235. /package/docs/{guide → v6/guide}/locating.mdx +0 -0
  236. /package/docs/{guide → v6/guide}/protips.mdx +0 -0
  237. /package/docs/{guide → v6/guide}/variables.mdx +0 -0
  238. /package/docs/{guide → v6/guide}/waiting.mdx +0 -0
  239. /package/docs/{importing → v6/importing}/csv.mdx +0 -0
  240. /package/docs/{importing → v6/importing}/gherkin.mdx +0 -0
  241. /package/docs/{importing → v6/importing}/jira.mdx +0 -0
  242. /package/docs/{importing → v6/importing}/testrail.mdx +0 -0
  243. /package/docs/{integrations → v6/integrations}/electron.mdx +0 -0
  244. /package/docs/{integrations → v6/integrations}/netlify.mdx +0 -0
  245. /package/docs/{integrations → v6/integrations}/vercel.mdx +0 -0
  246. /package/docs/{interactive → v6/interactive}/explore.mdx +0 -0
  247. /package/docs/{interactive → v6/interactive}/run.mdx +0 -0
  248. /package/docs/{interactive → v6/interactive}/save.mdx +0 -0
  249. /package/docs/{overview → v6/overview}/faq.mdx +0 -0
  250. /package/docs/{overview → v6/overview}/performance.mdx +0 -0
  251. /package/docs/{overview → v6/overview}/quickstart.mdx +0 -0
  252. /package/docs/{overview → v6/overview}/what-is-testdriver.mdx +0 -0
  253. /package/docs/{scenarios → v6/scenarios}/ai-chatbot.mdx +0 -0
  254. /package/docs/{scenarios → v6/scenarios}/cookie-banner.mdx +0 -0
  255. /package/docs/{scenarios → v6/scenarios}/file-upload.mdx +0 -0
  256. /package/docs/{scenarios → v6/scenarios}/form-filling.mdx +0 -0
  257. /package/docs/{scenarios → v6/scenarios}/log-in.mdx +0 -0
  258. /package/docs/{scenarios → v6/scenarios}/pdf-generation.mdx +0 -0
  259. /package/docs/{scenarios → v6/scenarios}/spell-check.mdx +0 -0
  260. /package/docs/{security → v6/security}/action.mdx +0 -0
  261. /package/docs/{security → v6/security}/agent.mdx +0 -0
  262. /package/docs/{security → v6/security}/platform.mdx +0 -0
  263. /package/docs/{tutorials → v6/tutorials}/advanced-test.mdx +0 -0
  264. /package/docs/{tutorials → v6/tutorials}/basic-test.mdx +0 -0
@@ -0,0 +1,346 @@
1
+ ---
2
+ title: "exec()"
3
+ sidebarTitle: "exec"
4
+ description: "Execute code or shell commands in the sandbox"
5
+ icon: "terminal"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ Execute JavaScript code in the browser or PowerShell commands in the Windows sandbox environment.
11
+
12
+ ## Syntax
13
+
14
+ ```javascript
15
+ await testdriver.exec(language, code, timeout, silent)
16
+ ```
17
+
18
+ ## Parameters
19
+
20
+ <ParamField path="language" type="string" required>
21
+ Language to execute: `'js'` (JavaScript) or `'pwsh'` (PowerShell)
22
+ </ParamField>
23
+
24
+ <ParamField path="code" type="string" required>
25
+ Code or command to execute
26
+ </ParamField>
27
+
28
+ <ParamField path="timeout" type="number" required>
29
+ Timeout in milliseconds
30
+ </ParamField>
31
+
32
+ <ParamField path="silent" type="boolean" default="false">
33
+ Suppress output if `true`
34
+ </ParamField>
35
+
36
+ ## Returns
37
+
38
+ `Promise<string>` - Command output
39
+
40
+ ## JavaScript Execution
41
+
42
+ Execute JavaScript in the browser context (Windows sandbox only).
43
+
44
+ ### DOM Manipulation
45
+
46
+ ```javascript
47
+ // Click an element via JavaScript
48
+ await testdriver.exec('js', `
49
+ document.querySelector('#submit-button').click();
50
+ `, 5000);
51
+
52
+ // Fill a form
53
+ await testdriver.exec('js', `
54
+ document.querySelector('#username').value = 'testuser';
55
+ document.querySelector('#password').value = 'password123';
56
+ document.querySelector('#login-form').submit();
57
+ `, 5000);
58
+
59
+ // Scroll to element
60
+ await testdriver.exec('js', `
61
+ document.querySelector('#footer').scrollIntoView();
62
+ `, 5000);
63
+ ```
64
+
65
+ ### Reading Page Data
66
+
67
+ ```javascript
68
+ // Get page title
69
+ const title = await testdriver.exec('js', 'document.title', 5000);
70
+ console.log('Page title:', title);
71
+
72
+ // Get all links
73
+ const links = await testdriver.exec('js', `
74
+ Array.from(document.querySelectorAll('a'))
75
+ .map(a => a.href)
76
+ .join('\\n')
77
+ `, 5000);
78
+
79
+ // Check if element exists
80
+ const exists = await testdriver.exec('js', `
81
+ document.querySelector('.error-message') !== null
82
+ `, 5000);
83
+
84
+ // Get element text
85
+ const text = await testdriver.exec('js', `
86
+ document.querySelector('.notification').textContent
87
+ `, 5000);
88
+ ```
89
+
90
+ ## PowerShell Execution
91
+
92
+ Execute PowerShell commands in the Windows sandbox.
93
+
94
+ ### Software Installation
95
+
96
+ ```javascript
97
+ // Install npm package globally
98
+ await testdriver.exec('pwsh', 'npm install -g http-server', 30000);
99
+
100
+ // Install via Chocolatey
101
+ await testdriver.exec('pwsh', 'choco install firefox -y', 60000);
102
+
103
+ // Download and run installer
104
+ await testdriver.exec('pwsh', `
105
+ Invoke-WebRequest -Uri "https://example.com/setup.exe" -OutFile "C:\\setup.exe"
106
+ Start-Process -FilePath "C:\\setup.exe" -ArgumentList "/S" -Wait
107
+ `, 120000);
108
+ ```
109
+
110
+ ### File Operations
111
+
112
+ ```javascript
113
+ // Create a file
114
+ await testdriver.exec('pwsh', `
115
+ Set-Content -Path "C:\\test.txt" -Value "Hello World"
116
+ `, 5000);
117
+
118
+ // Read a file
119
+ const content = await testdriver.exec('pwsh',
120
+ 'Get-Content -Path "C:\\test.txt"',
121
+ 5000
122
+ );
123
+
124
+ // Copy files
125
+ await testdriver.exec('pwsh',
126
+ 'Copy-Item -Path "C:\\source.txt" -Destination "C:\\dest.txt"',
127
+ 5000
128
+ );
129
+
130
+ // Delete files
131
+ await testdriver.exec('pwsh',
132
+ 'Remove-Item -Path "C:\\test.txt"',
133
+ 5000
134
+ );
135
+
136
+ // List directory
137
+ const files = await testdriver.exec('pwsh',
138
+ 'Get-ChildItem -Path "C:\\Users\\testdriver\\Documents"',
139
+ 5000
140
+ );
141
+ ```
142
+
143
+ ### Process Management
144
+
145
+ ```javascript
146
+ // List running processes
147
+ const processes = await testdriver.exec('pwsh', 'Get-Process', 5000);
148
+
149
+ // Start application
150
+ await testdriver.exec('pwsh', `
151
+ Start-Process "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" -ArgumentList "--start-maximized", "https://example.com"
152
+ `, 5000);
153
+
154
+ // Kill a process
155
+ await testdriver.exec('pwsh', 'Stop-Process -Name "chrome" -Force', 5000);
156
+
157
+ // Wait for process
158
+ await testdriver.exec('pwsh', 'Start-Process notepad -Wait', 30000);
159
+ ```
160
+
161
+ ### Environment Variables
162
+
163
+ ```javascript
164
+ // Set environment variable (session)
165
+ await testdriver.exec('pwsh', '$env:MY_VAR = "value"', 5000);
166
+
167
+ // Get environment variable
168
+ const value = await testdriver.exec('pwsh', '$env:MY_VAR', 5000);
169
+
170
+ // Set persistent environment variable
171
+ await testdriver.exec('pwsh', `
172
+ [Environment]::SetEnvironmentVariable("MY_VAR", "value", "User")
173
+ `, 5000);
174
+ ```
175
+
176
+ ### Network Operations
177
+
178
+ ```javascript
179
+ // Test connectivity
180
+ const pingResult = await testdriver.exec('pwsh',
181
+ 'Test-NetConnection google.com',
182
+ 10000
183
+ );
184
+
185
+ // Download file
186
+ await testdriver.exec('pwsh', `
187
+ Invoke-WebRequest -Uri "https://example.com/file.zip" -OutFile "C:\\Downloads\\file.zip"
188
+ `, 30000);
189
+
190
+ // Check if port is open
191
+ const portOpen = await testdriver.exec('pwsh',
192
+ 'Test-NetConnection -ComputerName localhost -Port 3000',
193
+ 5000
194
+ );
195
+ ```
196
+
197
+ ## Silent Execution
198
+
199
+ Suppress output for background operations:
200
+
201
+ ```javascript
202
+ // Silent installation
203
+ await testdriver.exec('pwsh', 'npm install -g some-package', 30000, true);
204
+
205
+ // Start background process
206
+ await testdriver.exec('pwsh', 'Start-Process notepad', 5000, true);
207
+
208
+ // Run setup script silently
209
+ await testdriver.exec('pwsh', '.\\setup.ps1', 60000, true);
210
+ ```
211
+
212
+ ## Best Practices
213
+
214
+ <Check>
215
+ **Use appropriate timeouts**
216
+
217
+ ```javascript
218
+ // Quick operations: 5000ms
219
+ await testdriver.exec('js', 'document.title', 5000);
220
+
221
+ // Installations: 30000-60000ms
222
+ await testdriver.exec('pwsh', 'npm install -g package', 30000);
223
+
224
+ // Downloads or complex operations: 60000-120000ms
225
+ await testdriver.exec('pwsh', 'Install-Module Something', 120000);
226
+ ```
227
+ </Check>
228
+
229
+ <Check>
230
+ **Handle errors gracefully**
231
+
232
+ ```javascript
233
+ try {
234
+ await testdriver.exec('pwsh', 'Some-Command', 5000);
235
+ } catch (error) {
236
+ console.error('Command failed:', error.message);
237
+ // Fallback or retry logic
238
+ }
239
+ ```
240
+ </Check>
241
+
242
+ <Check>
243
+ **Use silent mode for background tasks**
244
+
245
+ ```javascript
246
+ // Silent install
247
+ await testdriver.exec('pwsh', 'npm install -g tool', 30000, true);
248
+
249
+ // Background service
250
+ await testdriver.exec('pwsh', 'Start-Service MyService', 5000, true);
251
+ ```
252
+ </Check>
253
+
254
+ <Warning>
255
+ **Escape strings properly in PowerShell**
256
+
257
+ Use proper escaping for special characters:
258
+
259
+ ```javascript
260
+ // Use backticks for newlines
261
+ await testdriver.exec('pwsh', `
262
+ Write-Host "Line 1\`nLine 2"
263
+ `, 5000);
264
+
265
+ // Use single quotes to avoid variable expansion
266
+ await testdriver.exec('pwsh',
267
+ "Write-Host 'Text with $special chars'",
268
+ 5000
269
+ );
270
+ ```
271
+ </Warning>
272
+
273
+ ## Complete Example
274
+
275
+ ```javascript
276
+ import { beforeAll, afterAll, describe, it } from 'vitest';
277
+ import TestDriver from 'testdriverai';
278
+
279
+ describe('Code Execution', () => {
280
+ let testdriver;
281
+
282
+ beforeAll(async () => {
283
+ client = new TestDriver(process.env.TD_API_KEY);
284
+ await testdriver.auth();
285
+ await testdriver.connect({ newSandbox: true });
286
+ });
287
+
288
+ afterAll(async () => {
289
+ await testdriver.disconnect();
290
+ });
291
+
292
+ it('should execute JavaScript in browser', async () => {
293
+ await testdriver.focusApplication('Google Chrome');
294
+
295
+ // Get page info via JavaScript
296
+ const title = await testdriver.exec('js', 'document.title', 5000);
297
+ console.log('Page title:', title);
298
+
299
+ // Manipulate DOM
300
+ await testdriver.exec('js', `
301
+ document.querySelector('#username').value = 'testuser';
302
+ `, 5000);
303
+
304
+ // Verify
305
+ const value = await testdriver.exec('js', `
306
+ document.querySelector('#username').value
307
+ `, 5000);
308
+
309
+ expect(value).toBe('testuser');
310
+ });
311
+
312
+ it('should install and use tools', async () => {
313
+ // Install tool
314
+ await testdriver.exec('pwsh', 'npm install -g http-server', 30000, true);
315
+
316
+ // Create HTML file
317
+ await testdriver.exec('pwsh', `
318
+ Set-Content -Path "C:\\index.html" -Value "<h1>Test Page</h1>"
319
+ `, 5000);
320
+
321
+ // Start server in background
322
+ await testdriver.exec('pwsh', `
323
+ Start-Process pwsh -ArgumentList "-Command", "http-server C:\\ -p 8080"
324
+ `, 5000, true);
325
+
326
+ await new Promise(r => setTimeout(r, 3000));
327
+
328
+ // Launch browser
329
+ await testdriver.exec('pwsh', `
330
+ Start-Process chrome -ArgumentList "http://localhost:8080"
331
+ `, 5000);
332
+
333
+ await testdriver.focusApplication('Google Chrome');
334
+
335
+ // Verify page loaded
336
+ const content = await testdriver.exec('js', 'document.body.textContent', 5000);
337
+ expect(content).toContain('Test Page');
338
+ });
339
+ });
340
+ ```
341
+
342
+ ## Related Methods
343
+
344
+ - [`focusApplication()`](/v7/api/focusApplication) - Focus apps before exec
345
+ - [`find()`](/v7/api/find) - Locate elements (alternative to DOM manipulation)
346
+ - [`type()`](/v7/api/type) - Type text (alternative to JS form filling)
@@ -0,0 +1,316 @@
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
+ ```
17
+
18
+ ## Parameters
19
+
20
+ <ParamField path="description" type="string" required>
21
+ Natural language description of the element to find
22
+ </ParamField>
23
+
24
+ ## Returns
25
+
26
+ `Promise<Element>` - Element instance that has been automatically located
27
+
28
+ ## Examples
29
+
30
+ ### Basic Element Finding
31
+
32
+ ```javascript
33
+ // Find by role
34
+ const button = await testdriver.find('submit button');
35
+ const input = await testdriver.find('email input field');
36
+
37
+ // Find by text content
38
+ const link = await testdriver.find('Contact Us link');
39
+ const heading = await testdriver.find('Welcome heading');
40
+
41
+ // Find by visual appearance
42
+ const icon = await testdriver.find('red warning icon');
43
+ const image = await testdriver.find('company logo image');
44
+ ```
45
+
46
+ ### Finding with Context
47
+
48
+ ```javascript
49
+ // Provide location context
50
+ const field = await testdriver.find('username input in the login form');
51
+ const button = await testdriver.find('delete button in the top right corner');
52
+
53
+ // Describe nearby elements
54
+ const input = await testdriver.find('input field below the email label');
55
+ const checkbox = await testdriver.find('checkbox next to "Remember me"');
56
+
57
+ // Describe visual position
58
+ const menu = await testdriver.find('hamburger menu icon in the top left');
59
+ ```
60
+
61
+ ### Interacting with Found Elements
62
+
63
+ ```javascript
64
+ // Find and click
65
+ const submitBtn = await testdriver.find('submit button');
66
+ await submitBtn.click();
67
+
68
+ // Find and verify
69
+ const message = await testdriver.find('success message');
70
+ if (message.found()) {
71
+ console.log('Success message appeared');
72
+ }
73
+
74
+ // Find and extract info
75
+ const price = await testdriver.find('product price');
76
+ console.log('Price location:', price.coordinates);
77
+ console.log('Price text:', price.text);
78
+ ```
79
+
80
+ ## Element Object
81
+
82
+ The returned `Element` object provides:
83
+
84
+ ### Methods
85
+
86
+ - `found()` - Check if element was located
87
+ - `click(action)` - Click the element
88
+ - `hover()` - Hover over the element
89
+ - `doubleClick()` - Double-click the element
90
+ - `rightClick()` - Right-click the element
91
+ - `find(newDescription)` - Re-locate with optional new description
92
+
93
+ ### Properties
94
+
95
+ - `coordinates` - Element position `{x, y, centerX, centerY}`
96
+ - `x`, `y` - Top-left coordinates
97
+ - `centerX`, `centerY` - Center coordinates
98
+ - `text` - Text content (if available)
99
+ - `screenshot` - Base64 screenshot (if available)
100
+ - `confidence` - AI confidence score
101
+ - `width`, `height` - Element dimensions
102
+ - `boundingBox` - Complete bounding box
103
+
104
+ See [Elements Reference](/v7/api/elements) for complete details.
105
+
106
+ ## Best Practices
107
+
108
+ <Check>
109
+ **Be specific in descriptions**
110
+
111
+ More specific descriptions improve accuracy:
112
+
113
+ ```javascript
114
+ // ✅ Good
115
+ await testdriver.find('blue submit button below the email field');
116
+
117
+ // ❌ Too vague
118
+ await testdriver.find('button');
119
+ ```
120
+ </Check>
121
+
122
+ <Check>
123
+ **Always check if found**
124
+
125
+ Verify elements were located before interacting:
126
+
127
+ ```javascript
128
+ const element = await testdriver.find('login button');
129
+ if (!element.found()) {
130
+ throw new Error('Login button not found');
131
+ }
132
+ await element.click();
133
+ ```
134
+ </Check>
135
+
136
+ <Check>
137
+ **Include visual or positional context**
138
+
139
+ ```javascript
140
+ // Include color
141
+ await testdriver.find('red error icon');
142
+
143
+ // Include position
144
+ await testdriver.find('search button in the top navigation bar');
145
+
146
+ // Include nearby text
147
+ await testdriver.find('checkbox next to "I agree to terms"');
148
+ ```
149
+ </Check>
150
+
151
+ ## Polling for Dynamic Elements
152
+
153
+ For elements that may not be immediately visible:
154
+
155
+ ```javascript
156
+ // Poll until element appears
157
+ let loginButton;
158
+ const maxAttempts = 30;
159
+
160
+ for (let i = 0; i < maxAttempts; i++) {
161
+ loginButton = await testdriver.find('login button');
162
+ if (loginButton.found()) break;
163
+ await new Promise(r => setTimeout(r, 1000));
164
+ }
165
+
166
+ if (!loginButton.found()) {
167
+ throw new Error('Login button never appeared');
168
+ }
169
+
170
+ await loginButton.click();
171
+ ```
172
+
173
+ ### Helper Function
174
+
175
+ ```javascript
176
+ async function waitForElement(testdriver, description, timeout = 30000) {
177
+ const startTime = Date.now();
178
+
179
+ while (Date.now() - startTime < timeout) {
180
+ const element = await testdriver.find(description);
181
+ if (element.found()) return element;
182
+ await new Promise(r => setTimeout(r, 1000));
183
+ }
184
+
185
+ throw new Error(`Element "${description}" not found after ${timeout}ms`);
186
+ }
187
+
188
+ // Usage
189
+ const button = await waitForElement(testdriver, 'submit button', 10000);
190
+ await button.click();
191
+ ```
192
+
193
+ ## Use Cases
194
+
195
+ <AccordionGroup>
196
+ <Accordion title="Form Fields">
197
+ ```javascript
198
+ const emailField = await testdriver.find('email input field');
199
+ await emailField.click();
200
+ await testdriver.type('user@example.com');
201
+
202
+ const passwordField = await testdriver.find('password input');
203
+ await passwordField.click();
204
+ await testdriver.type('MyP@ssw0rd');
205
+ ```
206
+ </Accordion>
207
+
208
+ <Accordion title="Buttons and Links">
209
+ ```javascript
210
+ const submitBtn = await testdriver.find('submit button');
211
+ await submitBtn.click();
212
+
213
+ const cancelLink = await testdriver.find('cancel link');
214
+ await cancelLink.click();
215
+
216
+ const menuIcon = await testdriver.find('hamburger menu icon');
217
+ await menuIcon.click();
218
+ ```
219
+ </Accordion>
220
+
221
+ <Accordion title="Dynamic Content">
222
+ ```javascript
223
+ // Wait for loading to complete
224
+ let content;
225
+ for (let i = 0; i < 30; i++) {
226
+ content = await testdriver.find('results table');
227
+ if (content.found()) break;
228
+ await new Promise(r => setTimeout(r, 1000));
229
+ }
230
+
231
+ // Interact with loaded content
232
+ const firstRow = await testdriver.find('first row in the results table');
233
+ await firstRow.click();
234
+ ```
235
+ </Accordion>
236
+
237
+ <Accordion title="Complex UI Elements">
238
+ ```javascript
239
+ // Modals and dialogs
240
+ const modal = await testdriver.find('confirmation dialog');
241
+ if (modal.found()) {
242
+ const confirmBtn = await testdriver.find('confirm button in the dialog');
243
+ await confirmBtn.click();
244
+ }
245
+
246
+ // Dropdown menus
247
+ const dropdown = await testdriver.find('country dropdown');
248
+ await dropdown.click();
249
+
250
+ const option = await testdriver.find('United States option');
251
+ await option.click();
252
+ ```
253
+ </Accordion>
254
+ </AccordionGroup>
255
+
256
+ ## Complete Example
257
+
258
+ ```javascript
259
+ import { beforeAll, afterAll, describe, it, expect } from 'vitest';
260
+ import TestDriver from 'testdriverai';
261
+
262
+ describe('Element Finding', () => {
263
+ let testdriver;
264
+
265
+ beforeAll(async () => {
266
+ client = new TestDriver(process.env.TD_API_KEY);
267
+ await testdriver.auth();
268
+ await testdriver.connect({ newSandbox: true });
269
+ });
270
+
271
+ afterAll(async () => {
272
+ await testdriver.disconnect();
273
+ });
274
+
275
+ it('should find and interact with elements', async () => {
276
+ await testdriver.focusApplication('Google Chrome');
277
+
278
+ // Find login form elements
279
+ const usernameField = await testdriver.find('username input field');
280
+ expect(usernameField.found()).toBe(true);
281
+
282
+ await usernameField.click();
283
+ await testdriver.type('testuser');
284
+
285
+ // Find with context
286
+ const passwordField = await testdriver.find('password input below username');
287
+ await passwordField.click();
288
+ await testdriver.type('password123');
289
+
290
+ // Find button
291
+ const submitBtn = await testdriver.find('green submit button');
292
+ expect(submitBtn.found()).toBe(true);
293
+
294
+ console.log('Button location:', submitBtn.centerX, submitBtn.centerY);
295
+
296
+ await submitBtn.click();
297
+
298
+ // Wait for success message
299
+ let successMsg;
300
+ for (let i = 0; i < 10; i++) {
301
+ successMsg = await testdriver.find('success notification');
302
+ if (successMsg.found()) break;
303
+ await new Promise(r => setTimeout(r, 1000));
304
+ }
305
+
306
+ expect(successMsg.found()).toBe(true);
307
+ });
308
+ });
309
+ ```
310
+
311
+ ## Related Methods
312
+
313
+ - [`click()`](/v7/api/click) - Click on found elements
314
+ - [`hover()`](/v7/api/hover) - Hover over elements
315
+ - [`assert()`](/v7/api/assert) - Verify element states
316
+ - [Elements Reference](/v7/api/elements) - Complete Element API