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,360 @@
1
+ # Hooks API
2
+
3
+ React-style hooks for managing TestDriver and Dashcam lifecycle in Vitest tests.
4
+
5
+ ## Overview
6
+
7
+ Hooks provide automatic lifecycle management - no more forgetting to disconnect or stop recording. They integrate seamlessly with Vitest's test context.
8
+
9
+ ```javascript
10
+ import { test } from 'vitest';
11
+ import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
12
+
13
+ test('my test', async (context) => {
14
+ const client = useTestDriver(context, { os: 'linux' });
15
+ const dashcam = useDashcam(context, client, {
16
+ autoStart: true,
17
+ autoStop: true
18
+ });
19
+
20
+ // Test code here
21
+ // Automatic cleanup at test end!
22
+ });
23
+ ```
24
+
25
+ ## Available Hooks
26
+
27
+ ### useTestDriver
28
+
29
+ Creates and manages a TestDriver instance with automatic cleanup.
30
+
31
+ ```javascript
32
+ import { useTestDriver } from 'testdriverai/vitest/hooks';
33
+
34
+ test('my test', async (context) => {
35
+ const client = useTestDriver(context, {
36
+ os: 'linux', // Target OS (default: 'linux')
37
+ autoConnect: true, // Auto-connect to sandbox (default: true)
38
+ apiKey: process.env.TD_API_KEY,
39
+ apiRoot: 'https://...',
40
+ resolution: '1366x768',
41
+ analytics: true
42
+ });
43
+
44
+ // Client is ready to use
45
+ await client.find('button').click();
46
+
47
+ // Auto-disconnects at test end
48
+ });
49
+ ```
50
+
51
+ **Parameters:**
52
+ - `context` - Vitest test context (required)
53
+ - `options` - TestDriver configuration options
54
+
55
+ **Options:**
56
+ - `os` - Target OS: `'linux'`, `'mac'`, or `'windows'` (default: `'linux'`)
57
+ - `autoConnect` - Automatically connect to sandbox (default: `true`)
58
+ - `apiKey` - TestDriver API key (default: `process.env.TD_API_KEY`)
59
+ - `apiRoot` - API endpoint URL
60
+ - `resolution` - Screen resolution (default: `'1366x768'`)
61
+ - `analytics` - Enable analytics (default: `true`)
62
+ - `cacheThresholds` - Cache settings for find operations
63
+
64
+ **Returns:**
65
+ - TestDriver instance, ready to use
66
+
67
+ ### useDashcam
68
+
69
+ Creates and manages a Dashcam instance with optional auto-lifecycle.
70
+
71
+ ```javascript
72
+ import { useDashcam } from 'testdriverai/vitest/hooks';
73
+
74
+ test('my test', async (context) => {
75
+ // Assuming you have a client from useTestDriver
76
+ const dashcam = useDashcam(context, client, {
77
+ autoAuth: true, // Auto-authenticate (default: true)
78
+ autoStart: true, // Auto-start recording (default: false)
79
+ autoStop: true, // Auto-stop at test end (default: false)
80
+ apiKey: process.env.TD_API_KEY // Optional - uses TD_API_KEY by default
81
+ });
82
+
83
+ // If autoStart is false, manually start:
84
+ // await dashcam.start();
85
+
86
+ // Your test code
87
+
88
+ // If autoStop is true, URL is saved automatically
89
+ // Otherwise, manually stop:
90
+ // const url = await dashcam.stop();
91
+ });
92
+ ```
93
+
94
+ **Parameters:**
95
+ - `context` - Vitest test context (required)
96
+ - `client` - TestDriver instance from `useTestDriver()` (required)
97
+ - `options` - Dashcam configuration options
98
+
99
+ **Options:**
100
+ - `autoAuth` - Automatically authenticate (default: `true`)
101
+ - `autoStart` - Automatically start recording (default: `false`)
102
+ - `autoStop` - Automatically stop recording at test end (default: `false`)
103
+ - `apiKey` - API key (default: `process.env.TD_API_KEY`, same as TestDriver)
104
+
105
+ **Returns:**
106
+ - Dashcam instance
107
+
108
+ ### useTestDriverWithDashcam
109
+
110
+ Combined hook for the simplest usage - everything automatic.
111
+
112
+ ```javascript
113
+ import { useTestDriverWithDashcam } from 'testdriverai/vitest/hooks';
114
+
115
+ test('my test', async (context) => {
116
+ const { client, dashcam } = useTestDriverWithDashcam(context, {
117
+ os: 'linux',
118
+ // All TestDriver options +
119
+ // All Dashcam options (autoAuth, autoStart, autoStop all true by default)
120
+ });
121
+
122
+ // Everything is ready - just write your test!
123
+ await client.find('button').click();
124
+
125
+ // Dashcam auto-stops, client auto-disconnects
126
+ });
127
+ ```
128
+
129
+ **Parameters:**
130
+ - `context` - Vitest test context (required)
131
+ - `options` - Combined TestDriver and Dashcam options
132
+
133
+ **Returns:**
134
+ - `{ client, dashcam }` - Both instances, fully configured
135
+
136
+ ## Complete Examples
137
+
138
+ ### Basic Test with Hooks
139
+
140
+ ```javascript
141
+ import { describe, it, expect } from 'vitest';
142
+ import { useTestDriver } from 'testdriverai/vitest/hooks';
143
+
144
+ describe('Search Tests', () => {
145
+ it('should search successfully', async (context) => {
146
+ const client = useTestDriver(context, { os: 'linux' });
147
+
148
+ await client.focusApplication('Google Chrome');
149
+ await client.find('search box').type('testdriverai');
150
+ await client.pressKeys(['enter']);
151
+
152
+ const result = await client.assert('search results appear');
153
+ expect(result).toBeTruthy();
154
+ });
155
+ });
156
+ ```
157
+
158
+ ### With Dashcam Recording
159
+
160
+ ```javascript
161
+ import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
162
+
163
+ test('recorded test', async (context) => {
164
+ const client = useTestDriver(context, { os: 'linux' });
165
+ const dashcam = useDashcam(context, client, {
166
+ autoAuth: true,
167
+ autoStart: true,
168
+ autoStop: true // URL saved automatically
169
+ });
170
+
171
+ await client.focusApplication('Google Chrome');
172
+ await client.find('button').click();
173
+
174
+ // Dashcam URL will be in test results
175
+ });
176
+ ```
177
+
178
+ ### Fully Automatic
179
+
180
+ ```javascript
181
+ import { useTestDriverWithDashcam } from 'testdriverai/vitest/hooks';
182
+
183
+ test('automatic everything', async (context) => {
184
+ const { client } = useTestDriverWithDashcam(context);
185
+
186
+ await client.focusApplication('Google Chrome');
187
+ await client.find('login').click();
188
+
189
+ // Dashcam + TestDriver managed automatically
190
+ });
191
+ ```
192
+
193
+ ### Manual Control (Advanced)
194
+
195
+ ```javascript
196
+ import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
197
+
198
+ test('manual control', async (context) => {
199
+ const client = useTestDriver(context, {
200
+ os: 'linux',
201
+ autoConnect: false // We'll connect manually
202
+ });
203
+
204
+ // Manual connection
205
+ await client.auth();
206
+ await client.connect({ new: true });
207
+
208
+ const dashcam = useDashcam(context, client, {
209
+ autoAuth: true,
210
+ autoStart: false, // Manual start
211
+ autoStop: false // Manual stop
212
+ });
213
+
214
+ // Start recording when ready
215
+ await dashcam.start();
216
+
217
+ await client.find('button').click();
218
+
219
+ // Stop and get URL
220
+ const url = await dashcam.stop();
221
+ console.log('Replay:', url);
222
+
223
+ // Cleanup still automatic!
224
+ });
225
+ ```
226
+
227
+ ## How Hooks Work
228
+
229
+ Hooks use Vitest's `context.onTestFinished()` to register cleanup handlers:
230
+
231
+ ```javascript
232
+ // Internally, hooks do this:
233
+ export function useTestDriver(context, options = {}) {
234
+ const client = new TestDriver(apiKey, options);
235
+
236
+ // Register cleanup
237
+ context.onTestFinished(async () => {
238
+ await client.disconnect();
239
+ });
240
+
241
+ return client;
242
+ }
243
+ ```
244
+
245
+ This ensures cleanup always runs, even if your test fails.
246
+
247
+ ## TypeScript Support
248
+
249
+ ```typescript
250
+ import { useTestDriver, UseDashcamOptions } from 'testdriverai/vitest/hooks';
251
+
252
+ test('typed test', async (context) => {
253
+ const client = useTestDriver(context, {
254
+ os: 'linux', // ✅ Type-safe
255
+ resolution: '1920x1080'
256
+ });
257
+
258
+ const dashcamOptions: UseDashcamOptions = {
259
+ autoAuth: true,
260
+ autoStart: true,
261
+ autoStop: true
262
+ // apiKey is optional - uses TD_API_KEY by default
263
+ };
264
+
265
+ const dashcam = useDashcam(context, client, dashcamOptions);
266
+ });
267
+ ```
268
+
269
+ ## When to Use Hooks
270
+
271
+ **Use hooks when:**
272
+ - You want automatic cleanup
273
+ - You're testing with Vitest
274
+ - You need custom lifecycle control
275
+ - You're a power user who understands the lifecycle
276
+
277
+ **Use `provision()` instead when:**
278
+ - You're testing Chrome, VS Code, or Electron
279
+ - You want zero configuration
280
+ - You're a beginner
281
+ - You want the simplest API
282
+
283
+ **Use core classes directly when:**
284
+ - You need full manual control
285
+ - You're not using Vitest
286
+ - You're debugging lifecycle issues
287
+
288
+ ## Best Practices
289
+
290
+ 1. **Always pass context** - Required for automatic cleanup
291
+ 2. **One client per test** - Don't share clients between tests
292
+ 3. **Use autoStart/autoStop for Dashcam** - Unless you have specific timing needs
293
+ 4. **Leverage TypeScript** - Get autocomplete and catch errors early
294
+ 5. **Keep options in variables** - Easier to maintain and reuse
295
+
296
+ ## Common Patterns
297
+
298
+ ### Shared Setup
299
+
300
+ ```javascript
301
+ function setupBrowser(context) {
302
+ const client = useTestDriver(context, { os: 'linux' });
303
+ const dashcam = useDashcam(context, client, {
304
+ autoAuth: true,
305
+ autoStart: true,
306
+ autoStop: true
307
+ });
308
+ return { client, dashcam };
309
+ }
310
+
311
+ test('test 1', async (context) => {
312
+ const { client } = setupBrowser(context);
313
+ // ...
314
+ });
315
+
316
+ test('test 2', async (context) => {
317
+ const { client } = setupBrowser(context);
318
+ // ...
319
+ });
320
+ ```
321
+
322
+ ### Conditional Dashcam
323
+
324
+ ```javascript
325
+ test('maybe record', async (context) => {
326
+ const client = useTestDriver(context);
327
+
328
+ const shouldRecord = process.env.RECORD_TESTS === 'true';
329
+ const dashcam = shouldRecord
330
+ ? useDashcam(context, client, { autoStart: true, autoStop: true })
331
+ : null;
332
+
333
+ // Test code...
334
+ });
335
+ ```
336
+
337
+ ## Error Handling
338
+
339
+ Cleanup runs even if your test fails:
340
+
341
+ ```javascript
342
+ test('failing test', async (context) => {
343
+ const client = useTestDriver(context);
344
+
345
+ try {
346
+ await client.find('nonexistent element').click();
347
+ } catch (error) {
348
+ console.error('Test failed:', error);
349
+ throw error; // Test marked as failed
350
+ }
351
+
352
+ // client.disconnect() still runs automatically
353
+ });
354
+ ```
355
+
356
+ ## See Also
357
+
358
+ - [Provision API](./PROVISION.md) - Simpler API for common apps
359
+ - [Core Classes](./CORE.md) - Manual control
360
+ - [Migration Guide](../MIGRATION.md) - Upgrading from v6
@@ -0,0 +1,230 @@
1
+ # Progressive Disclosure APIs
2
+
3
+ TestDriver v7 introduces **progressive disclosure** - three levels of API to match your experience and needs.
4
+
5
+ ## Choose Your Level
6
+
7
+ ### 🟢 Beginner: Provision API
8
+
9
+ **Best for:** Getting started, testing common apps (Chrome, VS Code, Electron)
10
+
11
+ ```javascript
12
+ import { provision } from 'testdriverai/presets';
13
+
14
+ test('my test', async (context) => {
15
+ const { testdriver } = await provision('chrome', {
16
+ url: 'https://example.com'
17
+ }, context);
18
+
19
+ await testdriver.find('Login').click();
20
+ });
21
+ ```
22
+
23
+ **Why use this:**
24
+ - ✅ Zero configuration
25
+ - ✅ One line setup
26
+ - ✅ Automatic everything (launch, focus, cleanup, recording)
27
+ - ✅ Perfect for beginners
28
+
29
+ [Learn more →](./PROVISION.md)
30
+
31
+ ---
32
+
33
+ ### 🟡 Intermediate: Hooks API
34
+
35
+ **Best for:** Power users, custom workflows, manual lifecycle control
36
+
37
+ ```javascript
38
+ import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
39
+
40
+ test('my test', async (context) => {
41
+ const client = useTestDriver(context, { os: 'linux' });
42
+ const dashcam = useDashcam(context, client, {
43
+ autoStart: true,
44
+ autoStop: true
45
+ });
46
+
47
+ await client.find('button').click();
48
+ });
49
+ ```
50
+
51
+ **Why use this:**
52
+ - ✅ Automatic cleanup
53
+ - ✅ Flexible configuration
54
+ - ✅ Control over lifecycle
55
+ - ✅ Works with any application
56
+
57
+ [Learn more →](./HOOKS.md)
58
+
59
+ ---
60
+
61
+ ### 🔴 Advanced: Core Classes
62
+
63
+ **Best for:** Full control, non-Vitest frameworks, custom integrations
64
+
65
+ ```javascript
66
+ import { TestDriver, Dashcam } from 'testdriverai/core';
67
+
68
+ const client = new TestDriver(apiKey, { os: 'linux' });
69
+ await client.auth();
70
+ await client.connect();
71
+
72
+ const dashcam = new Dashcam(client);
73
+ await dashcam.start();
74
+
75
+ // Your code
76
+
77
+ await dashcam.stop();
78
+ await client.disconnect();
79
+ ```
80
+
81
+ **Why use this:**
82
+ - ✅ Complete manual control
83
+ - ✅ No framework dependencies
84
+ - ✅ Works anywhere
85
+ - ✅ Maximum flexibility
86
+
87
+ [Learn more →](./CORE.md)
88
+
89
+ ---
90
+
91
+ ## Architecture
92
+
93
+ ```
94
+ ┌─────────────────────────────────────────────┐
95
+ │ 🟢 Provision API (Easiest) │
96
+ │ provision('chrome', options, context) │
97
+ └─────────────────┬───────────────────────────┘
98
+
99
+ ┌─────────────────▼───────────────────────────┐
100
+ │ 🟡 Hooks API (Flexible) │
101
+ │ useTestDriver(), useDashcam() │
102
+ └─────────────────┬───────────────────────────┘
103
+
104
+ ┌─────────────────▼───────────────────────────┐
105
+ │ 🔴 Core Classes (Full Control) │
106
+ │ new TestDriver(), new Dashcam() │
107
+ └─────────────────────────────────────────────┘
108
+ ```
109
+
110
+ Each level builds on the one below it. Choose the highest level that meets your needs.
111
+
112
+ ## Quick Comparison
113
+
114
+ | Feature | Provision | Hooks | Core |
115
+ |---------|-----------|-------|------|
116
+ | Setup complexity | ⭐ 1 line | ⭐⭐ 2-3 lines | ⭐⭐⭐ 5+ lines |
117
+ | Cleanup | ✅ Automatic | ✅ Automatic | ❌ Manual |
118
+ | Framework requirement | Vitest | Vitest | None |
119
+ | Application support | Chrome, VS Code, Electron | Any | Any |
120
+ | Launch application | ✅ Automatic | ❌ Manual | ❌ Manual |
121
+ | Dashcam recording | ✅ Automatic | ⚡ Optional automatic | ❌ Manual |
122
+ | TypeScript support | ✅ Full | ✅ Full | ✅ Full |
123
+ | Customization | ⚡ Limited | ✅ High | ✅ Complete |
124
+
125
+ ## When to Use Each
126
+
127
+ ### Use Provision API when:
128
+ - ✅ Testing Chrome, VS Code, or Electron
129
+ - ✅ You're a beginner
130
+ - ✅ You want the simplest possible code
131
+ - ✅ You're okay with defaults
132
+
133
+ ### Use Hooks API when:
134
+ - ✅ You need custom application launch
135
+ - ✅ You want automatic cleanup
136
+ - ✅ You're using Vitest
137
+ - ✅ You need fine-grained lifecycle control
138
+
139
+ ### Use Core Classes when:
140
+ - ✅ Not using Vitest
141
+ - ✅ Integrating with other frameworks
142
+ - ✅ Building custom abstractions
143
+ - ✅ Debugging lifecycle issues
144
+ - ✅ Need complete manual control
145
+
146
+ ## Examples
147
+
148
+ ### Simple Chrome Test
149
+
150
+ **Provision (1 line):**
151
+ ```javascript
152
+ const { testdriver } = await provision('chrome', { url }, context);
153
+ ```
154
+
155
+ **Hooks (3 lines):**
156
+ ```javascript
157
+ const client = useTestDriver(context);
158
+ await client.exec('sh', 'google-chrome "https://..." &', 30000);
159
+ await client.focusApplication('Google Chrome');
160
+ ```
161
+
162
+ **Core (6+ lines):**
163
+ ```javascript
164
+ const client = new TestDriver(apiKey, { os: 'linux' });
165
+ await client.auth();
166
+ await client.connect();
167
+ await client.exec('sh', 'google-chrome "https://..." &', 30000);
168
+ await client.focusApplication('Google Chrome');
169
+ // ... test code ...
170
+ await client.disconnect();
171
+ ```
172
+
173
+ ### With Dashcam Recording
174
+
175
+ **Provision (1 line):**
176
+ ```javascript
177
+ const { testdriver, dashcam } = await provision('chrome', { url }, context);
178
+ // Recording automatic!
179
+ ```
180
+
181
+ **Hooks (2 lines):**
182
+ ```javascript
183
+ const client = useTestDriver(context);
184
+ const dashcam = useDashcam(context, client, { autoStart: true, autoStop: true });
185
+ ```
186
+
187
+ **Core (7+ lines):**
188
+ ```javascript
189
+ const client = new TestDriver(apiKey);
190
+ await client.auth();
191
+ await client.connect();
192
+ const dashcam = new Dashcam(client);
193
+ await dashcam.auth();
194
+ await dashcam.start();
195
+ // ... test code ...
196
+ await dashcam.stop();
197
+ await client.disconnect();
198
+ ```
199
+
200
+ ## Migration Path
201
+
202
+ Start simple, grow as needed:
203
+
204
+ 1. **Start with Provision** - Get tests working quickly
205
+ 2. **Move to Hooks** - When you need custom app launch
206
+ 3. **Use Core** - Only if you need full control or non-Vitest
207
+
208
+ You can mix and match in the same project!
209
+
210
+ ## Package Exports
211
+
212
+ All three APIs are available from the same package:
213
+
214
+ ```javascript
215
+ // Provision API
216
+ import { provision, chrome, vscode, electron } from 'testdriverai/presets';
217
+
218
+ // Hooks API
219
+ import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
220
+
221
+ // Core Classes
222
+ import { TestDriver, Dashcam } from 'testdriverai/core';
223
+ ```
224
+
225
+ ## See Also
226
+
227
+ - [Provision API Reference](./PROVISION.md)
228
+ - [Hooks API Reference](./HOOKS.md)
229
+ - [Core Classes Reference](./CORE.md)
230
+ - [Migration Guide](../MIGRATION.md)