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