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,459 @@
1
+ # Core Classes
2
+
3
+ Direct access to TestDriver and Dashcam classes for full manual control.
4
+
5
+ ## Overview
6
+
7
+ The core module provides the fundamental building blocks without any automatic lifecycle management. Use this when you need complete control or when working outside of Vitest.
8
+
9
+ ```javascript
10
+ import { TestDriver, Dashcam } from 'testdriverai/core';
11
+
12
+ const client = new TestDriver(apiKey, { os: 'linux' });
13
+ await client.auth();
14
+ await client.connect();
15
+
16
+ const dashcam = new Dashcam(client);
17
+ await dashcam.start();
18
+
19
+ // Your test code
20
+
21
+ await dashcam.stop();
22
+ await client.disconnect();
23
+ ```
24
+
25
+ ## TestDriver Class
26
+
27
+ ### Constructor
28
+
29
+ ```javascript
30
+ import { TestDriver } from 'testdriverai/core';
31
+
32
+ const client = new TestDriver(apiKey, options);
33
+ ```
34
+
35
+ **Parameters:**
36
+ - `apiKey` - Your TestDriver API key (string)
37
+ - `options` - Configuration object
38
+
39
+ **Options:**
40
+ ```javascript
41
+ {
42
+ os: 'linux', // Target OS: 'linux', 'mac', 'windows'
43
+ apiRoot: 'https://...', // API endpoint
44
+ resolution: '1366x768', // Screen resolution
45
+ newSandbox: true, // Create new sandbox
46
+ analytics: true, // Enable analytics
47
+ cacheThresholds: {
48
+ find: 0.05,
49
+ findAll: 0.05
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Methods
55
+
56
+ #### auth()
57
+ Authenticate with TestDriver API.
58
+
59
+ ```javascript
60
+ await client.auth();
61
+ ```
62
+
63
+ #### connect(options)
64
+ Connect to a sandbox instance.
65
+
66
+ ```javascript
67
+ await client.connect({
68
+ new: true // Create new sandbox (default: true)
69
+ });
70
+ ```
71
+
72
+ #### disconnect()
73
+ Disconnect from sandbox and clean up.
74
+
75
+ ```javascript
76
+ await client.disconnect();
77
+ ```
78
+
79
+ #### find(query)
80
+ Find an element on screen.
81
+
82
+ ```javascript
83
+ const element = await client.find('Login button');
84
+ await element.click();
85
+
86
+ // Or chain:
87
+ await client.find('Login button').then(el => el.click());
88
+ ```
89
+
90
+ #### findAll(query)
91
+ Find all matching elements.
92
+
93
+ ```javascript
94
+ const buttons = await client.findAll('button');
95
+ console.log('Found', buttons.length, 'buttons');
96
+ ```
97
+
98
+ #### click(target)
99
+ Click an element.
100
+
101
+ ```javascript
102
+ await client.click('Submit button');
103
+ ```
104
+
105
+ #### type(text)
106
+ Type text (at current cursor position).
107
+
108
+ ```javascript
109
+ await client.type('username@example.com');
110
+ ```
111
+
112
+ #### pressKeys(keys)
113
+ Press keyboard keys or shortcuts.
114
+
115
+ ```javascript
116
+ await client.pressKeys(['ctrl', 'a']);
117
+ await client.pressKeys(['enter']);
118
+ ```
119
+
120
+ #### exec(shell, command, timeout, ignoreError)
121
+ Execute shell command.
122
+
123
+ ```javascript
124
+ const output = await client.exec(
125
+ 'sh', // Shell: 'sh' or 'pwsh'
126
+ 'google-chrome "https://..." &', // Command
127
+ 30000, // Timeout (ms)
128
+ false // Ignore errors
129
+ );
130
+ ```
131
+
132
+ #### focusApplication(appName)
133
+ Focus/activate an application window.
134
+
135
+ ```javascript
136
+ await client.focusApplication('Google Chrome');
137
+ await client.focusApplication('Visual Studio Code');
138
+ ```
139
+
140
+ #### scroll(direction, amount)
141
+ Scroll the page.
142
+
143
+ ```javascript
144
+ await client.scroll('down', 500);
145
+ await client.scroll('up', 200);
146
+ ```
147
+
148
+ #### assert(query)
149
+ Assert that something is true on screen.
150
+
151
+ ```javascript
152
+ const result = await client.assert('Login successful message appears');
153
+ // Returns boolean
154
+ ```
155
+
156
+ ## Dashcam Class
157
+
158
+ ### Constructor
159
+
160
+ ```javascript
161
+ import { Dashcam } from 'testdriverai/core';
162
+
163
+ const dashcam = new Dashcam(client, options);
164
+ ```
165
+
166
+ **Parameters:**
167
+ - `client` - TestDriver instance (required)
168
+ - `options` - Configuration object (optional)
169
+
170
+ **Options:**
171
+ ```javascript
172
+ {
173
+ apiKey: process.env.TD_API_KEY // API key (same as TestDriver)
174
+ }
175
+ ```
176
+
177
+ ### Methods
178
+
179
+ #### auth(apiKey)
180
+ Authenticate with Dashcam CLI.
181
+
182
+ ```javascript
183
+ await dashcam.auth(); // Uses TD_API_KEY env var (same as TestDriver)
184
+ // Or:
185
+ await dashcam.auth('your-api-key');
186
+ ```
187
+
188
+ #### start()
189
+ Start recording.
190
+
191
+ ```javascript
192
+ await dashcam.start();
193
+ ```
194
+
195
+ #### stop()
196
+ Stop recording and get replay URL.
197
+
198
+ ```javascript
199
+ const url = await dashcam.stop();
200
+ console.log('Replay:', url);
201
+ // Returns: https://app.dashcam.io/replay/...
202
+ ```
203
+
204
+ #### isRecording()
205
+ Check if currently recording.
206
+
207
+ ```javascript
208
+ if (dashcam.isRecording()) {
209
+ console.log('Recording in progress');
210
+ }
211
+ ```
212
+
213
+ #### addFileLog(path, name)
214
+ Add a file to Dashcam logs.
215
+
216
+ ```javascript
217
+ await dashcam.addFileLog('/var/log/app.log', 'Application Log');
218
+ ```
219
+
220
+ #### addApplicationLog(application, name)
221
+ Track an application in Dashcam.
222
+
223
+ ```javascript
224
+ await dashcam.addApplicationLog('Google Chrome', 'Browser');
225
+ ```
226
+
227
+ ## Complete Examples
228
+
229
+ ### Basic Test
230
+
231
+ ```javascript
232
+ import { TestDriver } from 'testdriverai/core';
233
+
234
+ async function runTest() {
235
+ const client = new TestDriver(process.env.TD_API_KEY, {
236
+ os: 'linux',
237
+ resolution: '1920x1080'
238
+ });
239
+
240
+ try {
241
+ // Connect
242
+ await client.auth();
243
+ await client.connect({ new: true });
244
+
245
+ // Focus browser
246
+ await client.focusApplication('Google Chrome');
247
+
248
+ // Navigate
249
+ const urlBar = await client.find('URL bar');
250
+ await urlBar.click();
251
+ await client.type('https://example.com');
252
+ await client.pressKeys(['enter']);
253
+
254
+ // Test
255
+ await client.find('heading').click();
256
+ const result = await client.assert('page loaded successfully');
257
+
258
+ console.log('Test passed:', result);
259
+ } finally {
260
+ // Always disconnect
261
+ await client.disconnect();
262
+ }
263
+ }
264
+
265
+ runTest();
266
+ ```
267
+
268
+ ### With Dashcam
269
+
270
+ ```javascript
271
+ import { TestDriver, Dashcam } from 'testdriverai/core';
272
+
273
+ async function runRecordedTest() {
274
+ const client = new TestDriver(process.env.TD_API_KEY, { os: 'linux' });
275
+ const dashcam = new Dashcam(client);
276
+
277
+ try {
278
+ // Setup
279
+ await client.auth();
280
+ await client.connect();
281
+
282
+ // Start recording
283
+ await dashcam.auth();
284
+ await dashcam.start();
285
+
286
+ // Run test
287
+ await client.focusApplication('Google Chrome');
288
+ await client.find('button').click();
289
+
290
+ // Stop recording
291
+ const url = await dashcam.stop();
292
+ console.log('Replay URL:', url);
293
+
294
+ } finally {
295
+ await client.disconnect();
296
+ }
297
+ }
298
+
299
+ runRecordedTest();
300
+ ```
301
+
302
+ ### Multiple Operations
303
+
304
+ ```javascript
305
+ import { TestDriver } from 'testdriverai/core';
306
+
307
+ async function complexTest() {
308
+ const client = new TestDriver(process.env.TD_API_KEY, { os: 'linux' });
309
+
310
+ await client.auth();
311
+ await client.connect();
312
+
313
+ try {
314
+ // Launch application
315
+ await client.exec(
316
+ 'sh',
317
+ 'google-chrome --start-maximized "https://example.com" &',
318
+ 30000
319
+ );
320
+
321
+ await client.focusApplication('Google Chrome');
322
+
323
+ // Fill form
324
+ await client.find('username field').type('user@example.com');
325
+ await client.find('password field').type('password123');
326
+ await client.find('submit button').click();
327
+
328
+ // Navigate
329
+ await client.find('dashboard link').click();
330
+
331
+ // Scroll and interact
332
+ await client.scroll('down', 500);
333
+ await client.find('settings button').click();
334
+
335
+ // Verify
336
+ const result = await client.assert('settings page is visible');
337
+ console.log('Test result:', result);
338
+
339
+ } finally {
340
+ await client.disconnect();
341
+ }
342
+ }
343
+
344
+ complexTest();
345
+ ```
346
+
347
+ ### Error Handling
348
+
349
+ ```javascript
350
+ import { TestDriver } from 'testdriverai/core';
351
+
352
+ async function testWithErrorHandling() {
353
+ const client = new TestDriver(process.env.TD_API_KEY, { os: 'linux' });
354
+
355
+ try {
356
+ await client.auth();
357
+ await client.connect();
358
+
359
+ await client.focusApplication('Google Chrome');
360
+
361
+ // Try to find element
362
+ const element = await client.find('optional button');
363
+
364
+ if (element.found()) {
365
+ await element.click();
366
+ } else {
367
+ console.log('Button not found, continuing...');
368
+ }
369
+
370
+ } catch (error) {
371
+ console.error('Test failed:', error);
372
+ throw error;
373
+ } finally {
374
+ // Always cleanup
375
+ try {
376
+ await client.disconnect();
377
+ } catch (cleanupError) {
378
+ console.error('Cleanup error:', cleanupError);
379
+ }
380
+ }
381
+ }
382
+ ```
383
+
384
+ ## TypeScript Support
385
+
386
+ ```typescript
387
+ import { TestDriver, Dashcam, TestDriverOptions, DashcamOptions } from 'testdriverai/core';
388
+
389
+ const options: TestDriverOptions = {
390
+ os: 'linux',
391
+ resolution: '1366x768',
392
+ newSandbox: true,
393
+ analytics: true
394
+ };
395
+
396
+ const client = new TestDriver(process.env.TD_API_KEY!, options);
397
+
398
+ const dashcamOptions: DashcamOptions = {
399
+ apiKey: process.env.TD_API_KEY // Same as TestDriver
400
+ };
401
+
402
+ const dashcam = new Dashcam(client, dashcamOptions);
403
+ ```
404
+
405
+ ## When to Use Core Classes
406
+
407
+ **Use core classes when:**
408
+ - You need full manual control
409
+ - You're not using Vitest
410
+ - You're integrating with another test framework
411
+ - You're building custom abstractions
412
+ - You're debugging lifecycle issues
413
+ - You're writing scripts, not tests
414
+
415
+ **Use hooks or provision() instead when:**
416
+ - You're using Vitest
417
+ - You want automatic cleanup
418
+ - You prefer simpler APIs
419
+ - You're testing common applications
420
+
421
+ ## Best Practices
422
+
423
+ 1. **Always disconnect** - Use try/finally to ensure cleanup
424
+ 2. **Check element.found()** - Before using optional elements
425
+ 3. **Handle errors gracefully** - Log and re-throw when appropriate
426
+ 4. **Use TypeScript** - Get type safety and autocomplete
427
+ 5. **Set reasonable timeouts** - Default is 30 seconds for exec()
428
+ 6. **Focus applications** - Before interacting with them
429
+
430
+ ## Platform Differences
431
+
432
+ ### Shell Commands
433
+
434
+ **Linux/Mac:**
435
+ ```javascript
436
+ await client.exec('sh', 'google-chrome "https://example.com" &', 30000);
437
+ ```
438
+
439
+ **Windows:**
440
+ ```javascript
441
+ await client.exec(
442
+ 'pwsh',
443
+ 'Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "https://example.com"',
444
+ 30000
445
+ );
446
+ ```
447
+
448
+ ### Application Names
449
+
450
+ - Linux: `'Google Chrome'`, `'Firefox'`, `'Visual Studio Code'`
451
+ - Mac: `'Google Chrome'`, `'Firefox'`, `'Visual Studio Code'`
452
+ - Windows: `'Google Chrome'`, `'Firefox'`, `'Visual Studio Code'`
453
+
454
+ ## See Also
455
+
456
+ - [Provision API](./PROVISION.md) - Simplified API for common apps
457
+ - [Hooks API](./HOOKS.md) - Automatic lifecycle management
458
+ - [Migration Guide](../MIGRATION.md) - Upgrading from v6
459
+ - [API Reference](../../sdk.js) - Full source code