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,287 @@
1
+ ---
2
+ title: "Web Apps"
3
+ sidebarTitle: "Web Apps"
4
+ description: "Automatically launch and test Chrome browser applications"
5
+ icon: "chrome"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ The `chrome()` preset automatically sets up a Chrome browser with TestDriver and Dashcam recording. It's the easiest way to test web applications.
11
+
12
+ ## Quick Start
13
+
14
+ ```javascript
15
+ import { test } from 'vitest';
16
+ import { chrome } from 'testdriverai/presets';
17
+
18
+ test('login test', async (context) => {
19
+ const { testdriver } = await chrome(context, {
20
+ url: 'https://myapp.com/login'
21
+ });
22
+
23
+ await testdriver.find('email input').type('user@example.com');
24
+ await testdriver.find('password input').type('password123');
25
+ await testdriver.find('Login button').click();
26
+
27
+ await testdriver.assert('Welcome message is visible');
28
+ });
29
+ ```
30
+
31
+ ## Signature
32
+
33
+ ```typescript
34
+ chrome(context, options): Promise<ChromeResult>
35
+ ```
36
+
37
+ ### Parameters
38
+
39
+ <ParamField path="context" type="object" required>
40
+ Vitest test context - automatically passed to your test function
41
+ </ParamField>
42
+
43
+ <ParamField path="options" type="object">
44
+ Configuration options for Chrome
45
+
46
+ <Expandable title="properties">
47
+ <ParamField path="url" type="string" default="http://testdriver-sandbox.vercel.app/">
48
+ URL to navigate to when Chrome launches
49
+ </ParamField>
50
+
51
+ <ParamField path="maximized" type="boolean" default={true}>
52
+ Start Chrome in maximized window mode
53
+ </ParamField>
54
+
55
+ <ParamField path="guest" type="boolean" default={true}>
56
+ Use Chrome guest/incognito mode (no profile data)
57
+ </ParamField>
58
+
59
+ <ParamField path="dashcam" type="boolean" default={true}>
60
+ Enable Dashcam test recording
61
+ </ParamField>
62
+
63
+ <ParamField path="os" type="'linux' | 'mac' | 'windows'" default="linux">
64
+ Target operating system for the test
65
+ </ParamField>
66
+ </Expandable>
67
+ </ParamField>
68
+
69
+ ### Returns
70
+
71
+ <ResponseField name="testdriver" type="TestDriver" required>
72
+ TestDriver instance ready to use
73
+ </ResponseField>
74
+
75
+ <ResponseField name="dashcam" type="Dashcam">
76
+ Dashcam instance for test recording (if enabled)
77
+ </ResponseField>
78
+
79
+ ## Examples
80
+
81
+ ### Basic Web App Testing
82
+
83
+ ```javascript
84
+ import { test } from 'vitest';
85
+ import { chrome } from 'testdriverai/presets';
86
+
87
+ test('search functionality', async (context) => {
88
+ const { testdriver } = await chrome(context, {
89
+ url: 'https://example.com'
90
+ });
91
+
92
+ await testdriver.find('search input').type('TestDriver');
93
+ await testdriver.find('search button').click();
94
+ await testdriver.assert('search results are displayed');
95
+ });
96
+ ```
97
+
98
+ ### With Dashcam Recording
99
+
100
+ ```javascript
101
+ import { test, expect } from 'vitest';
102
+ import { chrome } from 'testdriverai/presets';
103
+
104
+ test('checkout flow', async (context) => {
105
+ const { testdriver, dashcam } = await chrome(context, {
106
+ url: 'https://shop.example.com',
107
+ maximized: true
108
+ });
109
+
110
+ // Add items to cart
111
+ await testdriver.find('Add to Cart button').click();
112
+ await testdriver.find('View Cart').click();
113
+
114
+ // Proceed to checkout
115
+ await testdriver.find('Checkout button').click();
116
+
117
+ // Fill shipping info
118
+ await testdriver.find('Name input').type('John Doe');
119
+ await testdriver.find('Address input').type('123 Main St');
120
+
121
+ // Submit order
122
+ await testdriver.find('Place Order').click();
123
+
124
+ // Verify confirmation
125
+ const confirmed = await testdriver.assert('Order confirmed');
126
+ expect(confirmed).toBeTruthy();
127
+
128
+ // Dashcam automatically saves replay URL when test completes
129
+ });
130
+ ```
131
+
132
+ ### Testing on Different Operating Systems
133
+
134
+ ```javascript
135
+ import { test } from 'vitest';
136
+ import { chrome } from 'testdriverai/presets';
137
+
138
+ test('windows chrome test', async (context) => {
139
+ const { testdriver } = await chrome(context, {
140
+ url: 'https://myapp.com',
141
+ os: 'windows'
142
+ });
143
+
144
+ await testdriver.find('Start').click();
145
+ });
146
+
147
+ test('mac chrome test', async (context) => {
148
+ const { testdriver } = await chrome(context, {
149
+ url: 'https://myapp.com',
150
+ os: 'mac'
151
+ });
152
+
153
+ await testdriver.find('Start').click();
154
+ });
155
+ ```
156
+
157
+ ### Without Dashcam
158
+
159
+ ```javascript
160
+ import { test } from 'vitest';
161
+ import { chrome } from 'testdriverai/presets';
162
+
163
+ test('quick test without recording', async (context) => {
164
+ const { testdriver } = await chrome(context, {
165
+ url: 'https://example.com',
166
+ dashcam: false // Disable Dashcam for faster execution
167
+ });
168
+
169
+ await testdriver.find('button').click();
170
+ });
171
+ ```
172
+
173
+ ### Testing Chrome Extensions
174
+
175
+ ```javascript
176
+ import { test } from 'vitest';
177
+ import { chrome } from 'testdriverai/presets';
178
+
179
+ test('chrome extension', async (context) => {
180
+ const { testdriver } = await chrome(context, {
181
+ url: 'chrome://extensions',
182
+ guest: false, // Need profile for extensions
183
+ maximized: true
184
+ });
185
+
186
+ await testdriver.find('Developer mode toggle').click();
187
+ await testdriver.find('Load unpacked').click();
188
+ });
189
+ ```
190
+
191
+ ## What It Does
192
+
193
+ When you call `chrome()`, it automatically:
194
+
195
+ 1. **Initializes TestDriver** - Creates and connects to sandbox
196
+ 2. **Sets up Dashcam** - Authenticates and starts recording (if enabled)
197
+ 3. **Launches Chrome** - Opens browser with your specified options
198
+ 4. **Navigates to URL** - Loads your application
199
+ 5. **Waits for Ready** - Ensures Chrome is focused and page is loaded
200
+ 6. **Returns Instances** - Provides ready-to-use testdriver and dashcam
201
+
202
+ At test end:
203
+ - Dashcam automatically stops and saves replay URL
204
+ - TestDriver automatically disconnects
205
+ - All cleanup is handled for you
206
+
207
+ ## Common Patterns
208
+
209
+ ### Form Filling
210
+
211
+ ```javascript
212
+ test('user registration', async (context) => {
213
+ const { testdriver } = await chrome(context, {
214
+ url: 'https://myapp.com/register'
215
+ });
216
+
217
+ await testdriver.find('email field').type('user@example.com');
218
+ await testdriver.find('password field').type('SecurePass123!');
219
+ await testdriver.find('confirm password field').type('SecurePass123!');
220
+ await testdriver.find('terms checkbox').click();
221
+ await testdriver.find('Sign Up button').click();
222
+
223
+ await testdriver.assert('Registration successful message appears');
224
+ });
225
+ ```
226
+
227
+ ### Navigation Testing
228
+
229
+ ```javascript
230
+ test('multi-page navigation', async (context) => {
231
+ const { testdriver } = await chrome(context, {
232
+ url: 'https://myapp.com'
233
+ });
234
+
235
+ // Navigate through pages
236
+ await testdriver.find('About link').click();
237
+ await testdriver.assert('About page heading is visible');
238
+
239
+ await testdriver.find('Services link').click();
240
+ await testdriver.assert('Services page content is loaded');
241
+
242
+ await testdriver.find('Contact link').click();
243
+ await testdriver.assert('Contact form is displayed');
244
+ });
245
+ ```
246
+
247
+ ### Error Handling
248
+
249
+ ```javascript
250
+ test('handles errors gracefully', async (context) => {
251
+ try {
252
+ const { testdriver } = await chrome(context, {
253
+ url: 'https://myapp.com'
254
+ });
255
+
256
+ await testdriver.find('non-existent element').click();
257
+ } catch (error) {
258
+ // Cleanup still happens automatically via Vitest hooks
259
+ console.error('Test failed:', error);
260
+ throw error; // Re-throw to mark test as failed
261
+ }
262
+ });
263
+ ```
264
+
265
+ ## Using with provision()
266
+
267
+ The `chrome()` preset can also be called via the unified `provision()` function:
268
+
269
+ ```javascript
270
+ import { provision } from 'testdriverai/presets';
271
+
272
+ test('using provision', async (context) => {
273
+ const { testdriver } = await provision('chrome', {
274
+ url: 'https://example.com'
275
+ }, context);
276
+
277
+ // Same functionality as chrome() directly
278
+ });
279
+ ```
280
+
281
+ ## See Also
282
+
283
+ - [Provision API](/v7/progressive-apis/PROVISION) - Overview of all presets
284
+ - [VS Code Preset](/v7/presets/vscode) - Testing VS Code extensions
285
+ - [Electron Preset](/v7/presets/electron) - Testing Electron apps
286
+ - [Vitest Integration](/v7/guides/vitest) - Complete Vitest setup guide
287
+ - [Hooks API](/v7/progressive-apis/HOOKS) - Manual lifecycle control
@@ -0,0 +1,435 @@
1
+ ---
2
+ title: "Desktop Apps"
3
+ sidebarTitle: "Desktop Apps"
4
+ description: "Automatically launch and test Electron applications"
5
+ icon: "atom"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ The `electron()` preset automatically sets up an Electron application with TestDriver and Dashcam recording. Perfect for testing desktop apps built with Electron.
11
+
12
+ ## Quick Start
13
+
14
+ ```javascript
15
+ import { test } from 'vitest';
16
+ import { electron } from 'testdriverai/presets';
17
+
18
+ test('electron app test', async (context) => {
19
+ const { app } = await electron(context, {
20
+ appPath: './dist/my-app'
21
+ });
22
+
23
+ await app.find('main window').click();
24
+ await app.find('File menu').click();
25
+ await app.find('New Document').click();
26
+ });
27
+ ```
28
+
29
+ ## Signature
30
+
31
+ ```typescript
32
+ electron(context, options): Promise<ElectronResult>
33
+ ```
34
+
35
+ ### Parameters
36
+
37
+ <ParamField path="context" type="object" required>
38
+ Vitest test context - automatically passed to your test function
39
+ </ParamField>
40
+
41
+ <ParamField path="options" type="object">
42
+ Configuration options for Electron
43
+
44
+ <Expandable title="properties">
45
+ <ParamField path="appPath" type="string" required>
46
+ Path to your Electron application executable or main file
47
+ </ParamField>
48
+
49
+ <ParamField path="args" type="string[]" default={[]}>
50
+ Additional command-line arguments to pass to Electron
51
+ </ParamField>
52
+
53
+ <ParamField path="dashcam" type="boolean" default={true}>
54
+ Enable Dashcam test recording
55
+ </ParamField>
56
+
57
+ <ParamField path="os" type="'linux' | 'mac' | 'windows'" default="linux">
58
+ Target operating system for the test
59
+ </ParamField>
60
+ </Expandable>
61
+ </ParamField>
62
+
63
+ ### Returns
64
+
65
+ <ResponseField name="testdriver" type="TestDriver" required>
66
+ TestDriver instance ready to use
67
+ </ResponseField>
68
+
69
+ <ResponseField name="app" type="TestDriver" required>
70
+ Alias for testdriver (semantic clarity for Electron apps)
71
+ </ResponseField>
72
+
73
+ <ResponseField name="dashcam" type="Dashcam">
74
+ Dashcam instance for test recording (if enabled)
75
+ </ResponseField>
76
+
77
+ ## Examples
78
+
79
+ ### Basic Electron App
80
+
81
+ ```javascript
82
+ import { test } from 'vitest';
83
+ import { electron } from 'testdriverai/presets';
84
+
85
+ test('opens main window', async (context) => {
86
+ const { app } = await electron(context, {
87
+ appPath: './dist/my-electron-app'
88
+ });
89
+
90
+ await app.assert('Main window is visible');
91
+ await app.find('Welcome message').click();
92
+ });
93
+ ```
94
+
95
+ ### With Command-Line Arguments
96
+
97
+ ```javascript
98
+ import { test } from 'vitest';
99
+ import { electron } from 'testdriverai/presets';
100
+
101
+ test('app with debug mode', async (context) => {
102
+ const { app } = await electron(context, {
103
+ appPath: './dist/app',
104
+ args: [
105
+ '--enable-logging',
106
+ '--debug',
107
+ '--user-data-dir=/tmp/test-data'
108
+ ]
109
+ });
110
+
111
+ await app.find('Debug panel').click();
112
+ await app.assert('Debug information is visible');
113
+ });
114
+ ```
115
+
116
+ ### Menu Navigation
117
+
118
+ ```javascript
119
+ import { test } from 'vitest';
120
+ import { electron } from 'testdriverai/presets';
121
+
122
+ test('file menu operations', async (context) => {
123
+ const { app } = await electron(context, {
124
+ appPath: './dist/editor-app'
125
+ });
126
+
127
+ // Open File menu
128
+ await app.find('File').click();
129
+ await app.find('New File').click();
130
+
131
+ // Verify new file created
132
+ await app.assert('Untitled document is open');
133
+
134
+ // Save file
135
+ await app.find('File').click();
136
+ await app.find('Save As').click();
137
+ await app.type('test-document.txt');
138
+ await app.pressKeys(['enter']);
139
+
140
+ await app.assert('File saved successfully');
141
+ });
142
+ ```
143
+
144
+ ### Testing on Different Platforms
145
+
146
+ ```javascript
147
+ import { test } from 'vitest';
148
+ import { electron } from 'testdriverai/presets';
149
+
150
+ test('windows electron app', async (context) => {
151
+ const { app } = await electron(context, {
152
+ appPath: 'C:\\Program Files\\MyApp\\MyApp.exe',
153
+ os: 'windows'
154
+ });
155
+
156
+ await app.find('Start button').click();
157
+ });
158
+
159
+ test('mac electron app', async (context) => {
160
+ const { app } = await electron(context, {
161
+ appPath: '/Applications/MyApp.app/Contents/MacOS/MyApp',
162
+ os: 'mac'
163
+ });
164
+
165
+ await app.find('Start button').click();
166
+ });
167
+ ```
168
+
169
+ ### Preferences and Settings
170
+
171
+ ```javascript
172
+ import { test } from 'vitest';
173
+ import { electron } from 'testdriverai/presets';
174
+
175
+ test('configure app settings', async (context) => {
176
+ const { app } = await electron(context, {
177
+ appPath: './dist/my-app'
178
+ });
179
+
180
+ // Open preferences
181
+ await app.find('Settings').click();
182
+
183
+ // Change theme
184
+ await app.find('Appearance').click();
185
+ await app.find('Dark mode toggle').click();
186
+
187
+ // Verify change
188
+ await app.assert('Dark mode is enabled');
189
+
190
+ // Save settings
191
+ await app.find('Save button').click();
192
+
193
+ await app.assert('Settings saved');
194
+ });
195
+ ```
196
+
197
+ ### Window Management
198
+
199
+ ```javascript
200
+ import { test } from 'vitest';
201
+ import { electron } from 'testdriverai/presets';
202
+
203
+ test('multiple windows', async (context) => {
204
+ const { app } = await electron(context, {
205
+ appPath: './dist/multi-window-app'
206
+ });
207
+
208
+ // Open new window
209
+ await app.find('File').click();
210
+ await app.find('New Window').click();
211
+
212
+ // Switch between windows
213
+ await app.find('second window').click();
214
+ await app.assert('Second window is focused');
215
+
216
+ // Close window
217
+ await app.find('Close button').click();
218
+
219
+ await app.assert('Window closed');
220
+ });
221
+ ```
222
+
223
+ ### Form Interaction
224
+
225
+ ```javascript
226
+ import { test } from 'vitest';
227
+ import { electron } from 'testdriverai/presets';
228
+
229
+ test('form submission', async (context) => {
230
+ const { app, dashcam } = await electron(context, {
231
+ appPath: './dist/form-app'
232
+ });
233
+
234
+ // Fill form
235
+ await app.find('Name input').type('John Doe');
236
+ await app.find('Email input').type('john@example.com');
237
+ await app.find('Phone input').type('555-1234');
238
+
239
+ // Select dropdown
240
+ await app.find('Country dropdown').click();
241
+ await app.find('United States').click();
242
+
243
+ // Check checkbox
244
+ await app.find('Terms and conditions').click();
245
+
246
+ // Submit
247
+ await app.find('Submit button').click();
248
+
249
+ await app.assert('Form submitted successfully');
250
+
251
+ // Dashcam captures entire interaction
252
+ });
253
+ ```
254
+
255
+ ## What It Does
256
+
257
+ When you call `electron()`, it automatically:
258
+
259
+ 1. **Initializes TestDriver** - Creates and connects to sandbox
260
+ 2. **Sets up Dashcam** - Authenticates and starts recording (if enabled)
261
+ 3. **Launches Electron** - Starts your app with specified arguments
262
+ 4. **Waits for Ready** - Ensures app is focused and windows are loaded
263
+ 5. **Returns Instances** - Provides ready-to-use testdriver, app alias, and dashcam
264
+
265
+ At test end:
266
+ - Dashcam automatically stops and saves replay URL
267
+ - TestDriver automatically disconnects
268
+ - All cleanup is handled for you
269
+
270
+ ## Common Patterns
271
+
272
+ ### IPC Communication Testing
273
+
274
+ ```javascript
275
+ test('ipc events', async (context) => {
276
+ const { app } = await electron(context, {
277
+ appPath: './dist/ipc-app'
278
+ });
279
+
280
+ // Trigger IPC event from renderer
281
+ await app.find('Send Message button').click();
282
+
283
+ // Verify main process response
284
+ await app.assert('Response received from main process');
285
+ });
286
+ ```
287
+
288
+ ### Notification Testing
289
+
290
+ ```javascript
291
+ test('system notifications', async (context) => {
292
+ const { app } = await electron(context, {
293
+ appPath: './dist/notification-app'
294
+ });
295
+
296
+ await app.find('Show Notification').click();
297
+ await app.assert('System notification appears');
298
+ });
299
+ ```
300
+
301
+ ### Tray Icon Interaction
302
+
303
+ ```javascript
304
+ test('system tray', async (context) => {
305
+ const { app } = await electron(context, {
306
+ appPath: './dist/tray-app'
307
+ });
308
+
309
+ // Click tray icon
310
+ await app.find('app tray icon').click();
311
+
312
+ // Interact with tray menu
313
+ await app.find('Show Window').click();
314
+
315
+ await app.assert('Main window appears');
316
+ });
317
+ ```
318
+
319
+ ### Auto-Update Flow
320
+
321
+ ```javascript
322
+ test('app update', async (context) => {
323
+ const { app } = await electron(context, {
324
+ appPath: './dist/updatable-app',
325
+ args: ['--check-updates']
326
+ });
327
+
328
+ await app.find('Check for Updates').click();
329
+ await app.assert('Checking for updates message');
330
+
331
+ // Assuming update is available
332
+ await app.find('Download Update').click();
333
+ await app.assert('Update downloaded');
334
+ });
335
+ ```
336
+
337
+ ## Development Paths
338
+
339
+ ### Common Development Paths
340
+
341
+ ```javascript
342
+ // Electron Forge
343
+ appPath: './out/my-app-linux-x64/my-app'
344
+
345
+ // Electron Builder
346
+ appPath: './dist/linux-unpacked/my-app'
347
+
348
+ // Direct execution
349
+ appPath: './node_modules/.bin/electron'
350
+ args: ['./main.js']
351
+
352
+ // Packaged app (Windows)
353
+ appPath: 'C:\\Program Files\\MyApp\\MyApp.exe'
354
+
355
+ // Packaged app (macOS)
356
+ appPath: '/Applications/MyApp.app/Contents/MacOS/MyApp'
357
+
358
+ // Packaged app (Linux)
359
+ appPath: '/opt/MyApp/my-app'
360
+ ```
361
+
362
+ ## Using with provision()
363
+
364
+ The `electron()` preset can also be called via the unified `provision()` function:
365
+
366
+ ```javascript
367
+ import { provision } from 'testdriverai/presets';
368
+
369
+ test('using provision', async (context) => {
370
+ const { app } = await provision('electron', {
371
+ appPath: './dist/my-app'
372
+ }, context);
373
+
374
+ // Same functionality as electron() directly
375
+ });
376
+ ```
377
+
378
+ ## Error Handling
379
+
380
+ ```javascript
381
+ test('handles missing app path', async (context) => {
382
+ try {
383
+ const { app } = await electron(context, {
384
+ appPath: '/nonexistent/path'
385
+ });
386
+ } catch (error) {
387
+ // Cleanup still happens automatically
388
+ expect(error.message).toContain('appPath');
389
+ }
390
+ });
391
+
392
+ test('handles app crashes', async (context) => {
393
+ const { app } = await electron(context, {
394
+ appPath: './dist/my-app'
395
+ });
396
+
397
+ try {
398
+ // Trigger something that might crash
399
+ await app.find('Crash button').click();
400
+ } catch (error) {
401
+ // Dashcam still saves replay of crash
402
+ console.error('App crashed:', error);
403
+ }
404
+ });
405
+ ```
406
+
407
+ ## Debugging Tips
408
+
409
+ 1. **Enable Electron DevTools** - Pass `--enable-logging` in args
410
+ 2. **Use Dashcam** - Review test recordings to see what happened
411
+ 3. **Custom User Data** - Use `--user-data-dir` for isolated testing
412
+ 4. **Remote Debugging** - Use `--remote-debugging-port=9222`
413
+
414
+ ```javascript
415
+ test('with debugging enabled', async (context) => {
416
+ const { app } = await electron(context, {
417
+ appPath: './dist/my-app',
418
+ args: [
419
+ '--enable-logging',
420
+ '--remote-debugging-port=9222',
421
+ '--user-data-dir=/tmp/test-profile'
422
+ ]
423
+ });
424
+
425
+ // Test with full debugging capabilities
426
+ });
427
+ ```
428
+
429
+ ## See Also
430
+
431
+ - [Provision API](/v7/progressive-apis/PROVISION) - Overview of all presets
432
+ - [Chrome Preset](/v7/presets/chrome) - Testing web applications
433
+ - [VS Code Preset](/v7/presets/vscode) - Testing VS Code extensions
434
+ - [Vitest Integration](/v7/guides/vitest) - Complete Vitest setup guide
435
+ - [Hooks API](/v7/progressive-apis/HOOKS) - Manual lifecycle control