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,425 @@
1
+ # Migration Guide: v6 → v7
2
+
3
+ This guide helps you migrate from the old TestDriver API (v6) to the new SDK architecture (v7).
4
+
5
+ ## Overview
6
+
7
+ v7 introduces a **progressive disclosure** pattern with three API levels:
8
+
9
+ 1. **Presets** (Beginner) - Zero config, instant setup
10
+ 2. **Hooks** (Intermediate) - Flexible lifecycle management
11
+ 3. **Core Classes** (Advanced) - Full manual control
12
+
13
+ You can mix and match these patterns based on your needs.
14
+
15
+ ## Quick Migration Examples
16
+
17
+ ### Before (v6) - Legacy Helpers
18
+
19
+ ```javascript
20
+ import { test } from 'vitest';
21
+ import { authDashcam, startDashcam, stopDashcam } from 'testdriverai';
22
+
23
+ test('my test', async ({ client }) => {
24
+ await authDashcam(client);
25
+ await startDashcam(client);
26
+
27
+ await client.find('Login button').click();
28
+
29
+ const url = await stopDashcam(client);
30
+ console.log('Replay:', url);
31
+ });
32
+ ```
33
+
34
+ ### After (v7) - Using Presets
35
+
36
+ ```javascript
37
+ import { test } from 'vitest';
38
+ import { chromePreset } from 'testdriverai/presets';
39
+
40
+ test('my test', async (context) => {
41
+ const { client } = await chromePreset(context, {
42
+ url: 'https://myapp.com'
43
+ });
44
+
45
+ // Dashcam already running, auto-stops at test end
46
+ await client.find('Login button').click();
47
+ });
48
+ ```
49
+
50
+ ### After (v7) - Using Hooks
51
+
52
+ ```javascript
53
+ import { test } from 'vitest';
54
+ import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
55
+
56
+ test('my test', async (context) => {
57
+ const client = useTestDriver(context, { os: 'linux' });
58
+ const dashcam = useDashcam(context, client, {
59
+ autoAuth: true,
60
+ autoStart: true,
61
+ autoStop: true
62
+ });
63
+
64
+ await client.find('Login button').click();
65
+ });
66
+ ```
67
+
68
+ ### After (v7) - Using Core Classes
69
+
70
+ ```javascript
71
+ import { test } from 'vitest';
72
+ import { TestDriver, Dashcam } from 'testdriverai/core';
73
+
74
+ test('my test', async (context) => {
75
+ const client = new TestDriver(process.env.TD_API_KEY, { os: 'linux' });
76
+ const dashcam = new Dashcam(client);
77
+
78
+ await client.auth();
79
+ await client.connect();
80
+
81
+ await dashcam.auth();
82
+ await dashcam.start();
83
+
84
+ await client.find('Login button').click();
85
+
86
+ const url = await dashcam.stop();
87
+ await client.disconnect();
88
+
89
+ console.log('Replay:', url);
90
+ });
91
+ ```
92
+
93
+ ## Package Exports
94
+
95
+ v7 introduces multiple entry points for different use cases:
96
+
97
+ ```javascript
98
+ // Main SDK (unchanged)
99
+ import TestDriver from 'testdriverai';
100
+
101
+ // Core classes
102
+ import { TestDriver, Dashcam } from 'testdriverai/core';
103
+
104
+ // Vitest hooks
105
+ import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
106
+
107
+ // Presets
108
+ import { chromePreset, vscodePreset } from 'testdriverai/presets';
109
+
110
+ // Vitest plugin (unchanged)
111
+ import testDriver from 'testdriverai/vitest';
112
+ ```
113
+
114
+ ## API Changes
115
+
116
+ ### Dashcam Lifecycle Helpers (DEPRECATED)
117
+
118
+ The following functions are **deprecated** but still work for backward compatibility:
119
+
120
+ ```javascript
121
+ // ❌ OLD (still works, but deprecated)
122
+ import {
123
+ authDashcam,
124
+ addDashcamLog,
125
+ startDashcam,
126
+ stopDashcam
127
+ } from 'testdriverai';
128
+
129
+ authDashcam(client);
130
+ startDashcam(client);
131
+ stopDashcam(client);
132
+ ```
133
+
134
+ **Migrate to:**
135
+
136
+ ```javascript
137
+ // ✅ NEW - Direct class usage
138
+ import { Dashcam } from 'testdriverai/core';
139
+
140
+ const dashcam = new Dashcam(client);
141
+ await dashcam.auth();
142
+ await dashcam.start();
143
+ const url = await dashcam.stop();
144
+ ```
145
+
146
+ Or even better:
147
+
148
+ ```javascript
149
+ // ✅ NEW - Using hooks
150
+ import { useDashcam } from 'testdriverai/vitest/hooks';
151
+
152
+ const dashcam = useDashcam(context, client, {
153
+ autoAuth: true,
154
+ autoStart: true,
155
+ autoStop: true
156
+ });
157
+ ```
158
+
159
+ ### TestDriver Client Creation
160
+
161
+ **No changes needed** - the main SDK API remains the same:
162
+
163
+ ```javascript
164
+ // Still works exactly the same
165
+ import TestDriver from 'testdriverai';
166
+ const client = new TestDriver(apiKey, { os: 'linux' });
167
+ ```
168
+
169
+ But you now have cleaner alternatives:
170
+
171
+ ```javascript
172
+ // Using hooks (auto-cleanup)
173
+ import { useTestDriver } from 'testdriverai/vitest/hooks';
174
+ const client = useTestDriver(context, { os: 'linux' });
175
+
176
+ // Using presets (zero config)
177
+ import { chromePreset } from 'testdriverai/presets';
178
+ const { browser } = await chromePreset(context, { url: 'https://example.com' });
179
+ ```
180
+
181
+ ## Migration Strategies
182
+
183
+ ### Strategy 1: Gradual Migration
184
+
185
+ Keep existing tests working, adopt new APIs for new tests:
186
+
187
+ ```javascript
188
+ // old-test.js - Leave as-is
189
+ import { authDashcam, startDashcam } from 'testdriverai';
190
+
191
+ // new-test.js - Use new APIs
192
+ import { chromePreset } from 'testdriverai/presets';
193
+ ```
194
+
195
+ The old helpers will continue to work indefinitely.
196
+
197
+ ### Strategy 2: Convert to Hooks
198
+
199
+ Replace lifecycle helpers with hooks for better lifecycle management:
200
+
201
+ **Before:**
202
+ ```javascript
203
+ import { authDashcam, startDashcam, stopDashcam } from 'testdriverai';
204
+
205
+ test('my test', async ({ client }) => {
206
+ await authDashcam(client);
207
+ await startDashcam(client);
208
+ // test code
209
+ await stopDashcam(client);
210
+ });
211
+ ```
212
+
213
+ **After:**
214
+ ```javascript
215
+ import { useDashcam } from 'testdriverai/vitest/hooks';
216
+
217
+ test('my test', async (context) => {
218
+ // Assuming client is already available via plugin or another hook
219
+ const dashcam = useDashcam(context, client, {
220
+ autoAuth: true,
221
+ autoStart: true,
222
+ autoStop: true
223
+ });
224
+ // test code
225
+ // Auto-stops at test end
226
+ });
227
+ ```
228
+
229
+ ### Strategy 3: Adopt Presets
230
+
231
+ For common scenarios (Chrome, VS Code, Electron), use presets:
232
+
233
+ **Before:**
234
+ ```javascript
235
+ test('chrome test', async ({ client }) => {
236
+ await authDashcam(client);
237
+ await startDashcam(client);
238
+
239
+ await client.exec('sh', 'google-chrome "https://example.com" &', 30000);
240
+ await client.focusApplication('Google Chrome');
241
+
242
+ await client.find('button').click();
243
+
244
+ await stopDashcam(client);
245
+ });
246
+ ```
247
+
248
+ **After:**
249
+ ```javascript
250
+ test('chrome test', async (context) => {
251
+ const { browser } = await chromePreset(context, {
252
+ url: 'https://example.com'
253
+ });
254
+
255
+ await browser.find('button').click();
256
+ // Dashcam auto-stops, cleanup automatic
257
+ });
258
+ ```
259
+
260
+ ## Benefits of Migration
261
+
262
+ ### Before Migration
263
+
264
+ - ❌ Manual lifecycle management (easy to forget cleanup)
265
+ - ❌ Lots of boilerplate for common scenarios
266
+ - ❌ No TypeScript support
267
+ - ❌ Helper functions scattered across codebase
268
+ - ❌ Tight coupling to plugin
269
+
270
+ ### After Migration
271
+
272
+ - ✅ Automatic lifecycle management (hooks)
273
+ - ✅ Zero boilerplate (presets)
274
+ - ✅ Full TypeScript definitions
275
+ - ✅ Organized, composable APIs
276
+ - ✅ Works with or without plugin
277
+
278
+ ## Common Patterns
279
+
280
+ ### Pattern 1: Chrome Testing
281
+
282
+ ```javascript
283
+ // OLD
284
+ test('chrome test', async ({ client }) => {
285
+ await client.exec('sh', 'google-chrome "https://example.com" &', 30000);
286
+ await client.focusApplication('Google Chrome');
287
+ await authDashcam(client);
288
+ await startDashcam(client);
289
+ // ... test code
290
+ await stopDashcam(client);
291
+ });
292
+
293
+ // NEW
294
+ import { chromePreset } from 'testdriverai/presets';
295
+
296
+ test('chrome test', async (context) => {
297
+ const { client } = await chromePreset(context, {
298
+ url: 'https://example.com'
299
+ });
300
+ // ... test code
301
+ });
302
+ ```
303
+
304
+ **Lines of code:** 7 → 2 (71% reduction)
305
+
306
+ ### Pattern 2: Manual Dashcam Control
307
+
308
+ ```javascript
309
+ // OLD
310
+ test('dashcam test', async ({ client }) => {
311
+ await authDashcam(client);
312
+ await startDashcam(client);
313
+ // ... test code
314
+ const url = await stopDashcam(client);
315
+ console.log(url);
316
+ });
317
+
318
+ // NEW
319
+ import { Dashcam } from 'testdriverai/core';
320
+
321
+ test('dashcam test', async (context) => {
322
+ const dashcam = new Dashcam(client);
323
+ await dashcam.auth();
324
+ await dashcam.start();
325
+ // ... test code
326
+ const url = await dashcam.stop();
327
+ console.log(url);
328
+ });
329
+ ```
330
+
331
+ ### Pattern 3: Custom Application Setup
332
+
333
+ ```javascript
334
+ // OLD
335
+ test('custom app', async ({ client }) => {
336
+ await authDashcam(client);
337
+ await startDashcam(client);
338
+ await client.exec('sh', 'myapp --arg1 --arg2 &', 30000);
339
+ await client.focusApplication('MyApp');
340
+ // ... test code
341
+ await stopDashcam(client);
342
+ });
343
+
344
+ // NEW - Create custom preset
345
+ import { createPreset } from 'testdriverai/presets';
346
+
347
+ const myAppPreset = createPreset({
348
+ name: 'My App',
349
+ defaults: { args: [] },
350
+ async setup(context, client, dashcam, options) {
351
+ const { args = [] } = options;
352
+ const argsStr = args.join(' ');
353
+ await client.exec('sh', `myapp ${argsStr} &`, 30000);
354
+ await client.focusApplication('MyApp');
355
+ return {}; // client is returned automatically
356
+ }
357
+ });
358
+
359
+ test('custom app', async (context) => {
360
+ const { client } = await myAppPreset(context, {
361
+ args: ['--arg1', '--arg2']
362
+ });
363
+ // ... test code
364
+ // Auto-cleanup
365
+ });
366
+ ```
367
+
368
+ **Reusable** - Use `myAppPreset` in all your tests!
369
+
370
+ ## TypeScript Support
371
+
372
+ v7 includes full TypeScript definitions:
373
+
374
+ ```typescript
375
+ import { test } from 'vitest';
376
+ import { chromePreset, ChromePresetOptions } from 'testdriverai/presets';
377
+ import { useTestDriver, UseDashcamOptions } from 'testdriverai/vitest/hooks';
378
+ import { Dashcam, DashcamOptions } from 'testdriverai/core';
379
+
380
+ // Full autocomplete and type checking!
381
+ test('typed test', async (context) => {
382
+ const { client } = await chromePreset(context, {
383
+ url: 'https://example.com',
384
+ maximized: true,
385
+ os: 'linux' // Type-safe: only 'linux' | 'mac' | 'windows'
386
+ });
387
+
388
+ await client.find('button').click();
389
+ });
390
+ ```
391
+
392
+ ## Breaking Changes
393
+
394
+ ### None! 🎉
395
+
396
+ v7 is **100% backward compatible**. All existing code continues to work.
397
+
398
+ The old lifecycle helpers (`authDashcam`, `startDashcam`, `stopDashcam`) are marked as deprecated but fully functional.
399
+
400
+ ## Deprecation Timeline
401
+
402
+ - **v7.0** - New APIs introduced, old helpers work (with deprecation warnings)
403
+ - **v7.x** - Old helpers continue to work
404
+ - **v8.0** - Old helpers removed (TBD, at least 6 months notice)
405
+
406
+ ## Getting Help
407
+
408
+ - 📖 **Hooks Documentation**: See `/docs/HOOKS.md`
409
+ - 📖 **Presets Documentation**: See `/docs/PRESETS.md`
410
+ - 💬 **Examples**: See `/testdriver/acceptance-sdk/*-example.test.mjs`
411
+ - 🐛 **Issues**: GitHub Issues
412
+
413
+ ## Summary
414
+
415
+ **Choose your level:**
416
+
417
+ | Level | Best For | Example |
418
+ |-------|----------|---------|
419
+ | **Presets** | Common apps (Chrome, VS Code) | `chromePreset(context, { url })` |
420
+ | **Hooks** | Custom lifecycle, power users | `useTestDriver(context, options)` |
421
+ | **Core** | Advanced control, debugging | `new Dashcam(client)` |
422
+
423
+ **Recommendation:** Start with presets for common scenarios, use hooks for custom needs, drop to core classes only when necessary.
424
+
425
+ Migration is **optional** - your existing code continues to work!
@@ -0,0 +1,210 @@
1
+ # TestDriver Presets
2
+
3
+ Presets provide pre-configured setups for common applications, reducing boilerplate and making your tests easier to write.
4
+
5
+ ## Available Presets
6
+
7
+ ### chromePreset
8
+
9
+ Automatically sets up Chrome browser with TestDriver and Dashcam.
10
+
11
+ ```javascript
12
+ import { test } from 'vitest';
13
+ import { chromePreset } from 'testdriverai/presets';
14
+
15
+ test('my test', async (context) => {
16
+ const { client } = await chromePreset(context, {
17
+ url: 'https://myapp.com/login'
18
+ });
19
+
20
+ await client.find('email input').type('user@example.com');
21
+ await client.find('Login button').click();
22
+ });
23
+ ```
24
+
25
+ **Options:**
26
+ - `url` - URL to navigate to (default: 'http://testdriver-sandbox.vercel.app/')
27
+ - `os` - Target OS: 'linux', 'mac', 'windows' (default: 'linux')
28
+ - `dashcam` - Enable Dashcam recording (default: true)
29
+ - `maximized` - Start maximized (default: true)
30
+ - `guest` - Use guest mode (default: true)
31
+
32
+ **Returns:**
33
+ - `client` - TestDriver instance
34
+ - `dashcam` - Dashcam instance (if enabled)
35
+
36
+ ### vscodePreset
37
+
38
+ Automatically sets up VS Code with TestDriver and Dashcam.
39
+
40
+ ```javascript
41
+ import { vscodePreset } from 'testdriverai/presets';
42
+
43
+ test('extension test', async (context) => {
44
+ const { vscode } = await vscodePreset(context, {
45
+ workspace: '/tmp/test-project',
46
+ extensions: ['ms-python.python']
47
+ });
48
+
49
+ await vscode.find('File menu').click();
50
+ await vscode.find('New File').click();
51
+ });
52
+ ```
53
+
54
+ **Options:**
55
+ - `workspace` - Workspace/folder to open
56
+ - `os` - Target OS (default: 'linux')
57
+ - `dashcam` - Enable Dashcam recording (default: true)
58
+ - `extensions` - Array of extension IDs to install
59
+
60
+ **Returns:**
61
+ - `client` - TestDriver instance
62
+ - `vscode` - Alias for client
63
+ - `dashcam` - Dashcam instance (if enabled)
64
+
65
+ ### electronPreset
66
+
67
+ Automatically sets up an Electron application.
68
+
69
+ ```javascript
70
+ import { electronPreset } from 'testdriverai/presets';
71
+
72
+ test('electron app test', async (context) => {
73
+ const { app } = await electronPreset(context, {
74
+ appPath: '/path/to/electron/app',
75
+ args: ['--enable-logging']
76
+ });
77
+
78
+ await app.find('main window').click();
79
+ });
80
+ ```
81
+
82
+ **Options:**
83
+ - `appPath` - Path to Electron app (required)
84
+ - `os` - Target OS (default: 'linux')
85
+ - `dashcam` - Enable Dashcam recording (default: true)
86
+ - `args` - Additional electron arguments
87
+
88
+ **Returns:**
89
+ - `client` - TestDriver instance
90
+ - `app` - Alias for client
91
+ - `dashcam` - Dashcam instance (if enabled)
92
+
93
+ ### webAppPreset
94
+
95
+ Generic web application preset (currently uses Chrome).
96
+
97
+ ```javascript
98
+ import { webAppPreset } from 'testdriverai/presets';
99
+
100
+ test('web app test', async (context) => {
101
+ const { client } = await webAppPreset(context, {
102
+ url: 'https://example.com',
103
+ browser: 'chrome' // Only Chrome supported currently
104
+ });
105
+
106
+ await client.find('login form').click();
107
+ });
108
+ ```
109
+
110
+ ## Creating Custom Presets
111
+
112
+ Use `createPreset` to build your own presets:
113
+
114
+ ```javascript
115
+ import { createPreset } from 'testdriverai/presets';
116
+
117
+ const firefoxPreset = createPreset({
118
+ name: 'Firefox Browser',
119
+ defaults: { os: 'linux', dashcam: true },
120
+ async setup(context, client, dashcam, options) {
121
+ const { url } = options;
122
+
123
+ // Launch Firefox
124
+ await client.exec('sh', `firefox "${url}" >/dev/null 2>&1 &`, 30000);
125
+ await client.focusApplication('Firefox');
126
+
127
+ return {
128
+ // client is already included automatically
129
+ };
130
+ },
131
+ });
132
+
133
+ // Use your custom preset
134
+ test('my test', async (context) => {
135
+ const { client } = await firefoxPreset(context, {
136
+ url: 'https://example.com',
137
+ });
138
+
139
+ await client.find('page content').click();
140
+ });
141
+ ```
142
+
143
+ ### createPreset API
144
+
145
+ ```javascript
146
+ createPreset({
147
+ name: string, // Preset name (for errors)
148
+ defaults: object, // Default options
149
+ setup: async function // Setup function
150
+ })
151
+ ```
152
+
153
+ The `setup` function receives:
154
+ - `context` - Vitest test context
155
+ - `client` - TestDriver instance (already connected)
156
+ - `dashcam` - Dashcam instance (if enabled)
157
+ - `options` - Merged defaults + user options
158
+
159
+ The `setup` function should return an object with any custom properties. The returned object will automatically include `client` and `dashcam`.
160
+
161
+ ## How Presets Work
162
+
163
+ Presets automatically:
164
+
165
+ 1. **Create TestDriver client** - Uses `useTestDriver` hook
166
+ 2. **Connect to sandbox** - Authenticates and connects
167
+ 3. **Set up Dashcam** - If enabled (default: true)
168
+ 4. **Configure application** - Launch and focus the app
169
+ 5. **Handle cleanup** - Automatic disconnect and dashcam stop
170
+
171
+ All lifecycle is managed automatically via Vitest hooks.
172
+
173
+ ## Progressive Disclosure
174
+
175
+ Presets fit into the progressive disclosure pattern:
176
+
177
+ ### Beginner (Presets)
178
+ ```javascript
179
+ const { client } = await chromePreset(context, { url: 'https://example.com' });
180
+ ```
181
+ Everything automatic - just pass URL and start testing.
182
+
183
+ ### Intermediate (Hooks)
184
+ ```javascript
185
+ const client = useTestDriver(context, { os: 'linux' });
186
+ const dashcam = useDashcam(context, client, { autoStart: true });
187
+ // Custom setup code
188
+ ```
189
+ More control over lifecycle, still automatic cleanup.
190
+
191
+ ### Advanced (Direct)
192
+ ```javascript
193
+ const client = new TestDriver(apiKey, { os: 'linux' });
194
+ await client.auth();
195
+ await client.connect();
196
+ // Full manual control
197
+ ```
198
+ Complete control, manual everything.
199
+
200
+ ## Best Practices
201
+
202
+ 1. **Use presets for common scenarios** - Chrome, VS Code, Electron
203
+ 2. **Create custom presets for your apps** - Encapsulate setup logic
204
+ 3. **Enable dashcam by default** - Great for debugging failures
205
+ 4. **Keep presets focused** - One app/scenario per preset
206
+ 5. **Use descriptive variable names** - `client`, `vscode`, `app` based on what you're testing
207
+
208
+ ## Examples
209
+
210
+ See `testdriver/acceptance-sdk/presets-example.test.mjs` for working examples.