testdriverai 7.3.2 → 7.3.3

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 (359) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +4 -0
  3. package/.github/workflows/acceptance-linux-scheduled.yaml +45 -0
  4. package/.github/workflows/acceptance-windows-scheduled.yaml +54 -0
  5. package/.github/workflows/acceptance.yaml +106 -0
  6. package/.github/workflows/publish.yaml +75 -0
  7. package/.github/workflows/test-init.yml +157 -0
  8. package/.github/workflows/testdriver.yml +170 -0
  9. package/.github/workflows/windows-self-hosted.yaml +82 -0
  10. package/.prettierignore +4 -0
  11. package/.prettierrc +1 -0
  12. package/CHANGELOG.md +158 -0
  13. package/SKILLs.md +17 -0
  14. package/ai/.claude-plugin/plugin.json +9 -0
  15. package/docs/GITHUB_COMMENTS.md +330 -0
  16. package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
  17. package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
  18. package/docs/TEST-GITHUB-COMMENTS.md +129 -0
  19. package/docs/_scripts/generate-skills.js +149 -0
  20. package/docs/_scripts/link-replacer.js +164 -0
  21. package/docs/_scripts/upload-docs-to-openai.js +284 -0
  22. package/docs/claude-mcp-plugin.mdx +160 -0
  23. package/docs/docs.json +394 -0
  24. package/docs/github-integration-setup.md +266 -0
  25. package/docs/guide/best-practices-polling.mdx +154 -0
  26. package/docs/images/content/account/newprojectsettings.png +0 -0
  27. package/docs/images/content/account/projectpage.png +0 -0
  28. package/docs/images/content/account/projectreplays.png +0 -0
  29. package/docs/images/content/account/team-manage.png +0 -0
  30. package/docs/images/content/account/teampage.png +0 -0
  31. package/docs/images/content/extension/cursor.svg +1 -0
  32. package/docs/images/content/extension/vscode.svg +57 -0
  33. package/docs/images/content/extension/windsurf.svg +3 -0
  34. package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
  35. package/docs/images/content/side-by-side.png +0 -0
  36. package/docs/images/content/vscode/ide-full.png +0 -0
  37. package/docs/images/content/vscode/running.png +0 -0
  38. package/docs/images/content/vscode/vscode-2-assert.png +0 -0
  39. package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
  40. package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
  41. package/docs/images/content/vscode/vscode-file-creation.png +0 -0
  42. package/docs/images/content/vscode/vscode-install.png +0 -0
  43. package/docs/images/content/vscode/vscode-overview.png +0 -0
  44. package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
  45. package/docs/images/content/vscode/vscode-stopchat.png +0 -0
  46. package/docs/images/content/vscode/vscode-stoptest.png +0 -0
  47. package/docs/images/content/vscode/vscode-tdservice.png +0 -0
  48. package/docs/images/content/vscode/vscode-test-output.png +0 -0
  49. package/docs/images/content/vscode/vscode-testhistory.png +0 -0
  50. package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
  51. package/docs/images/content/vscode/vscode-testpane.png +0 -0
  52. package/docs/images/template/dark.png +0 -0
  53. package/docs/images/template/icon.png +0 -0
  54. package/docs/images/template/light.png +0 -0
  55. package/docs/snippets/calendar-link.mdx +4 -0
  56. package/docs/snippets/gitignore-warning.mdx +7 -0
  57. package/docs/snippets/lifecycle-warning.mdx +6 -0
  58. package/docs/snippets/test-prereqs.mdx +12 -0
  59. package/docs/snippets/tests/assert-replay.mdx +7 -0
  60. package/docs/snippets/tests/assert-yaml.mdx +8 -0
  61. package/docs/snippets/tests/exec-js-replay.mdx +7 -0
  62. package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
  63. package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
  64. package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
  65. package/docs/snippets/tests/hover-image-replay.mdx +7 -0
  66. package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
  67. package/docs/snippets/tests/hover-text-replay.mdx +7 -0
  68. package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
  69. package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
  70. package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
  71. package/docs/snippets/tests/match-image-replay.mdx +7 -0
  72. package/docs/snippets/tests/match-image-yaml.mdx +17 -0
  73. package/docs/snippets/tests/press-keys-replay.mdx +7 -0
  74. package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
  75. package/docs/snippets/tests/remember-replay.mdx +7 -0
  76. package/docs/snippets/tests/remember-yaml.mdx +28 -0
  77. package/docs/snippets/tests/scroll-replay.mdx +7 -0
  78. package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
  79. package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
  80. package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
  81. package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
  82. package/docs/snippets/tests/scroll-yaml.mdx +30 -0
  83. package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
  84. package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
  85. package/docs/snippets/tests/type-replay.mdx +7 -0
  86. package/docs/snippets/tests/type-yaml.mdx +28 -0
  87. package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
  88. package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
  89. package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
  90. package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
  91. package/docs/snippets/tests/wait-replay.mdx +7 -0
  92. package/docs/snippets/tests/wait-yaml.mdx +13 -0
  93. package/docs/styles.css +65 -0
  94. package/docs/v6/account/dashboard.mdx +16 -0
  95. package/docs/v6/account/enterprise.mdx +110 -0
  96. package/docs/v6/account/pricing.mdx +33 -0
  97. package/docs/v6/account/projects.mdx +33 -0
  98. package/docs/v6/account/team.mdx +35 -0
  99. package/docs/v6/action/ami.mdx +109 -0
  100. package/docs/v6/action/performance.mdx +105 -0
  101. package/docs/v6/action/secrets.mdx +93 -0
  102. package/docs/v6/apps/chrome-extensions.mdx +48 -0
  103. package/docs/v6/apps/desktop-apps.mdx +93 -0
  104. package/docs/v6/apps/mobile-apps.mdx +26 -0
  105. package/docs/v6/apps/static-websites.mdx +54 -0
  106. package/docs/v6/apps/tauri-apps.mdx +361 -0
  107. package/docs/v6/bugs/jira.mdx +232 -0
  108. package/docs/v6/cli/overview.mdx +66 -0
  109. package/docs/v6/commands/assert.mdx +45 -0
  110. package/docs/v6/commands/exec.mdx +282 -0
  111. package/docs/v6/commands/focus-application.mdx +44 -0
  112. package/docs/v6/commands/hover-image.mdx +69 -0
  113. package/docs/v6/commands/hover-text.mdx +47 -0
  114. package/docs/v6/commands/if.mdx +53 -0
  115. package/docs/v6/commands/match-image.mdx +67 -0
  116. package/docs/v6/commands/press-keys.mdx +87 -0
  117. package/docs/v6/commands/remember.mdx +49 -0
  118. package/docs/v6/commands/run.mdx +44 -0
  119. package/docs/v6/commands/scroll-until-image.mdx +66 -0
  120. package/docs/v6/commands/scroll-until-text.mdx +60 -0
  121. package/docs/v6/commands/scroll.mdx +69 -0
  122. package/docs/v6/commands/type.mdx +45 -0
  123. package/docs/v6/commands/wait-for-image.mdx +54 -0
  124. package/docs/v6/commands/wait-for-text.mdx +48 -0
  125. package/docs/v6/commands/wait.mdx +45 -0
  126. package/docs/v6/exporting/junit.mdx +218 -0
  127. package/docs/v6/exporting/playwright.mdx +197 -0
  128. package/docs/v6/features/auto-healing.mdx +144 -0
  129. package/docs/v6/features/generation.mdx +116 -0
  130. package/docs/v6/features/parallel-testing.mdx +151 -0
  131. package/docs/v6/features/reusable-snippets.mdx +131 -0
  132. package/docs/v6/features/selectorless.mdx +80 -0
  133. package/docs/v6/features/visual-assertions.mdx +139 -0
  134. package/docs/v6/getting-started/ci.mdx +146 -0
  135. package/docs/v6/getting-started/cli.mdx +91 -0
  136. package/docs/v6/getting-started/editing.mdx +100 -0
  137. package/docs/v6/getting-started/playwright.mdx +342 -0
  138. package/docs/v6/getting-started/running.mdx +48 -0
  139. package/docs/v6/getting-started/self-hosting.mdx +408 -0
  140. package/docs/v6/getting-started/vscode.mdx +88 -0
  141. package/docs/v6/guide/assertions.mdx +189 -0
  142. package/docs/v6/guide/authentication.mdx +136 -0
  143. package/docs/v6/guide/code.mdx +65 -0
  144. package/docs/v6/guide/dashcam.mdx +118 -0
  145. package/docs/v6/guide/environment-variables.mdx +26 -0
  146. package/docs/v6/guide/lifecycle.mdx +242 -0
  147. package/docs/v6/guide/locating.mdx +141 -0
  148. package/docs/v6/guide/protips.mdx +43 -0
  149. package/docs/v6/guide/variables.mdx +143 -0
  150. package/docs/v6/guide/waiting.mdx +130 -0
  151. package/docs/v6/importing/csv.mdx +196 -0
  152. package/docs/v6/importing/gherkin.mdx +143 -0
  153. package/docs/v6/importing/jira.mdx +164 -0
  154. package/docs/v6/importing/testrail.mdx +162 -0
  155. package/docs/v6/integrations/electron.mdx +146 -0
  156. package/docs/v6/integrations/netlify.mdx +100 -0
  157. package/docs/v6/integrations/vercel.mdx +125 -0
  158. package/docs/v6/interactive/explore.mdx +99 -0
  159. package/docs/v6/interactive/run.mdx +52 -0
  160. package/docs/v6/interactive/save.mdx +63 -0
  161. package/docs/v6/overview/comparison.mdx +101 -0
  162. package/docs/v6/overview/faq.mdx +162 -0
  163. package/docs/v6/overview/performance.mdx +52 -0
  164. package/docs/v6/overview/quickstart.mdx +137 -0
  165. package/docs/v6/overview/what-is-testdriver.mdx +85 -0
  166. package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
  167. package/docs/v6/scenarios/cookie-banner.mdx +32 -0
  168. package/docs/v6/scenarios/file-upload.mdx +33 -0
  169. package/docs/v6/scenarios/form-filling.mdx +32 -0
  170. package/docs/v6/scenarios/log-in.mdx +75 -0
  171. package/docs/v6/scenarios/pdf-generation.mdx +25 -0
  172. package/docs/v6/scenarios/spell-check.mdx +22 -0
  173. package/docs/v6/security/action.mdx +84 -0
  174. package/docs/v6/security/agent.mdx +73 -0
  175. package/docs/v6/security/platform.mdx +77 -0
  176. package/docs/v6/tutorials/advanced-test.mdx +81 -0
  177. package/docs/v6/tutorials/basic-test.mdx +45 -0
  178. package/docs/v7/_drafts/agents.mdx +852 -0
  179. package/docs/v7/_drafts/architecture.mdx +399 -0
  180. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  181. package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
  182. package/docs/v7/_drafts/best-practices.mdx +486 -0
  183. package/docs/v7/_drafts/caching-ai.mdx +215 -0
  184. package/docs/v7/_drafts/caching-selectors.mdx +424 -0
  185. package/docs/v7/_drafts/caching.mdx +366 -0
  186. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
  187. package/docs/v7/_drafts/commands/assert.mdx +45 -0
  188. package/docs/v7/_drafts/commands/exec.mdx +282 -0
  189. package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
  190. package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
  191. package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
  192. package/docs/v7/_drafts/commands/if.mdx +53 -0
  193. package/docs/v7/_drafts/commands/match-image.mdx +67 -0
  194. package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
  195. package/docs/v7/_drafts/commands/remember.mdx +49 -0
  196. package/docs/v7/_drafts/commands/run.mdx +44 -0
  197. package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
  198. package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
  199. package/docs/v7/_drafts/commands/scroll.mdx +69 -0
  200. package/docs/v7/_drafts/commands/type.mdx +45 -0
  201. package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
  202. package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
  203. package/docs/v7/_drafts/commands/wait.mdx +45 -0
  204. package/docs/v7/_drafts/configuration.mdx +378 -0
  205. package/docs/v7/_drafts/contributing.mdx +174 -0
  206. package/docs/v7/_drafts/core.mdx +458 -0
  207. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  208. package/docs/v7/_drafts/debugging.mdx +349 -0
  209. package/docs/v7/_drafts/error-handling.mdx +501 -0
  210. package/docs/v7/_drafts/faq.mdx +393 -0
  211. package/docs/v7/_drafts/hooks.mdx +360 -0
  212. package/docs/v7/_drafts/init-command.mdx +95 -0
  213. package/docs/v7/_drafts/installation.mdx +420 -0
  214. package/docs/v7/_drafts/migration.mdx +562 -0
  215. package/docs/v7/_drafts/observable.mdx +604 -0
  216. package/docs/v7/_drafts/playwright.mdx +342 -0
  217. package/docs/v7/_drafts/plugin-migration.mdx +220 -0
  218. package/docs/v7/_drafts/powerful.mdx +419 -0
  219. package/docs/v7/_drafts/presets.mdx +210 -0
  220. package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
  221. package/docs/v7/_drafts/prompt-cache.mdx +200 -0
  222. package/docs/v7/_drafts/provision.mdx +390 -0
  223. package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
  224. package/docs/v7/_drafts/readme.mdx +135 -0
  225. package/docs/v7/_drafts/reports.mdx +414 -0
  226. package/docs/v7/_drafts/scalable.mdx +754 -0
  227. package/docs/v7/_drafts/screenshot.mdx +155 -0
  228. package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
  229. package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
  230. package/docs/v7/_drafts/sdk-migration.mdx +474 -0
  231. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  232. package/docs/v7/_drafts/self-hosting.mdx +369 -0
  233. package/docs/v7/_drafts/test-recording.mdx +382 -0
  234. package/docs/v7/_drafts/troubleshooting.mdx +526 -0
  235. package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
  236. package/docs/v7/_drafts/vitest.mdx +535 -0
  237. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  238. package/{ai/skills/testdriver:ai/SKILL.md → docs/v7/ai.mdx} +4 -3
  239. package/{ai/skills/testdriver:assert/SKILL.md → docs/v7/assert.mdx} +4 -3
  240. package/{ai/skills/testdriver:aws-setup/SKILL.md → docs/v7/aws-setup.mdx} +4 -3
  241. package/{ai/skills/testdriver:caching/SKILL.md → docs/v7/caching.mdx} +7 -3
  242. package/{ai/skills/testdriver:captcha/SKILL.md → docs/v7/captcha.mdx} +4 -3
  243. package/{ai/skills/testdriver:ci-cd/SKILL.md → docs/v7/ci-cd.mdx} +4 -3
  244. package/{ai/skills/testdriver:click/SKILL.md → docs/v7/click.mdx} +4 -3
  245. package/{ai/skills/testdriver:client/SKILL.md → docs/v7/client.mdx} +8 -3
  246. package/{ai/skills/testdriver:cloud/SKILL.md → docs/v7/cloud.mdx} +4 -3
  247. package/{ai/skills/testdriver:customizing-devices/SKILL.md → docs/v7/customizing-devices.mdx} +3 -3
  248. package/{ai/skills/testdriver:dashcam/SKILL.md → docs/v7/dashcam.mdx} +4 -3
  249. package/docs/v7/debugging-with-screenshots.mdx +402 -0
  250. package/{ai/skills/testdriver:device-config/SKILL.md → docs/v7/device-config.mdx} +3 -3
  251. package/{ai/skills/testdriver:double-click/SKILL.md → docs/v7/double-click.mdx} +3 -3
  252. package/{ai/skills/testdriver:elements/SKILL.md → docs/v7/elements.mdx} +4 -3
  253. package/{ai/skills/testdriver:enterprise/SKILL.md → docs/v7/enterprise.mdx} +5 -3
  254. package/docs/v7/examples.mdx +5 -0
  255. package/{ai/skills/testdriver:exec/SKILL.md → docs/v7/exec.mdx} +4 -3
  256. package/{ai/skills/testdriver:find/SKILL.md → docs/v7/find.mdx} +4 -3
  257. package/{ai/skills/testdriver:focus-application/SKILL.md → docs/v7/focus-application.mdx} +4 -3
  258. package/{ai/skills/testdriver:generating-tests/SKILL.md → docs/v7/generating-tests.mdx} +3 -3
  259. package/{ai/skills/testdriver:hover/SKILL.md → docs/v7/hover.mdx} +4 -3
  260. package/{ai/skills/testdriver:locating-elements/SKILL.md → docs/v7/locating-elements.mdx} +3 -3
  261. package/{ai/skills/testdriver:making-assertions/SKILL.md → docs/v7/making-assertions.mdx} +3 -3
  262. package/{ai/skills/testdriver:mouse-down/SKILL.md → docs/v7/mouse-down.mdx} +3 -3
  263. package/{ai/skills/testdriver:mouse-up/SKILL.md → docs/v7/mouse-up.mdx} +3 -3
  264. package/docs/v7/ocr.mdx +236 -0
  265. package/{ai/skills/testdriver:performing-actions/SKILL.md → docs/v7/performing-actions.mdx} +3 -3
  266. package/{ai/skills/testdriver:press-keys/SKILL.md → docs/v7/press-keys.mdx} +4 -3
  267. package/{ai/skills/testdriver:quickstart/SKILL.md → docs/v7/quickstart.mdx} +6 -20
  268. package/{ai/skills/testdriver:reusable-code/SKILL.md → docs/v7/reusable-code.mdx} +3 -3
  269. package/{ai/skills/testdriver:right-click/SKILL.md → docs/v7/right-click.mdx} +3 -3
  270. package/{ai/skills/testdriver:running-tests/SKILL.md → docs/v7/running-tests.mdx} +7 -3
  271. package/{ai/skills/testdriver:screenshot/SKILL.md → docs/v7/screenshot.mdx} +88 -6
  272. package/{ai/skills/testdriver:scroll/SKILL.md → docs/v7/scroll.mdx} +40 -3
  273. package/{ai/skills/testdriver:secrets/SKILL.md → docs/v7/secrets.mdx} +3 -3
  274. package/{ai/skills/testdriver:self-hosted/SKILL.md → docs/v7/self-hosted.mdx} +4 -3
  275. package/{ai/skills/testdriver:type/SKILL.md → docs/v7/type.mdx} +4 -3
  276. package/{ai/skills/testdriver:variables/SKILL.md → docs/v7/variables.mdx} +3 -3
  277. package/{ai/skills/testdriver:waiting-for-elements/SKILL.md → docs/v7/waiting-for-elements.mdx} +3 -3
  278. package/{ai/skills/testdriver:what-is-testdriver/SKILL.md → docs/v7/what-is-testdriver.mdx} +3 -3
  279. package/eslint.config.js +67 -0
  280. package/examples/ai.test.mjs +30 -0
  281. package/examples/assert.test.mjs +47 -0
  282. package/examples/captcha-api.test.mjs +50 -0
  283. package/examples/chrome-extension.test.mjs +94 -0
  284. package/examples/drag-and-drop.test.mjs +58 -0
  285. package/examples/element-not-found.test.mjs +26 -0
  286. package/examples/exec-output.test.mjs +59 -0
  287. package/examples/exec-pwsh.test.mjs +57 -0
  288. package/examples/focus-window.test.mjs +36 -0
  289. package/examples/formatted-logging.test.mjs +26 -0
  290. package/examples/hover-image.test.mjs +52 -0
  291. package/examples/hover-text-with-description.test.mjs +56 -0
  292. package/examples/hover-text.test.mjs +27 -0
  293. package/examples/installer.test.mjs +49 -0
  294. package/examples/launch-vscode-linux.test.mjs +54 -0
  295. package/examples/match-image.test.mjs +54 -0
  296. package/examples/no-provision.test.mjs +23 -0
  297. package/examples/press-keys.test.mjs +50 -0
  298. package/examples/prompt.test.mjs +33 -0
  299. package/examples/scroll-keyboard.test.mjs +37 -0
  300. package/examples/scroll-until-image.test.mjs +39 -0
  301. package/examples/scroll-until-text.test.mjs +67 -0
  302. package/examples/scroll.test.mjs +41 -0
  303. package/examples/type.test.mjs +45 -0
  304. package/examples/windows-installer.test.mjs +53 -0
  305. package/jsconfig.json +26 -0
  306. package/manual/test-init-command.js +223 -0
  307. package/mcp-server/README.md +312 -0
  308. package/mcp-server/mcp-app.html +28 -0
  309. package/mcp-server/mcp-config.example.json +19 -0
  310. package/mcp-server/package-lock.json +4018 -0
  311. package/mcp-server/package.json +29 -0
  312. package/mcp-server/src/codegen.ts +189 -0
  313. package/mcp-server/src/mcp-app.css +360 -0
  314. package/mcp-server/src/mcp-app.ts +547 -0
  315. package/mcp-server/src/provision-types.ts +209 -0
  316. package/mcp-server/src/server.ts +2313 -0
  317. package/mcp-server/src/session.ts +194 -0
  318. package/mcp-server/tsconfig.json +16 -0
  319. package/mcp-server/vite.config.ts +23 -0
  320. package/package.json +2 -17
  321. package/scripts/generate-skills.js +94 -0
  322. package/setup/aws/cloudformation.yaml +470 -0
  323. package/setup/aws/spawn-runner.sh +190 -0
  324. package/test/api-resilience.test.mjs +0 -0
  325. package/test/captcha-solver.test.mjs +152 -0
  326. package/test/chrome-remote-debugging.test.mjs +66 -0
  327. package/test/duckduckgo/experiment.test.mjs +28 -0
  328. package/test/duckduckgo/setup.test.mjs +29 -0
  329. package/test/manual/debug-locate-response.js +82 -0
  330. package/test/manual/reconnect-provision.test.mjs +49 -0
  331. package/test/manual/test-console-logs.test.mjs +42 -0
  332. package/test/manual/test-find-api.js +73 -0
  333. package/test/manual/test-init.sh +54 -0
  334. package/test/manual/test-prompt-cache.js +97 -0
  335. package/test/manual/test-provision-auth.mjs +22 -0
  336. package/test/manual/test-sandbox-render.js +29 -0
  337. package/test/manual/test-sdk-methods.js +15 -0
  338. package/test/manual/test-sdk-refactor.js +53 -0
  339. package/test/manual/test-stack-trace.mjs +57 -0
  340. package/test/manual/verify-element-api.js +89 -0
  341. package/test/manual/verify-types.js +0 -0
  342. package/test/manual-unawaited-promise.test.mjs +31 -0
  343. package/test-ide-preview.mjs +17 -0
  344. package/tests/airbnb-booking.test.mjs +39 -0
  345. package/tests/airbnb-search.test.mjs +43 -0
  346. package/tests/example.test.js +33 -0
  347. package/tests/login.js +28 -0
  348. package/vitest.config.mjs +24 -0
  349. package/vscode-extension/.vscodeignore +12 -0
  350. package/vscode-extension/README.md +94 -0
  351. package/vscode-extension/media/icon.png +0 -0
  352. package/vscode-extension/package-lock.json +4126 -0
  353. package/vscode-extension/package.json +86 -0
  354. package/vscode-extension/src/extension.ts +829 -0
  355. package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
  356. package/vscode-extension/tsconfig.json +16 -0
  357. package/ai/skills/testdriver:examples/SKILL.md +0 -7
  358. package/ai/skills/testdriver:mcp-workflow/SKILL.md +0 -410
  359. package/ai/skills/testdriver:testdriver/SKILL.md +0 -523
