testdriverai 7.2.64 → 7.2.65

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 (360) hide show
  1. package/agent/index.js +4 -3
  2. package/agent/interface.js +11 -251
  3. package/agent/lib/debugger-server.js +2 -1
  4. package/agent/lib/logger.js +56 -0
  5. package/agent/lib/sandbox.js +6 -7
  6. package/ai/agents/test-writer.md +457 -0
  7. package/{docs/v7/ai.mdx → ai/skills/testdriver:ai/SKILL.md} +3 -5
  8. package/{docs/v7/assert.mdx → ai/skills/testdriver:assert/SKILL.md} +3 -4
  9. package/{docs/v7/aws-setup.mdx → ai/skills/testdriver:aws-setup/SKILL.md} +3 -4
  10. package/{docs/v7/caching.mdx → ai/skills/testdriver:caching/SKILL.md} +3 -7
  11. package/{docs/v7/captcha.mdx → ai/skills/testdriver:captcha/SKILL.md} +4 -5
  12. package/{docs/v7/ci-cd.mdx → ai/skills/testdriver:ci-cd/SKILL.md} +3 -4
  13. package/{docs/v7/click.mdx → ai/skills/testdriver:click/SKILL.md} +3 -4
  14. package/{docs/v7/client.mdx → ai/skills/testdriver:client/SKILL.md} +11 -5
  15. package/{docs/v7/cloud.mdx → ai/skills/testdriver:cloud/SKILL.md} +3 -4
  16. package/{docs/v7/customizing-devices.mdx → ai/skills/testdriver:customizing-devices/SKILL.md} +36 -26
  17. package/{docs/v7/dashcam.mdx → ai/skills/testdriver:dashcam/SKILL.md} +3 -4
  18. package/{docs/v7/device-config.mdx → ai/skills/testdriver:device-config/SKILL.md} +3 -3
  19. package/{docs/v7/double-click.mdx → ai/skills/testdriver:double-click/SKILL.md} +3 -3
  20. package/{docs/v7/elements.mdx → ai/skills/testdriver:elements/SKILL.md} +3 -4
  21. package/{docs/v7/enterprise.mdx → ai/skills/testdriver:enterprise/SKILL.md} +3 -5
  22. package/ai/skills/testdriver:examples/SKILL.md +7 -0
  23. package/{docs/v7/exec.mdx → ai/skills/testdriver:exec/SKILL.md} +3 -4
  24. package/{docs/v7/find.mdx → ai/skills/testdriver:find/SKILL.md} +81 -4
  25. package/{docs/v7/focus-application.mdx → ai/skills/testdriver:focus-application/SKILL.md} +3 -4
  26. package/{docs/v7/generating-tests.mdx → ai/skills/testdriver:generating-tests/SKILL.md} +3 -3
  27. package/{docs/v7/hover.mdx → ai/skills/testdriver:hover/SKILL.md} +3 -4
  28. package/{docs/v7/locating-elements.mdx → ai/skills/testdriver:locating-elements/SKILL.md} +3 -3
  29. package/{docs/v7/making-assertions.mdx → ai/skills/testdriver:making-assertions/SKILL.md} +3 -3
  30. package/ai/skills/testdriver:mcp-workflow/SKILL.md +410 -0
  31. package/{docs/v7/mouse-down.mdx → ai/skills/testdriver:mouse-down/SKILL.md} +3 -3
  32. package/{docs/v7/mouse-up.mdx → ai/skills/testdriver:mouse-up/SKILL.md} +3 -3
  33. package/{docs/v7/performing-actions.mdx → ai/skills/testdriver:performing-actions/SKILL.md} +3 -3
  34. package/{docs/v7/press-keys.mdx → ai/skills/testdriver:press-keys/SKILL.md} +3 -4
  35. package/{docs/v7/quickstart.mdx → ai/skills/testdriver:quickstart/SKILL.md} +3 -4
  36. package/{docs/v7/reusable-code.mdx → ai/skills/testdriver:reusable-code/SKILL.md} +3 -3
  37. package/{docs/v7/right-click.mdx → ai/skills/testdriver:right-click/SKILL.md} +3 -3
  38. package/{docs/v7/running-tests.mdx → ai/skills/testdriver:running-tests/SKILL.md} +3 -3
  39. package/{docs/v7/screenshot.mdx → ai/skills/testdriver:screenshot/SKILL.md} +3 -4
  40. package/{docs/v7/scroll.mdx → ai/skills/testdriver:scroll/SKILL.md} +3 -4
  41. package/{docs/v7/secrets.mdx → ai/skills/testdriver:secrets/SKILL.md} +3 -3
  42. package/{docs/v7/self-hosted.mdx → ai/skills/testdriver:self-hosted/SKILL.md} +3 -4
  43. package/ai/skills/testdriver:testdriver/SKILL.md +31 -0
  44. package/{docs/v7/type.mdx → ai/skills/testdriver:type/SKILL.md} +3 -4
  45. package/{docs/v7/variables.mdx → ai/skills/testdriver:variables/SKILL.md} +3 -3
  46. package/{docs/v7/waiting-for-elements.mdx → ai/skills/testdriver:waiting-for-elements/SKILL.md} +3 -3
  47. package/{docs/v7/what-is-testdriver.mdx → ai/skills/testdriver:what-is-testdriver/SKILL.md} +3 -3
  48. package/interfaces/cli/commands/init.js +278 -1
  49. package/interfaces/cli/commands/setup.js +382 -0
  50. package/interfaces/vitest-plugin.mjs +190 -122
  51. package/lib/sentry.js +4 -3
  52. package/lib/vitest/hooks.mjs +70 -16
  53. package/package.json +29 -9
  54. package/sdk.d.ts +29 -2
  55. package/sdk.js +1 -0
  56. package/.env.example +0 -4
  57. package/.github/workflows/acceptance-linux-scheduled.yaml +0 -45
  58. package/.github/workflows/acceptance-windows-scheduled.yaml +0 -54
  59. package/.github/workflows/acceptance.yaml +0 -87
  60. package/.github/workflows/publish.yaml +0 -68
  61. package/.github/workflows/test-init.yml +0 -145
  62. package/.github/workflows/testdriver.yml +0 -170
  63. package/.github/workflows/windows-self-hosted.yaml +0 -82
  64. package/.prettierignore +0 -4
  65. package/.prettierrc +0 -1
  66. package/CHANGELOG.md +0 -34
  67. package/agents.md +0 -455
  68. package/debugger/bg.png +0 -0
  69. package/debugger/icon.png +0 -0
  70. package/debugger/index.html +0 -797
  71. package/debugger/td.png +0 -0
  72. package/debugger/tray-buffered.png +0 -0
  73. package/debugger/tray.png +0 -0
  74. package/docs/GITHUB_COMMENTS.md +0 -330
  75. package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +0 -167
  76. package/docs/QUICK-START-GITHUB-COMMENTS.md +0 -84
  77. package/docs/TEST-GITHUB-COMMENTS.md +0 -129
  78. package/docs/_scripts/link-replacer.js +0 -164
  79. package/docs/_scripts/upload-docs-to-openai.js +0 -284
  80. package/docs/docs.json +0 -393
  81. package/docs/github-integration-setup.md +0 -266
  82. package/docs/guide/best-practices-polling.mdx +0 -154
  83. package/docs/images/content/account/newprojectsettings.png +0 -0
  84. package/docs/images/content/account/projectpage.png +0 -0
  85. package/docs/images/content/account/projectreplays.png +0 -0
  86. package/docs/images/content/account/team-manage.png +0 -0
  87. package/docs/images/content/account/teampage.png +0 -0
  88. package/docs/images/content/extension/cursor.svg +0 -1
  89. package/docs/images/content/extension/vscode.svg +0 -57
  90. package/docs/images/content/extension/windsurf.svg +0 -3
  91. package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
  92. package/docs/images/content/side-by-side.png +0 -0
  93. package/docs/images/content/vscode/ide-full.png +0 -0
  94. package/docs/images/content/vscode/running.png +0 -0
  95. package/docs/images/content/vscode/vscode-2-assert.png +0 -0
  96. package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
  97. package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
  98. package/docs/images/content/vscode/vscode-file-creation.png +0 -0
  99. package/docs/images/content/vscode/vscode-install.png +0 -0
  100. package/docs/images/content/vscode/vscode-overview.png +0 -0
  101. package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
  102. package/docs/images/content/vscode/vscode-stopchat.png +0 -0
  103. package/docs/images/content/vscode/vscode-stoptest.png +0 -0
  104. package/docs/images/content/vscode/vscode-tdservice.png +0 -0
  105. package/docs/images/content/vscode/vscode-test-output.png +0 -0
  106. package/docs/images/content/vscode/vscode-testhistory.png +0 -0
  107. package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
  108. package/docs/images/content/vscode/vscode-testpane.png +0 -0
  109. package/docs/images/template/dark.png +0 -0
  110. package/docs/images/template/icon.png +0 -0
  111. package/docs/images/template/light.png +0 -0
  112. package/docs/snippets/calendar-link.mdx +0 -4
  113. package/docs/snippets/gitignore-warning.mdx +0 -7
  114. package/docs/snippets/lifecycle-warning.mdx +0 -6
  115. package/docs/snippets/test-prereqs.mdx +0 -12
  116. package/docs/snippets/tests/assert-replay.mdx +0 -7
  117. package/docs/snippets/tests/assert-yaml.mdx +0 -8
  118. package/docs/snippets/tests/exec-js-replay.mdx +0 -7
  119. package/docs/snippets/tests/exec-js-yaml.mdx +0 -32
  120. package/docs/snippets/tests/exec-shell-replay.mdx +0 -7
  121. package/docs/snippets/tests/exec-shell-yaml.mdx +0 -15
  122. package/docs/snippets/tests/hover-image-replay.mdx +0 -7
  123. package/docs/snippets/tests/hover-image-yaml.mdx +0 -17
  124. package/docs/snippets/tests/hover-text-replay.mdx +0 -7
  125. package/docs/snippets/tests/hover-text-with-description-replay.mdx +0 -7
  126. package/docs/snippets/tests/hover-text-with-description-yaml.mdx +0 -24
  127. package/docs/snippets/tests/hover-text-yaml.mdx +0 -14
  128. package/docs/snippets/tests/match-image-replay.mdx +0 -7
  129. package/docs/snippets/tests/match-image-yaml.mdx +0 -17
  130. package/docs/snippets/tests/press-keys-replay.mdx +0 -7
  131. package/docs/snippets/tests/press-keys-yaml.mdx +0 -36
  132. package/docs/snippets/tests/remember-replay.mdx +0 -7
  133. package/docs/snippets/tests/remember-yaml.mdx +0 -28
  134. package/docs/snippets/tests/scroll-replay.mdx +0 -7
  135. package/docs/snippets/tests/scroll-until-image-replay.mdx +0 -7
  136. package/docs/snippets/tests/scroll-until-image-yaml.mdx +0 -14
  137. package/docs/snippets/tests/scroll-until-text-replay.mdx +0 -7
  138. package/docs/snippets/tests/scroll-until-text-yaml.mdx +0 -17
  139. package/docs/snippets/tests/scroll-yaml.mdx +0 -30
  140. package/docs/snippets/tests/type-repeated-replay.mdx +0 -7
  141. package/docs/snippets/tests/type-repeated-yaml.mdx +0 -22
  142. package/docs/snippets/tests/type-replay.mdx +0 -7
  143. package/docs/snippets/tests/type-yaml.mdx +0 -28
  144. package/docs/snippets/tests/wait-for-image-replay.mdx +0 -7
  145. package/docs/snippets/tests/wait-for-image-yaml.mdx +0 -18
  146. package/docs/snippets/tests/wait-for-text-replay.mdx +0 -7
  147. package/docs/snippets/tests/wait-for-text-yaml.mdx +0 -18
  148. package/docs/snippets/tests/wait-replay.mdx +0 -7
  149. package/docs/snippets/tests/wait-yaml.mdx +0 -13
  150. package/docs/styles.css +0 -65
  151. package/docs/v6/account/dashboard.mdx +0 -16
  152. package/docs/v6/account/enterprise.mdx +0 -110
  153. package/docs/v6/account/pricing.mdx +0 -33
  154. package/docs/v6/account/projects.mdx +0 -33
  155. package/docs/v6/account/team.mdx +0 -35
  156. package/docs/v6/action/ami.mdx +0 -109
  157. package/docs/v6/action/performance.mdx +0 -105
  158. package/docs/v6/action/secrets.mdx +0 -93
  159. package/docs/v6/apps/chrome-extensions.mdx +0 -48
  160. package/docs/v6/apps/desktop-apps.mdx +0 -93
  161. package/docs/v6/apps/mobile-apps.mdx +0 -26
  162. package/docs/v6/apps/static-websites.mdx +0 -54
  163. package/docs/v6/apps/tauri-apps.mdx +0 -361
  164. package/docs/v6/bugs/jira.mdx +0 -232
  165. package/docs/v6/cli/overview.mdx +0 -66
  166. package/docs/v6/commands/assert.mdx +0 -45
  167. package/docs/v6/commands/exec.mdx +0 -282
  168. package/docs/v6/commands/focus-application.mdx +0 -44
  169. package/docs/v6/commands/hover-image.mdx +0 -69
  170. package/docs/v6/commands/hover-text.mdx +0 -47
  171. package/docs/v6/commands/if.mdx +0 -53
  172. package/docs/v6/commands/match-image.mdx +0 -67
  173. package/docs/v6/commands/press-keys.mdx +0 -87
  174. package/docs/v6/commands/remember.mdx +0 -49
  175. package/docs/v6/commands/run.mdx +0 -44
  176. package/docs/v6/commands/scroll-until-image.mdx +0 -66
  177. package/docs/v6/commands/scroll-until-text.mdx +0 -60
  178. package/docs/v6/commands/scroll.mdx +0 -69
  179. package/docs/v6/commands/type.mdx +0 -45
  180. package/docs/v6/commands/wait-for-image.mdx +0 -54
  181. package/docs/v6/commands/wait-for-text.mdx +0 -48
  182. package/docs/v6/commands/wait.mdx +0 -45
  183. package/docs/v6/exporting/junit.mdx +0 -218
  184. package/docs/v6/exporting/playwright.mdx +0 -197
  185. package/docs/v6/features/auto-healing.mdx +0 -144
  186. package/docs/v6/features/generation.mdx +0 -116
  187. package/docs/v6/features/parallel-testing.mdx +0 -151
  188. package/docs/v6/features/reusable-snippets.mdx +0 -131
  189. package/docs/v6/features/selectorless.mdx +0 -80
  190. package/docs/v6/features/visual-assertions.mdx +0 -139
  191. package/docs/v6/getting-started/ci.mdx +0 -146
  192. package/docs/v6/getting-started/cli.mdx +0 -91
  193. package/docs/v6/getting-started/editing.mdx +0 -100
  194. package/docs/v6/getting-started/playwright.mdx +0 -342
  195. package/docs/v6/getting-started/running.mdx +0 -48
  196. package/docs/v6/getting-started/self-hosting.mdx +0 -408
  197. package/docs/v6/getting-started/vscode.mdx +0 -89
  198. package/docs/v6/guide/assertions.mdx +0 -189
  199. package/docs/v6/guide/authentication.mdx +0 -136
  200. package/docs/v6/guide/code.mdx +0 -65
  201. package/docs/v6/guide/dashcam.mdx +0 -118
  202. package/docs/v6/guide/environment-variables.mdx +0 -26
  203. package/docs/v6/guide/lifecycle.mdx +0 -242
  204. package/docs/v6/guide/locating.mdx +0 -141
  205. package/docs/v6/guide/protips.mdx +0 -43
  206. package/docs/v6/guide/variables.mdx +0 -143
  207. package/docs/v6/guide/waiting.mdx +0 -130
  208. package/docs/v6/importing/csv.mdx +0 -196
  209. package/docs/v6/importing/gherkin.mdx +0 -143
  210. package/docs/v6/importing/jira.mdx +0 -164
  211. package/docs/v6/importing/testrail.mdx +0 -162
  212. package/docs/v6/integrations/electron.mdx +0 -146
  213. package/docs/v6/integrations/netlify.mdx +0 -100
  214. package/docs/v6/integrations/vercel.mdx +0 -125
  215. package/docs/v6/interactive/explore.mdx +0 -99
  216. package/docs/v6/interactive/run.mdx +0 -52
  217. package/docs/v6/interactive/save.mdx +0 -63
  218. package/docs/v6/overview/comparison.mdx +0 -101
  219. package/docs/v6/overview/faq.mdx +0 -162
  220. package/docs/v6/overview/performance.mdx +0 -52
  221. package/docs/v6/overview/quickstart.mdx +0 -137
  222. package/docs/v6/overview/what-is-testdriver.mdx +0 -85
  223. package/docs/v6/scenarios/ai-chatbot.mdx +0 -28
  224. package/docs/v6/scenarios/cookie-banner.mdx +0 -32
  225. package/docs/v6/scenarios/file-upload.mdx +0 -33
  226. package/docs/v6/scenarios/form-filling.mdx +0 -32
  227. package/docs/v6/scenarios/log-in.mdx +0 -75
  228. package/docs/v6/scenarios/pdf-generation.mdx +0 -25
  229. package/docs/v6/scenarios/spell-check.mdx +0 -22
  230. package/docs/v6/security/action.mdx +0 -84
  231. package/docs/v6/security/agent.mdx +0 -73
  232. package/docs/v6/security/platform.mdx +0 -77
  233. package/docs/v6/tutorials/advanced-test.mdx +0 -81
  234. package/docs/v6/tutorials/basic-test.mdx +0 -45
  235. package/docs/v7/_drafts/agents.mdx +0 -852
  236. package/docs/v7/_drafts/architecture.mdx +0 -399
  237. package/docs/v7/_drafts/auto-cache-key.mdx +0 -167
  238. package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +0 -100
  239. package/docs/v7/_drafts/best-practices.mdx +0 -486
  240. package/docs/v7/_drafts/caching-ai.mdx +0 -215
  241. package/docs/v7/_drafts/caching-selectors.mdx +0 -424
  242. package/docs/v7/_drafts/caching.mdx +0 -366
  243. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +0 -425
  244. package/docs/v7/_drafts/commands/assert.mdx +0 -45
  245. package/docs/v7/_drafts/commands/exec.mdx +0 -282
  246. package/docs/v7/_drafts/commands/focus-application.mdx +0 -44
  247. package/docs/v7/_drafts/commands/hover-image.mdx +0 -69
  248. package/docs/v7/_drafts/commands/hover-text.mdx +0 -47
  249. package/docs/v7/_drafts/commands/if.mdx +0 -53
  250. package/docs/v7/_drafts/commands/match-image.mdx +0 -67
  251. package/docs/v7/_drafts/commands/press-keys.mdx +0 -87
  252. package/docs/v7/_drafts/commands/remember.mdx +0 -49
  253. package/docs/v7/_drafts/commands/run.mdx +0 -44
  254. package/docs/v7/_drafts/commands/scroll-until-image.mdx +0 -66
  255. package/docs/v7/_drafts/commands/scroll-until-text.mdx +0 -60
  256. package/docs/v7/_drafts/commands/scroll.mdx +0 -69
  257. package/docs/v7/_drafts/commands/type.mdx +0 -45
  258. package/docs/v7/_drafts/commands/wait-for-image.mdx +0 -54
  259. package/docs/v7/_drafts/commands/wait-for-text.mdx +0 -48
  260. package/docs/v7/_drafts/commands/wait.mdx +0 -45
  261. package/docs/v7/_drafts/configuration.mdx +0 -378
  262. package/docs/v7/_drafts/contributing.mdx +0 -174
  263. package/docs/v7/_drafts/core.mdx +0 -458
  264. package/docs/v7/_drafts/dashcam-title-feature.mdx +0 -89
  265. package/docs/v7/_drafts/debugging.mdx +0 -349
  266. package/docs/v7/_drafts/error-handling.mdx +0 -501
  267. package/docs/v7/_drafts/faq.mdx +0 -393
  268. package/docs/v7/_drafts/hooks.mdx +0 -360
  269. package/docs/v7/_drafts/init-command.mdx +0 -95
  270. package/docs/v7/_drafts/installation.mdx +0 -420
  271. package/docs/v7/_drafts/migration.mdx +0 -562
  272. package/docs/v7/_drafts/observable.mdx +0 -604
  273. package/docs/v7/_drafts/playwright.mdx +0 -342
  274. package/docs/v7/_drafts/plugin-migration.mdx +0 -220
  275. package/docs/v7/_drafts/powerful.mdx +0 -419
  276. package/docs/v7/_drafts/presets.mdx +0 -210
  277. package/docs/v7/_drafts/progressive-disclosure.mdx +0 -230
  278. package/docs/v7/_drafts/prompt-cache.mdx +0 -200
  279. package/docs/v7/_drafts/provision.mdx +0 -390
  280. package/docs/v7/_drafts/quick-start-test-recording.mdx +0 -214
  281. package/docs/v7/_drafts/readme.mdx +0 -135
  282. package/docs/v7/_drafts/reports.mdx +0 -414
  283. package/docs/v7/_drafts/scalable.mdx +0 -754
  284. package/docs/v7/_drafts/screenshot.mdx +0 -155
  285. package/docs/v7/_drafts/sdk-awesome-logs.mdx +0 -468
  286. package/docs/v7/_drafts/sdk-browser-rendering.mdx +0 -167
  287. package/docs/v7/_drafts/sdk-migration.mdx +0 -474
  288. package/docs/v7/_drafts/sdk-v7-complete.mdx +0 -345
  289. package/docs/v7/_drafts/self-hosting.mdx +0 -369
  290. package/docs/v7/_drafts/test-recording.mdx +0 -382
  291. package/docs/v7/_drafts/troubleshooting.mdx +0 -526
  292. package/docs/v7/_drafts/vitest-plugin.mdx +0 -477
  293. package/docs/v7/_drafts/vitest.mdx +0 -535
  294. package/docs/v7/_drafts/writing-tests.mdx +0 -25
  295. package/docs/v7/examples.mdx +0 -5
  296. package/eslint.config.js +0 -67
  297. package/examples/ai.test.mjs +0 -30
  298. package/examples/assert.test.mjs +0 -46
  299. package/examples/captcha-api.test.mjs +0 -50
  300. package/examples/chrome-extension.test.mjs +0 -94
  301. package/examples/drag-and-drop.test.mjs +0 -58
  302. package/examples/element-not-found.test.mjs +0 -26
  303. package/examples/exec-output.test.mjs +0 -59
  304. package/examples/exec-pwsh.test.mjs +0 -57
  305. package/examples/focus-window.test.mjs +0 -36
  306. package/examples/formatted-logging.test.mjs +0 -26
  307. package/examples/hover-image.test.mjs +0 -52
  308. package/examples/hover-text-with-description.test.mjs +0 -56
  309. package/examples/hover-text.test.mjs +0 -27
  310. package/examples/installer.test.mjs +0 -49
  311. package/examples/launch-vscode-linux.test.mjs +0 -54
  312. package/examples/match-image.test.mjs +0 -54
  313. package/examples/no-provision.test.mjs +0 -23
  314. package/examples/press-keys.test.mjs +0 -50
  315. package/examples/prompt.test.mjs +0 -33
  316. package/examples/scroll-keyboard.test.mjs +0 -37
  317. package/examples/scroll-until-image.test.mjs +0 -39
  318. package/examples/scroll-until-text.test.mjs +0 -67
  319. package/examples/scroll.test.mjs +0 -41
  320. package/examples/type.test.mjs +0 -45
  321. package/examples/windows-installer.test.mjs +0 -53
  322. package/interfaces/cli/commands/edit.js +0 -3
  323. package/interfaces/cli/commands/generate.js +0 -3
  324. package/interfaces/cli/commands/run.js +0 -3
  325. package/interfaces/cli/utils/factory.js +0 -71
  326. package/jsconfig.json +0 -26
  327. package/manual/test-init-command.js +0 -223
  328. package/sdk-log-formatter.js +0 -930
  329. package/setup/aws/cloudformation.yaml +0 -470
  330. package/setup/aws/spawn-runner.sh +0 -190
  331. package/test/api-resilience.test.mjs +0 -0
  332. package/test/captcha-solver.test.mjs +0 -70
  333. package/test/chrome-remote-debugging.test.mjs +0 -66
  334. package/test/manual/debug-locate-response.js +0 -82
  335. package/test/manual/reconnect-provision.test.mjs +0 -49
  336. package/test/manual/test-console-logs.test.mjs +0 -42
  337. package/test/manual/test-find-api.js +0 -73
  338. package/test/manual/test-init.sh +0 -54
  339. package/test/manual/test-prompt-cache.js +0 -96
  340. package/test/manual/test-provision-auth.mjs +0 -22
  341. package/test/manual/test-sandbox-render.js +0 -28
  342. package/test/manual/test-sdk-methods.js +0 -15
  343. package/test/manual/test-sdk-refactor.js +0 -53
  344. package/test/manual/test-stack-trace.mjs +0 -57
  345. package/test/manual/verify-element-api.js +0 -89
  346. package/test/manual/verify-types.js +0 -0
  347. package/test/manual-unawaited-promise.test.mjs +0 -31
  348. package/testdriver-plugin/skills/actions/SKILL.md +0 -93
  349. package/testdriver-plugin/skills/assertions/SKILL.md +0 -77
  350. package/testdriver-plugin/skills/caching/SKILL.md +0 -66
  351. package/testdriver-plugin/skills/creating-tests/SKILL.md +0 -104
  352. package/testdriver-plugin/skills/finding-elements/SKILL.md +0 -77
  353. package/testdriver-plugin/skills/github-actions/SKILL.md +0 -100
  354. package/testdriver-plugin/skills/running-tests/SKILL.md +0 -77
  355. package/testdriver-plugin/skills/secrets/SKILL.md +0 -87
  356. package/testdriver-plugin/skills/self-hosting/SKILL.md +0 -89
  357. package/testdriver-plugin/skills/setup/SKILL.md +0 -76
  358. package/testdriver-plugin/skills/variables/SKILL.md +0 -88
  359. package/testdriver-plugin/skills/waiting/SKILL.md +0 -72
  360. package/vitest.config.mjs +0 -29
@@ -1,754 +0,0 @@
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 npx vitest run
141
- TEST_ENV=staging npx vitest run
142
- TEST_ENV=production npx 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
- npx vitest run
249
-
250
- # Control concurrency
251
- npx 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
- npx vitest
261
-
262
- # Only run changed tests
263
- npx 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: npx 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
- - npx 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: npx 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 'npx 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
- npx 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: npx 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: npx 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: npx 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: npx 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
- - npx vitest run --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
616
- ```
617
- </Tab>
618
-
619
- <Tab title="Manual Sharding">
620
- ```bash
621
- # Machine 1
622
- npx vitest run --shard=1/4
623
-
624
- # Machine 2
625
- npx vitest run --shard=2/4
626
-
627
- # Machine 3
628
- npx vitest run --shard=3/4
629
-
630
- # Machine 4
631
- npx 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
- npx vitest run
685
- ```
686
-
687
- [Learn about sandbox management](/agents.md#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>