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