@@ -0,0 +1,754 @@
1
+ ---
2
+ title: "Scalability"
3
+ description: "From small projects to enterprise test suites with thousands of tests"
4
+ icon: "arrow-up-right-dots"
5
+ ---
6
+
7
+ TestDriver scales effortlessly from your first test to enterprise suites with thousands of tests running in parallel across multiple platforms.
8
+
9
+ ## Code Snippets for Reusability
10
+
11
+ Scale your test suite with reusable code snippets to reduce duplication and maintain consistency:
12
+
13
+ <Tabs>
14
+ <Tab title="Helper Functions">
15
+ ```javascript test/helpers/auth.js
16
+ // Reusable authentication helpers
17
+ export async function login(testdriver, { email, password }) {
18
+ await testdriver.find('email input').type(email);
19
+ await testdriver.find('password input').type(password);
20
+ await testdriver.find('login button').click();
21
+ await testdriver.assert('logged in successfully');
22
+ }
23
+
24
+ export async function logout(testdriver) {
25
+ await testdriver.find('user menu').click();
26
+ await testdriver.find('logout button').click();
27
+ }
28
+ ```
29
+
30
+ ```javascript test/checkout.test.js
31
+ import { login } from './helpers/auth.js';
32
+
33
+ test('checkout flow', async (context) => {
34
+ const { testdriver } = await chrome(context, { url });
35
+ await login(testdriver, {
36
+ email: 'user@example.com',
37
+ password: 'password123'
38
+ });
39
+ // Continue with checkout test
40
+ });
41
+ ```
42
+ </Tab>
43
+
44
+ <Tab title="Page Objects">
45
+ ```javascript test/pages/LoginPage.js
46
+ export class LoginPage {
47
+ constructor(testdriver) {
48
+ this.testdriver = testdriver;
49
+ }
50
+
51
+ async login(email, password) {
52
+ await this.testdriver.find('email input').type(email);
53
+ await this.testdriver.find('password input').type(password);
54
+ await this.testdriver.find('submit button').click();
55
+ }
56
+
57
+ async assertError(message) {
58
+ await this.testdriver.assert(`error message shows "${message}"`);
59
+ }
60
+ }
61
+ ```
62
+
63
+ ```javascript test/auth.test.js
64
+ import { LoginPage } from './pages/LoginPage.js';
65
+
66
+ test('invalid login shows error', async (context) => {
67
+ const { testdriver } = await chrome(context, { url });
68
+ const loginPage = new LoginPage(testdriver);
69
+
70
+ await loginPage.login('invalid@test.com', 'wrong');
71
+ await loginPage.assertError('Invalid credentials');
72
+ });
73
+ ```
74
+ </Tab>
75
+
76
+ <Tab title="Custom Commands">
77
+ ```javascript test/commands/navigation.js
78
+ export function addNavigationCommands(testdriver) {
79
+ testdriver.navigateTo = async (section) => {
80
+ await testdriver.find(`${section} nav link`).click();
81
+ await testdriver.assert(`${section} page is loaded`);
82
+ };
83
+
84
+ testdriver.searchFor = async (query) => {
85
+ await testdriver.find('search input').type(query);
86
+ await testdriver.find('search button').click();
87
+ await testdriver.assert('search results are displayed');
88
+ };
89
+
90
+ return testdriver;
91
+ }
92
+ ```
93
+
94
+ ```javascript test/search.test.js
95
+ import { addNavigationCommands } from './commands/navigation.js';
96
+
97
+ test('search functionality', async (context) => {
98
+ let { testdriver } = await chrome(context, { url });
99
+ testdriver = addNavigationCommands(testdriver);
100
+
101
+ await testdriver.searchFor('laptop');
102
+ // Custom command used
103
+ });
104
+ ```
105
+ </Tab>
106
+ </Tabs>
107
+
108
+ <Check>
109
+ Reusable snippets reduce test maintenance time by up to 70% in large test suites.
110
+ </Check>
111
+
112
+ ## Dynamic Variables for Data-Driven Tests
113
+
114
+ Scale your testing with dynamic data to cover more scenarios:
115
+
116
+ <Tabs>
117
+ <Tab title="Environment Variables">
118
+ ```javascript
119
+ import { test } from 'vitest';
120
+ import { chrome } from 'testdriverai/presets';
121
+
122
+ test('multi-environment testing', async (context) => {
123
+ const env = process.env.TEST_ENV || 'staging';
124
+ const urls = {
125
+ dev: 'https://dev.myapp.com',
126
+ staging: 'https://staging.myapp.com',
127
+ production: 'https://myapp.com'
128
+ };
129
+
130
+ const { testdriver } = await chrome(context, {
131
+ url: urls[env]
132
+ });
133
+
134
+ await testdriver.assert('app is running');
135
+ });
136
+ ```
137
+
138
+ ```bash
139
+ # Run against different environments
140
+ TEST_ENV=dev vitest run
141
+ TEST_ENV=staging vitest run
142
+ TEST_ENV=production vitest run
143
+ ```
144
+ </Tab>
145
+
146
+ <Tab title="Test Fixtures">
147
+ ```javascript test/fixtures/users.js
148
+ export const testUsers = [
149
+ { email: 'admin@test.com', role: 'admin' },
150
+ { email: 'user@test.com', role: 'user' },
151
+ { email: 'guest@test.com', role: 'guest' }
152
+ ];
153
+
154
+ export const products = [
155
+ { name: 'Laptop', price: 999 },
156
+ { name: 'Mouse', price: 29 },
157
+ { name: 'Keyboard', price: 89 }
158
+ ];
159
+ ```
160
+
161
+ ```javascript test/permissions.test.js
162
+ import { test } from 'vitest';
163
+ import { chrome } from 'testdriverai/presets';
164
+ import { testUsers } from './fixtures/users.js';
165
+
166
+ test.each(testUsers)('$role can access dashboard', async ({ email, role }, context) => {
167
+ const { testdriver } = await chrome(context, { url });
168
+
169
+ await testdriver.find('email input').type(email);
170
+ await testdriver.find('password input').type('password123');
171
+ await testdriver.find('login button').click();
172
+
173
+ if (role === 'admin') {
174
+ await testdriver.assert('admin panel is visible');
175
+ } else {
176
+ await testdriver.assert('user dashboard is visible');
177
+ }
178
+ });
179
+ ```
180
+ </Tab>
181
+
182
+ <Tab title="Dynamic Data Generation">
183
+ ```javascript
184
+ import { test } from 'vitest';
185
+ import { chrome } from 'testdriverai/presets';
186
+ import { faker } from '@faker-js/faker';
187
+
188
+ test('user registration with dynamic data', async (context) => {
189
+ const { testdriver } = await chrome(context, { url });
190
+
191
+ // Generate unique test data for each run
192
+ const userData = {
193
+ firstName: faker.person.firstName(),
194
+ lastName: faker.person.lastName(),
195
+ email: faker.internet.email(),
196
+ password: faker.internet.password({ length: 12 })
197
+ };
198
+
199
+ await testdriver.find('first name input').type(userData.firstName);
200
+ await testdriver.find('last name input').type(userData.lastName);
201
+ await testdriver.find('email input').type(userData.email);
202
+ await testdriver.find('password input').type(userData.password);
203
+ await testdriver.find('register button').click();
204
+
205
+ await testdriver.assert('registration successful');
206
+ console.log('Registered user:', userData.email);
207
+ });
208
+ ```
209
+
210
+ ```bash
211
+ npm install --save-dev @faker-js/faker
212
+ ```
213
+ </Tab>
214
+ </Tabs>
215
+
216
+ <Card title="Dynamic Variables Best Practices" icon="lightbulb">
217
+ - **Environment configs:** Store URLs, credentials, and settings in env vars
218
+ - **Test fixtures:** Maintain reusable test data in separate files
219
+ - **Data generators:** Use libraries like Faker for unique test data
220
+ - **Parameterization:** Test multiple scenarios with `test.each()`
221
+ - **CI/CD integration:** Pass dynamic values via environment variables
222
+ </Card>
223
+
224
+ ## Works with Vitest
225
+
226
+ Full integration with Vitest's powerful features:
227
+
228
+ ```javascript vitest.config.mjs
229
+ import { defineConfig } from 'vitest/config';
230
+
231
+ export default defineConfig({
232
+ test: {
233
+ testTimeout: 120000,
234
+ hookTimeout: 120000,
235
+ maxConcurrency: 10, // Run 10 tests in parallel
236
+ minThreads: 2,
237
+ maxThreads: 10,
238
+ },
239
+ });
240
+ ```
241
+
242
+ <CardGroup cols={2}>
243
+ <Card title="Parallel Execution" icon="layer-group">
244
+ Run multiple tests simultaneously for maximum throughput:
245
+
246
+ ```bash
247
+ # Run all tests in parallel
248
+ vitest run
249
+
250
+ # Control concurrency
251
+ vitest run --max-concurrency=5
252
+ ```
253
+ </Card>
254
+
255
+ <Card title="Watch Mode" icon="eye">
256
+ Instant feedback during development:
257
+
258
+ ```bash
259
+ # Run in watch mode
260
+ vitest
261
+
262
+ # Only run changed tests
263
+ vitest --changed
264
+ ```
265
+ </Card>
266
+ </CardGroup>
267
+
268
+ [See complete Vitest integration guide](/v7/guides/vitest)
269
+
270
+ ## CI/CD Compatible
271
+
272
+ TestDriver integrates seamlessly with all major CI/CD platforms:
273
+
274
+ <Tabs>
275
+ <Tab title="GitHub Actions">
276
+ ```yaml .github/workflows/test.yml
277
+ name: E2E Tests
278
+
279
+ on: [push, pull_request]
280
+
281
+ jobs:
282
+ test:
283
+ runs-on: ubuntu-latest
284
+ steps:
285
+ - uses: actions/checkout@v3
286
+ - uses: actions/setup-node@v3
287
+ - run: npm install
288
+ - run: vitest run
289
+ env:
290
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
291
+ ```
292
+
293
+ [GitHub Actions guide](/v7/guides/ci-cd/github-actions)
294
+ </Tab>
295
+
296
+ <Tab title="GitLab CI">
297
+ ```yaml .gitlab-ci.yml
298
+ test:
299
+ image: node:20
300
+ script:
301
+ - npm install
302
+ - vitest run
303
+ variables:
304
+ TD_API_KEY: $TD_API_KEY
305
+ ```
306
+
307
+ [GitLab CI guide](/v7/guides/ci-cd/gitlab)
308
+ </Tab>
309
+
310
+ <Tab title="CircleCI">
311
+ ```yaml .circleci/config.yml
312
+ version: 2.1
313
+ jobs:
314
+ test:
315
+ docker:
316
+ - image: cimg/node:20.0
317
+ steps:
318
+ - checkout
319
+ - run: npm install
320
+ - run: vitest run
321
+ ```
322
+
323
+ [CircleCI guide](/v7/guides/ci-cd/circleci)
324
+ </Tab>
325
+
326
+ <Tab title="Jenkins">
327
+ ```groovy Jenkinsfile
328
+ pipeline {
329
+ agent any
330
+ stages {
331
+ stage('Test') {
332
+ steps {
333
+ sh 'npm install'
334
+ sh 'vitest run'
335
+ }
336
+ }
337
+ }
338
+ }
339
+ ```
340
+
341
+ [Jenkins guide](/v7/guides/ci-cd/jenkins)
342
+ </Tab>
343
+ </Tabs>
344
+
345
+ ## JUnit Reports
346
+
347
+ Generate JUnit XML reports for test result aggregation and CI/CD integration.
348
+
349
+ ### Basic Setup
350
+
351
+ Configure Vitest to output JUnit reports by adding a reporter to your config:
352
+
353
+ ```javascript vitest.config.mjs
354
+ import { defineConfig } from 'vitest/config';
355
+
356
+ export default defineConfig({
357
+ test: {
358
+ testTimeout: 120000,
359
+ hookTimeout: 120000,
360
+ reporters: ['default', 'junit'],
361
+ outputFile: {
362
+ junit: 'test-report.junit.xml'
363
+ }
364
+ },
365
+ });
366
+ ```
367
+
368
+ Or run from the command line:
369
+
370
+ ```bash
371
+ vitest run --reporter=junit --outputFile=test-results.xml
372
+ ```
373
+
374
+ This generates a standard JUnit XML report:
375
+
376
+ ```xml test-results.xml
377
+ <?xml version="1.0" encoding="UTF-8"?>
378
+ <testsuites name="vitest tests" tests="12" failures="0" errors="0" time="125.3">
379
+ <testsuite name="login.test.js" tests="3" failures="0" time="31.2">
380
+ <testcase name="user can login" time="12.4" />
381
+ <testcase name="invalid credentials show error" time="9.8" />
382
+ <testcase name="password reset works" time="9.0" />
383
+ </testsuite>
384
+ </testsuites>
385
+ ```
386
+
387
+ ### GitHub Actions PR Comments
388
+
389
+ Use JUnit reports to automatically post test results as comments on pull requests. This provides immediate visibility into test failures without leaving GitHub.
390
+
391
+ ```yaml .github/workflows/test.yml
392
+ name: E2E Tests
393
+
394
+ on:
395
+ pull_request:
396
+ branches: [main]
397
+
398
+ permissions:
399
+ contents: read
400
+ pull-requests: write
401
+ checks: write
402
+
403
+ jobs:
404
+ test:
405
+ runs-on: ubuntu-latest
406
+
407
+ steps:
408
+ - uses: actions/checkout@v4
409
+
410
+ - name: Setup Node.js
411
+ uses: actions/setup-node@v4
412
+ with:
413
+ node-version: '20'
414
+ cache: 'npm'
415
+
416
+ - name: Install dependencies
417
+ run: npm ci
418
+
419
+ - name: Run tests
420
+ run: vitest run
421
+ env:
422
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
423
+
424
+ - name: Publish Test Results
425
+ uses: EnricoMi/publish-unit-test-result-action@v2
426
+ if: always()
427
+ with:
428
+ files: test-report.junit.xml
429
+ comment_mode: always
430
+ check_name: Test Results
431
+ ```
432
+
433
+ <Note>
434
+ The `if: always()` ensures test results are published even when tests fail, so you always see what went wrong.
435
+ </Note>
436
+
437
+ The [publish-unit-test-result-action](https://github.com/EnricoMi/publish-unit-test-result-action) creates:
438
+
439
+ - **PR comments** with a summary table of passed/failed tests
440
+ - **Check runs** visible in the GitHub PR checks tab
441
+ - **Annotations** highlighting failed tests in the diff view
442
+
443
+ ### Multi-Platform Testing with JUnit
444
+
445
+ When testing across multiple platforms, use separate check names to distinguish results:
446
+
447
+ ```yaml .github/workflows/test.yml
448
+ jobs:
449
+ test-linux:
450
+ runs-on: ubuntu-latest
451
+ steps:
452
+ # ... setup steps ...
453
+
454
+ - name: Run Linux tests
455
+ run: vitest run
456
+ env:
457
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
458
+ TD_OS: linux
459
+
460
+ - name: Publish Test Results
461
+ uses: EnricoMi/publish-unit-test-result-action@v2
462
+ if: always()
463
+ with:
464
+ files: test-report.junit.xml
465
+ comment_mode: always
466
+ check_name: Test Results (Linux)
467
+
468
+ test-windows:
469
+ runs-on: ubuntu-latest
470
+ steps:
471
+ # ... setup steps ...
472
+
473
+ - name: Run Windows tests
474
+ run: vitest run
475
+ env:
476
+ TD_API_KEY: ${{ secrets.TD_API_KEY }}
477
+ TD_OS: windows
478
+
479
+ - name: Publish Test Results
480
+ uses: EnricoMi/publish-unit-test-result-action@v2
481
+ if: always()
482
+ with:
483
+ files: test-report.junit.xml
484
+ comment_mode: always
485
+ check_name: Test Results (Windows)
486
+ ```
487
+
488
+ <Check>
489
+ JUnit reports integrate with Jenkins, Azure DevOps, TeamCity, GitLab, and other CI platforms for test result visualization.
490
+ </Check>
491
+
492
+ ## Familiar Test Syntax
493
+
494
+ TestDriver works with the test frameworks you already know:
495
+
496
+ <Tabs>
497
+ <Tab title="Vitest">
498
+ ```javascript
499
+ import { test, describe, beforeAll, afterAll } from 'vitest';
500
+ import { chrome } from 'testdriverai/presets';
501
+
502
+ describe('My Feature', () => {
503
+ test('should work', async (context) => {
504
+ const { testdriver } = await chrome(context, { url });
505
+ await testdriver.find('button').click();
506
+ });
507
+ });
508
+ ```
509
+ </Tab>
510
+
511
+ <Tab title="Jest">
512
+ ```javascript
513
+ import { chrome } from 'testdriverai/presets';
514
+
515
+ describe('My Feature', () => {
516
+ test('should work', async () => {
517
+ const { testdriver } = await chrome({ url });
518
+ await testdriver.find('button').click();
519
+ });
520
+ });
521
+ ```
522
+ </Tab>
523
+
524
+ <Tab title="Mocha">
525
+ ```javascript
526
+ import { chrome } from 'testdriverai/presets';
527
+
528
+ describe('My Feature', function() {
529
+ it('should work', async function() {
530
+ const { testdriver } = await chrome(this, { url });
531
+ await testdriver.find('button').click();
532
+ });
533
+ });
534
+ ```
535
+ </Tab>
536
+ </Tabs>
537
+
538
+ ## Existing Systems Integration
539
+
540
+ Drop TestDriver into your current workflow without disruption:
541
+
542
+ ```javascript
543
+ import { test, expect } from 'vitest';
544
+ import { chrome } from 'testdriverai/presets';
545
+
546
+ test('integrates with existing assertions', async (context) => {
547
+ const { testdriver } = await chrome(context, { url });
548
+
549
+ // Use TestDriver's AI assertions
550
+ await testdriver.assert('welcome message is visible');
551
+
552
+ // Or use traditional assertions
553
+ const button = await testdriver.find('submit button');
554
+ expect(button.coordinates).toBeDefined();
555
+ expect(button.text).toContain('Submit');
556
+
557
+ // Mix and match as needed
558
+ const element = await testdriver.exec('js', 'document.title');
559
+ expect(element).toBe('My App');
560
+ });
561
+ ```
562
+
563
+ ## Scale to Thousands of Tests
564
+
565
+ TestDriver handles large test suites efficiently:
566
+
567
+ <Card title="Enterprise Test Suite Example" icon="building">
568
+ ```
569
+ Project: E-commerce Platform
570
+ Total tests: 3,847
571
+ Test files: 412
572
+ Parallel runners: 20
573
+ Total duration: 18 minutes
574
+
575
+ Breakdown:
576
+ - Unit tests: 2,134 (3 min)
577
+ - Integration: 891 (7 min)
578
+ - E2E (TestDriver): 822 (18 min)
579
+
580
+ Cost per run: $4.32
581
+ Runs per day: 50
582
+ Monthly cost: $6,480
583
+ ```
584
+
585
+ With caching enabled:
586
+ ```
587
+ E2E duration: 8 minutes (2.25x faster)
588
+ Cost per run: $1.89 (56% reduction)
589
+ Monthly cost: $2,835 (saves $3,645/month)
590
+ ```
591
+ </Card>
592
+
593
+ ## Test Sharding
594
+
595
+ Distribute tests across multiple machines:
596
+
597
+ <Tabs>
598
+ <Tab title="GitHub Actions Matrix">
599
+ ```yaml .github/workflows/test.yml
600
+ strategy:
601
+ matrix:
602
+ shard: [1, 2, 3, 4, 5]
603
+ steps:
604
+ - run: vitest run --shard=${{ matrix.shard }}/5
605
+ ```
606
+
607
+ Runs 5 parallel jobs, each handling 1/5 of tests.
608
+ </Tab>
609
+
610
+ <Tab title="GitLab CI Parallel">
611
+ ```yaml .gitlab-ci.yml
612
+ test:
613
+ parallel: 5
614
+ script:
615
+ - vitest run --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
616
+ ```
617
+ </Tab>
618
+
619
+ <Tab title="Manual Sharding">
620
+ ```bash
621
+ # Machine 1
622
+ vitest run --shard=1/4
623
+
624
+ # Machine 2
625
+ vitest run --shard=2/4
626
+
627
+ # Machine 3
628
+ vitest run --shard=3/4
629
+
630
+ # Machine 4
631
+ vitest run --shard=4/4
632
+ ```
633
+ </Tab>
634
+ </Tabs>
635
+
636
+ ## Team Collaboration
637
+
638
+ Built for teams with multiple developers:
639
+
640
+ <AccordionGroup>
641
+ <Accordion title="Shared Test Cache">
642
+ Tests automatically benefit from each other's cache entries:
643
+
644
+ ```javascript
645
+ // Developer A runs test
646
+ await testdriver.find('submit button').click();
647
+ // Creates cache entry
648
+
649
+ // Developer B runs test later
650
+ await testdriver.find('submit button').click();
651
+ // Uses Developer A's cache ⚡
652
+ ```
653
+
654
+ Per-team cache sharing accelerates everyone's tests.
655
+ </Accordion>
656
+
657
+ <Accordion title="Dashcam Replays">
658
+ Share test replays with your team:
659
+
660
+ ```javascript
661
+ test('shareable replay', async (context) => {
662
+ const { testdriver, dashcam } = await chrome(context, { url });
663
+
664
+ await testdriver.find('button').click();
665
+
666
+ // Share replay URL with team
667
+ console.log('Replay:', dashcam.url);
668
+ // https://console.testdriver.ai/dashcam/abc123
669
+ });
670
+ ```
671
+
672
+ View replays at [app.testdriver.ai](https://app.testdriver.ai)
673
+ </Accordion>
674
+
675
+ <Accordion title="Sandbox Management">
676
+ Long-running sandboxes for team debugging:
677
+
678
+ ```bash
679
+ # Spawn a sandbox for the team
680
+ testdriver sandbox spawn --timeout 7200000
681
+
682
+ # Team members can connect
683
+ export TESTDRIVER_SANDBOX_ID=i-0abc123def
684
+ vitest run
685
+ ```
686
+
687
+ [Learn about sandbox management](/v7/guides/sandbox-management)
688
+ </Accordion>
689
+ </AccordionGroup>
690
+
691
+ ## Cost Optimization
692
+
693
+ TestDriver scales cost-effectively:
694
+
695
+ <Card title="Pricing Model" icon="dollar-sign">
696
+ - **API calls:** Pay per AI vision analysis
697
+ - **Sandbox time:** Pay per minute of VM usage
698
+ - **Caching:** Reduces both costs dramatically
699
+ - **Shared cache:** Team benefits from collective cache
700
+
701
+ **Example costs:**
702
+ - Single test run: $0.04 - $0.12
703
+ - 100-test suite: $4 - $12 (first run)
704
+ - Cached suite: $0.50 - $2 (90%+ savings)
705
+ </Card>
706
+
707
+ ## Enterprise Scale
708
+
709
+ TestDriver supports the largest testing operations:
710
+
711
+ - **Unlimited tests** in enterprise plans
712
+ - **Unlimited sandbox hours** for large suites
713
+ - **Unlimited team members** for collaboration
714
+ - **Priority infrastructure** for faster execution
715
+ - **Dedicated support** for optimization help
716
+ - **Custom SLA** for guaranteed uptime
717
+
718
+ [Contact sales](https://testdriver.ai/enterprise) for enterprise pricing.
719
+
720
+ ## Learn More
721
+
722
+ <CardGroup cols={2}>
723
+ <Card
724
+ title="Vitest Integration"
725
+ icon="flask-vial"
726
+ href="/v7/guides/vitest"
727
+ >
728
+ Complete Vitest guide
729
+ </Card>
730
+
731
+ <Card
732
+ title="CI/CD Setup"
733
+ icon="arrows-spin"
734
+ href="/v7/guides/ci-cd/overview"
735
+ >
736
+ CI/CD integration guides
737
+ </Card>
738
+
739
+ <Card
740
+ title="Performance Optimization"
741
+ icon="gauge-high"
742
+ href="/v7/guides/performance"
743
+ >
744
+ Optimize test performance
745
+ </Card>
746
+
747
+ <Card
748
+ title="Self-Hosting"
749
+ icon="server"
750
+ href="/v7/guides/self-hosting"
751
+ >
752
+ Run on your infrastructure
753
+ </Card>
754
+ </CardGroup>