testdriverai 7.0.0 → 7.1.1

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 (324) hide show
  1. package/.env.example +2 -0
  2. package/.github/workflows/linux-tests.yml +28 -0
  3. package/README.md +126 -0
  4. package/agent/index.js +7 -9
  5. package/agent/interface.js +13 -2
  6. package/agent/lib/commands.js +795 -136
  7. package/agent/lib/redraw.js +124 -39
  8. package/agent/lib/sandbox.js +40 -3
  9. package/agent/lib/sdk.js +21 -0
  10. package/agent/lib/valid-version.js +2 -2
  11. package/debugger/index.html +1 -1
  12. package/docs/docs.json +86 -71
  13. package/docs/guide/best-practices-polling.mdx +154 -0
  14. package/docs/v6/getting-started/self-hosting.mdx +3 -2
  15. package/docs/v7/_drafts/agents.mdx +852 -0
  16. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  17. package/docs/v7/_drafts/best-practices.mdx +486 -0
  18. package/docs/v7/_drafts/caching-ai.mdx +215 -0
  19. package/docs/v7/_drafts/caching-selectors.mdx +400 -0
  20. package/docs/v7/_drafts/caching.mdx +366 -0
  21. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
  22. package/docs/v7/_drafts/core.mdx +459 -0
  23. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  24. package/docs/v7/_drafts/debugging.mdx +349 -0
  25. package/docs/v7/_drafts/error-handling.mdx +501 -0
  26. package/docs/v7/_drafts/faq.mdx +393 -0
  27. package/docs/v7/_drafts/hooks.mdx +360 -0
  28. package/docs/v7/_drafts/implementation-plan.mdx +994 -0
  29. package/docs/v7/_drafts/init-command.mdx +95 -0
  30. package/docs/v7/_drafts/optimal-sdk-design.mdx +1348 -0
  31. package/docs/v7/_drafts/performance.mdx +517 -0
  32. package/docs/v7/_drafts/presets.mdx +210 -0
  33. package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
  34. package/docs/v7/_drafts/provision.mdx +266 -0
  35. package/docs/{QUICK_START_TEST_RECORDING.md → v7/_drafts/quick-start-test-recording.mdx} +3 -3
  36. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  37. package/docs/v7/{guides → _drafts}/self-hosting.mdx +1 -1
  38. package/docs/v7/_drafts/troubleshooting.mdx +526 -0
  39. package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
  40. package/docs/v7/_drafts/vitest.mdx +535 -0
  41. package/docs/v7/api/{ai.mdx → act.mdx} +24 -24
  42. package/docs/v7/api/client.mdx +1 -1
  43. package/docs/v7/api/dashcam.mdx +497 -0
  44. package/docs/v7/api/doubleClick.mdx +102 -0
  45. package/docs/v7/api/elements.mdx +143 -41
  46. package/docs/v7/api/find.mdx +258 -0
  47. package/docs/v7/api/mouseDown.mdx +161 -0
  48. package/docs/v7/api/mouseUp.mdx +164 -0
  49. package/docs/v7/api/rightClick.mdx +123 -0
  50. package/docs/v7/api/type.mdx +51 -7
  51. package/docs/v7/features/ai-native.mdx +427 -0
  52. package/docs/v7/features/easy-to-write.mdx +351 -0
  53. package/docs/v7/features/enterprise.mdx +540 -0
  54. package/docs/v7/features/fast.mdx +424 -0
  55. package/docs/v7/features/observable.mdx +623 -0
  56. package/docs/v7/features/powerful.mdx +531 -0
  57. package/docs/v7/features/scalable.mdx +417 -0
  58. package/docs/v7/features/stable.mdx +514 -0
  59. package/docs/v7/getting-started/configuration.mdx +380 -0
  60. package/docs/v7/getting-started/generating-tests.mdx +525 -0
  61. package/docs/v7/getting-started/installation.mdx +486 -0
  62. package/docs/v7/getting-started/quickstart.mdx +320 -141
  63. package/docs/v7/getting-started/running-and-debugging.mdx +511 -0
  64. package/docs/v7/getting-started/setting-up-in-ci.mdx +612 -0
  65. package/docs/v7/getting-started/writing-tests.mdx +535 -0
  66. package/docs/v7/overview/what-is-testdriver.mdx +398 -0
  67. package/docs/v7/platforms/linux.mdx +308 -0
  68. package/docs/v7/platforms/macos.mdx +433 -0
  69. package/docs/v7/platforms/windows.mdx +430 -0
  70. package/docs/v7/playwright.mdx +3 -3
  71. package/docs/v7/presets/chrome-extension.mdx +223 -0
  72. package/docs/v7/presets/chrome.mdx +303 -0
  73. package/docs/v7/presets/electron.mdx +453 -0
  74. package/docs/v7/presets/vscode.mdx +417 -0
  75. package/docs/v7/presets/webapp.mdx +396 -0
  76. package/examples/run-tests-with-recording.sh +2 -2
  77. package/interfaces/cli/commands/init.js +358 -0
  78. package/interfaces/vitest-plugin.mjs +393 -103
  79. package/lib/core/Dashcam.js +506 -0
  80. package/lib/core/index.d.ts +150 -0
  81. package/lib/core/index.js +12 -0
  82. package/lib/presets/index.mjs +331 -0
  83. package/lib/vitest/hooks.d.ts +119 -0
  84. package/lib/vitest/hooks.mjs +316 -0
  85. package/lib/vitest/setup.mjs +44 -0
  86. package/package.json +13 -3
  87. package/sdk.d.ts +350 -44
  88. package/sdk.js +818 -105
  89. package/{self-hosted.yml → setup/aws/self-hosted.yml} +1 -1
  90. package/test/manual/test-console-logs.test.mjs +42 -0
  91. package/test/manual/test-init.sh +54 -0
  92. package/test/manual/test-provision-auth.mjs +22 -0
  93. package/test/testdriver/assert.test.mjs +41 -0
  94. package/test/testdriver/auto-cache-key-demo.test.mjs +56 -0
  95. package/test/testdriver/chrome-extension.test.mjs +89 -0
  96. package/{testdriver/acceptance-sdk → test/testdriver}/drag-and-drop.test.mjs +7 -19
  97. package/{testdriver/acceptance-sdk → test/testdriver}/element-not-found.test.mjs +6 -19
  98. package/{testdriver/acceptance-sdk → test/testdriver}/exec-js.test.mjs +6 -18
  99. package/{testdriver/acceptance-sdk → test/testdriver}/exec-output.test.mjs +9 -21
  100. package/{testdriver/acceptance-sdk → test/testdriver}/exec-pwsh.test.mjs +14 -26
  101. package/{testdriver/acceptance-sdk → test/testdriver}/focus-window.test.mjs +8 -20
  102. package/{testdriver/acceptance-sdk → test/testdriver}/formatted-logging.test.mjs +5 -20
  103. package/{testdriver/acceptance-sdk → test/testdriver}/hover-image.test.mjs +10 -19
  104. package/{testdriver/acceptance-sdk → test/testdriver}/hover-text-with-description.test.mjs +7 -19
  105. package/{testdriver/acceptance-sdk → test/testdriver}/hover-text.test.mjs +5 -19
  106. package/{testdriver/acceptance-sdk → test/testdriver}/match-image.test.mjs +7 -19
  107. package/{testdriver/acceptance-sdk → test/testdriver}/press-keys.test.mjs +5 -19
  108. package/{testdriver/acceptance-sdk → test/testdriver}/prompt.test.mjs +7 -19
  109. package/{testdriver/acceptance-sdk → test/testdriver}/scroll-keyboard.test.mjs +6 -20
  110. package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-image.test.mjs +6 -18
  111. package/test/testdriver/scroll-until-text.test.mjs +28 -0
  112. package/{testdriver/acceptance-sdk → test/testdriver}/scroll.test.mjs +12 -21
  113. package/test/testdriver/setup/lifecycleHelpers.mjs +262 -0
  114. package/{testdriver/acceptance-sdk → test/testdriver}/setup/testHelpers.mjs +25 -20
  115. package/test/testdriver/type.test.mjs +45 -0
  116. package/vitest.config.mjs +11 -56
  117. package/.github/dependabot.yml +0 -11
  118. package/.github/workflows/acceptance-linux.yml +0 -75
  119. package/.github/workflows/acceptance-sdk-tests.yml +0 -133
  120. package/.github/workflows/acceptance-tests.yml +0 -130
  121. package/.github/workflows/lint.yml +0 -27
  122. package/.github/workflows/publish-canary.yml +0 -40
  123. package/.github/workflows/publish-latest.yml +0 -61
  124. package/.github/workflows/test-install.yml +0 -29
  125. package/.vscode/extensions.json +0 -3
  126. package/.vscode/launch.json +0 -22
  127. package/.vscode/mcp.json +0 -9
  128. package/.vscode/settings.json +0 -14
  129. package/CODEOWNERS +0 -3
  130. package/MIGRATION.md +0 -389
  131. package/SDK_README.md +0 -1122
  132. package/_testdriver/acceptance/assert.yaml +0 -7
  133. package/_testdriver/acceptance/dashcam.yaml +0 -9
  134. package/_testdriver/acceptance/drag-and-drop.yaml +0 -49
  135. package/_testdriver/acceptance/embed.yaml +0 -9
  136. package/_testdriver/acceptance/exec-js.yaml +0 -29
  137. package/_testdriver/acceptance/exec-output.yaml +0 -43
  138. package/_testdriver/acceptance/exec-shell.yaml +0 -40
  139. package/_testdriver/acceptance/focus-window.yaml +0 -16
  140. package/_testdriver/acceptance/hover-image.yaml +0 -18
  141. package/_testdriver/acceptance/hover-text-with-description.yaml +0 -29
  142. package/_testdriver/acceptance/hover-text.yaml +0 -14
  143. package/_testdriver/acceptance/if-else.yaml +0 -31
  144. package/_testdriver/acceptance/match-image.yaml +0 -15
  145. package/_testdriver/acceptance/press-keys.yaml +0 -35
  146. package/_testdriver/acceptance/prompt.yaml +0 -11
  147. package/_testdriver/acceptance/remember.yaml +0 -27
  148. package/_testdriver/acceptance/screenshots/cart.png +0 -0
  149. package/_testdriver/acceptance/scroll-keyboard.yaml +0 -34
  150. package/_testdriver/acceptance/scroll-until-image.yaml +0 -26
  151. package/_testdriver/acceptance/scroll-until-text.yaml +0 -20
  152. package/_testdriver/acceptance/scroll.yaml +0 -33
  153. package/_testdriver/acceptance/snippets/login.yaml +0 -29
  154. package/_testdriver/acceptance/snippets/match-cart.yaml +0 -8
  155. package/_testdriver/acceptance/type.yaml +0 -29
  156. package/_testdriver/behavior/failure.yaml +0 -7
  157. package/_testdriver/behavior/hover-text.yaml +0 -13
  158. package/_testdriver/behavior/lifecycle/postrun.yaml +0 -10
  159. package/_testdriver/behavior/lifecycle/prerun.yaml +0 -8
  160. package/_testdriver/behavior/lifecycle/provision.yaml +0 -8
  161. package/_testdriver/behavior/secrets.yaml +0 -7
  162. package/_testdriver/edge-cases/dashcam-chrome.yaml +0 -8
  163. package/_testdriver/edge-cases/exec-pwsh-multiline.yaml +0 -10
  164. package/_testdriver/edge-cases/js-exception.yaml +0 -8
  165. package/_testdriver/edge-cases/js-promise.yaml +0 -19
  166. package/_testdriver/edge-cases/lifecycle/postrun.yaml +0 -10
  167. package/_testdriver/edge-cases/prompt-in-middle.yaml +0 -23
  168. package/_testdriver/edge-cases/prompt-nested.yaml +0 -7
  169. package/_testdriver/edge-cases/success-test.yaml +0 -9
  170. package/_testdriver/examples/android/example.yaml +0 -12
  171. package/_testdriver/examples/android/lifecycle/postrun.yaml +0 -11
  172. package/_testdriver/examples/android/lifecycle/provision.yaml +0 -47
  173. package/_testdriver/examples/android/readme.md +0 -7
  174. package/_testdriver/examples/chrome-extension/lifecycle/provision.yaml +0 -74
  175. package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
  176. package/_testdriver/examples/desktop/lifecycle/provision.yaml +0 -64
  177. package/_testdriver/examples/vscode-extension/lifecycle/provision.yaml +0 -73
  178. package/_testdriver/examples/web/lifecycle/postrun.yaml +0 -7
  179. package/_testdriver/examples/web/lifecycle/prerun.yaml +0 -22
  180. package/_testdriver/lifecycle/postrun.yaml +0 -8
  181. package/_testdriver/lifecycle/prerun.yaml +0 -15
  182. package/_testdriver/lifecycle/provision.yaml +0 -25
  183. package/debug-screenshot-1763401388589.png +0 -0
  184. package/mcp-server/AI_GUIDELINES.md +0 -57
  185. package/scripts/view-test-results.mjs +0 -96
  186. package/styles/.vale-config/2-MDX.ini +0 -5
  187. package/styles/Microsoft/AMPM.yml +0 -9
  188. package/styles/Microsoft/Accessibility.yml +0 -30
  189. package/styles/Microsoft/Acronyms.yml +0 -64
  190. package/styles/Microsoft/Adverbs.yml +0 -272
  191. package/styles/Microsoft/Auto.yml +0 -11
  192. package/styles/Microsoft/Avoid.yml +0 -14
  193. package/styles/Microsoft/Contractions.yml +0 -50
  194. package/styles/Microsoft/Dashes.yml +0 -13
  195. package/styles/Microsoft/DateFormat.yml +0 -8
  196. package/styles/Microsoft/DateNumbers.yml +0 -40
  197. package/styles/Microsoft/DateOrder.yml +0 -8
  198. package/styles/Microsoft/Ellipses.yml +0 -9
  199. package/styles/Microsoft/FirstPerson.yml +0 -16
  200. package/styles/Microsoft/Foreign.yml +0 -13
  201. package/styles/Microsoft/Gender.yml +0 -8
  202. package/styles/Microsoft/GenderBias.yml +0 -42
  203. package/styles/Microsoft/GeneralURL.yml +0 -11
  204. package/styles/Microsoft/HeadingAcronyms.yml +0 -7
  205. package/styles/Microsoft/HeadingColons.yml +0 -8
  206. package/styles/Microsoft/HeadingPunctuation.yml +0 -13
  207. package/styles/Microsoft/Headings.yml +0 -28
  208. package/styles/Microsoft/Hyphens.yml +0 -14
  209. package/styles/Microsoft/Negative.yml +0 -13
  210. package/styles/Microsoft/Ordinal.yml +0 -13
  211. package/styles/Microsoft/OxfordComma.yml +0 -8
  212. package/styles/Microsoft/Passive.yml +0 -183
  213. package/styles/Microsoft/Percentages.yml +0 -7
  214. package/styles/Microsoft/Plurals.yml +0 -7
  215. package/styles/Microsoft/Quotes.yml +0 -7
  216. package/styles/Microsoft/RangeTime.yml +0 -13
  217. package/styles/Microsoft/Semicolon.yml +0 -8
  218. package/styles/Microsoft/SentenceLength.yml +0 -6
  219. package/styles/Microsoft/Spacing.yml +0 -8
  220. package/styles/Microsoft/Suspended.yml +0 -7
  221. package/styles/Microsoft/Terms.yml +0 -42
  222. package/styles/Microsoft/URLFormat.yml +0 -9
  223. package/styles/Microsoft/Units.yml +0 -16
  224. package/styles/Microsoft/Vocab.yml +0 -25
  225. package/styles/Microsoft/We.yml +0 -11
  226. package/styles/Microsoft/Wordiness.yml +0 -127
  227. package/styles/Microsoft/meta.json +0 -4
  228. package/styles/alex/Ablist.yml +0 -274
  229. package/styles/alex/Condescending.yml +0 -16
  230. package/styles/alex/Gendered.yml +0 -110
  231. package/styles/alex/LGBTQ.yml +0 -55
  232. package/styles/alex/OCD.yml +0 -10
  233. package/styles/alex/Press.yml +0 -12
  234. package/styles/alex/ProfanityLikely.yml +0 -1289
  235. package/styles/alex/ProfanityMaybe.yml +0 -282
  236. package/styles/alex/ProfanityUnlikely.yml +0 -251
  237. package/styles/alex/README.md +0 -27
  238. package/styles/alex/Race.yml +0 -85
  239. package/styles/alex/Suicide.yml +0 -26
  240. package/styles/alex/meta.json +0 -4
  241. package/styles/config/vocabularies/Docs/accept.txt +0 -47
  242. package/styles/config/vocabularies/Docs/reject.txt +0 -4
  243. package/styles/proselint/Airlinese.yml +0 -8
  244. package/styles/proselint/AnimalLabels.yml +0 -48
  245. package/styles/proselint/Annotations.yml +0 -9
  246. package/styles/proselint/Apologizing.yml +0 -8
  247. package/styles/proselint/Archaisms.yml +0 -52
  248. package/styles/proselint/But.yml +0 -8
  249. package/styles/proselint/Cliches.yml +0 -782
  250. package/styles/proselint/CorporateSpeak.yml +0 -30
  251. package/styles/proselint/Currency.yml +0 -5
  252. package/styles/proselint/Cursing.yml +0 -15
  253. package/styles/proselint/DateCase.yml +0 -7
  254. package/styles/proselint/DateMidnight.yml +0 -7
  255. package/styles/proselint/DateRedundancy.yml +0 -10
  256. package/styles/proselint/DateSpacing.yml +0 -7
  257. package/styles/proselint/DenizenLabels.yml +0 -52
  258. package/styles/proselint/Diacritical.yml +0 -95
  259. package/styles/proselint/GenderBias.yml +0 -45
  260. package/styles/proselint/GroupTerms.yml +0 -39
  261. package/styles/proselint/Hedging.yml +0 -8
  262. package/styles/proselint/Hyperbole.yml +0 -6
  263. package/styles/proselint/Jargon.yml +0 -11
  264. package/styles/proselint/LGBTOffensive.yml +0 -13
  265. package/styles/proselint/LGBTTerms.yml +0 -15
  266. package/styles/proselint/Malapropisms.yml +0 -8
  267. package/styles/proselint/Needless.yml +0 -358
  268. package/styles/proselint/Nonwords.yml +0 -38
  269. package/styles/proselint/Oxymorons.yml +0 -22
  270. package/styles/proselint/P-Value.yml +0 -6
  271. package/styles/proselint/RASSyndrome.yml +0 -30
  272. package/styles/proselint/README.md +0 -12
  273. package/styles/proselint/Skunked.yml +0 -13
  274. package/styles/proselint/Spelling.yml +0 -17
  275. package/styles/proselint/Typography.yml +0 -11
  276. package/styles/proselint/Uncomparables.yml +0 -50
  277. package/styles/proselint/Very.yml +0 -6
  278. package/styles/proselint/meta.json +0 -15
  279. package/styles/write-good/Cliches.yml +0 -702
  280. package/styles/write-good/E-Prime.yml +0 -32
  281. package/styles/write-good/Illusions.yml +0 -11
  282. package/styles/write-good/Passive.yml +0 -183
  283. package/styles/write-good/README.md +0 -27
  284. package/styles/write-good/So.yml +0 -5
  285. package/styles/write-good/ThereIs.yml +0 -6
  286. package/styles/write-good/TooWordy.yml +0 -221
  287. package/styles/write-good/Weasel.yml +0 -29
  288. package/styles/write-good/meta.json +0 -4
  289. package/test/mcp-example-test.yaml +0 -27
  290. package/test/test_parser.js +0 -47
  291. package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +0 -61
  292. package/testdriver/acceptance-sdk/README.md +0 -128
  293. package/testdriver/acceptance-sdk/TEST_REPORTING.md +0 -245
  294. package/testdriver/acceptance-sdk/assert.test.mjs +0 -44
  295. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +0 -42
  296. package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +0 -239
  297. package/testdriver/acceptance-sdk/type-checking-demo.js +0 -49
  298. package/testdriver/acceptance-sdk/type.test.mjs +0 -84
  299. package/vale.ini +0 -18
  300. package/vitest.config.example.js +0 -19
  301. package/vitest.config.mjs.bak +0 -44
  302. /package/docs/{ARCHITECTURE.md → v7/_drafts/architecture.mdx} +0 -0
  303. /package/docs/{AWESOME_LOGS_QUICK_REF.md → v7/_drafts/awesome-logs-quick-ref.mdx} +0 -0
  304. /package/{CONTRIBUTING.md → docs/v7/_drafts/contributing.mdx} +0 -0
  305. /package/docs/v7/{guides → _drafts}/migration.mdx +0 -0
  306. /package/{PLUGIN_MIGRATION.md → docs/v7/_drafts/plugin-migration.mdx} +0 -0
  307. /package/{PROMPT_CACHE.md → docs/v7/_drafts/prompt-cache.mdx} +0 -0
  308. /package/docs/{SDK_AWESOME_LOGS.md → v7/_drafts/sdk-awesome-logs.mdx} +0 -0
  309. /package/docs/{sdk-browser-rendering.md → v7/_drafts/sdk-browser-rendering.mdx} +0 -0
  310. /package/{SDK_LOGGING.md → docs/v7/_drafts/sdk-logging.mdx} +0 -0
  311. /package/{SDK_MIGRATION.md → docs/v7/_drafts/sdk-migration.mdx} +0 -0
  312. /package/docs/{TEST_RECORDING.md → v7/_drafts/test-recording.mdx} +0 -0
  313. /package/docs/v7/{README.md → overview/readme.mdx} +0 -0
  314. /package/{debug-locate-response.js → test/manual/debug-locate-response.js} +0 -0
  315. /package/{test-find-api.js → test/manual/test-find-api.js} +0 -0
  316. /package/{test-prompt-cache.js → test/manual/test-prompt-cache.js} +0 -0
  317. /package/{test-sandbox-render.js → test/manual/test-sandbox-render.js} +0 -0
  318. /package/{test-sdk-methods.js → test/manual/test-sdk-methods.js} +0 -0
  319. /package/{test-sdk-refactor.js → test/manual/test-sdk-refactor.js} +0 -0
  320. /package/{test-stack-trace.mjs → test/manual/test-stack-trace.mjs} +0 -0
  321. /package/{verify-element-api.js → test/manual/verify-element-api.js} +0 -0
  322. /package/{verify-types.js → test/manual/verify-types.js} +0 -0
  323. /package/{testdriver/acceptance-sdk → test/testdriver}/setup/globalTeardown.mjs +0 -0
  324. /package/{testdriver/acceptance-sdk → test/testdriver}/setup/vitestSetup.mjs +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