testdriverai 7.3.2 → 7.3.4
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/.github/workflows/acceptance-linux-scheduled.yaml +45 -0
- package/.github/workflows/acceptance-windows-scheduled.yaml +54 -0
- package/.github/workflows/acceptance.yaml +106 -0
- package/.github/workflows/publish.yaml +75 -0
- package/.github/workflows/test-init.yml +157 -0
- package/.github/workflows/testdriver.yml +170 -0
- package/.github/workflows/windows-self-hosted.yaml +82 -0
- package/.prettierignore +4 -0
- package/.prettierrc +1 -0
- package/CHANGELOG.md +162 -0
- package/SKILLs.md +17 -0
- package/ai/.claude-plugin/plugin.json +9 -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/_scripts/generate-skills.js +149 -0
- package/docs/_scripts/link-replacer.js +164 -0
- package/docs/_scripts/upload-docs-to-openai.js +284 -0
- package/docs/claude-mcp-plugin.mdx +160 -0
- package/docs/docs.json +394 -0
- package/docs/github-integration-setup.md +266 -0
- package/docs/guide/best-practices-polling.mdx +154 -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/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/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 +282 -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 +852 -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 +282 -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 +754 -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/{ai/skills/testdriver:ai/SKILL.md → docs/v7/ai.mdx} +4 -3
- package/{ai/skills/testdriver:assert/SKILL.md → docs/v7/assert.mdx} +4 -3
- package/{ai/skills/testdriver:aws-setup/SKILL.md → docs/v7/aws-setup.mdx} +4 -3
- package/{ai/skills/testdriver:caching/SKILL.md → docs/v7/caching.mdx} +7 -3
- package/{ai/skills/testdriver:captcha/SKILL.md → docs/v7/captcha.mdx} +4 -3
- package/{ai/skills/testdriver:ci-cd/SKILL.md → docs/v7/ci-cd.mdx} +4 -3
- package/{ai/skills/testdriver:click/SKILL.md → docs/v7/click.mdx} +4 -3
- package/{ai/skills/testdriver:client/SKILL.md → docs/v7/client.mdx} +8 -3
- package/{ai/skills/testdriver:cloud/SKILL.md → docs/v7/cloud.mdx} +4 -3
- package/{ai/skills/testdriver:customizing-devices/SKILL.md → docs/v7/customizing-devices.mdx} +3 -3
- package/{ai/skills/testdriver:dashcam/SKILL.md → docs/v7/dashcam.mdx} +4 -3
- package/docs/v7/debugging-with-screenshots.mdx +402 -0
- package/{ai/skills/testdriver:device-config/SKILL.md → docs/v7/device-config.mdx} +3 -3
- package/{ai/skills/testdriver:double-click/SKILL.md → docs/v7/double-click.mdx} +3 -3
- package/{ai/skills/testdriver:elements/SKILL.md → docs/v7/elements.mdx} +4 -3
- package/{ai/skills/testdriver:enterprise/SKILL.md → docs/v7/enterprise.mdx} +5 -3
- package/docs/v7/examples.mdx +5 -0
- package/{ai/skills/testdriver:exec/SKILL.md → docs/v7/exec.mdx} +4 -3
- package/{ai/skills/testdriver:find/SKILL.md → docs/v7/find.mdx} +4 -3
- package/{ai/skills/testdriver:focus-application/SKILL.md → docs/v7/focus-application.mdx} +4 -3
- package/{ai/skills/testdriver:generating-tests/SKILL.md → docs/v7/generating-tests.mdx} +3 -3
- package/{ai/skills/testdriver:hover/SKILL.md → docs/v7/hover.mdx} +4 -3
- package/{ai/skills/testdriver:locating-elements/SKILL.md → docs/v7/locating-elements.mdx} +3 -3
- package/{ai/skills/testdriver:making-assertions/SKILL.md → docs/v7/making-assertions.mdx} +3 -3
- package/{ai/skills/testdriver:mouse-down/SKILL.md → docs/v7/mouse-down.mdx} +3 -3
- package/{ai/skills/testdriver:mouse-up/SKILL.md → docs/v7/mouse-up.mdx} +3 -3
- package/docs/v7/ocr.mdx +236 -0
- package/{ai/skills/testdriver:performing-actions/SKILL.md → docs/v7/performing-actions.mdx} +3 -3
- package/{ai/skills/testdriver:press-keys/SKILL.md → docs/v7/press-keys.mdx} +4 -3
- package/{ai/skills/testdriver:quickstart/SKILL.md → docs/v7/quickstart.mdx} +6 -20
- package/{ai/skills/testdriver:reusable-code/SKILL.md → docs/v7/reusable-code.mdx} +3 -3
- package/{ai/skills/testdriver:right-click/SKILL.md → docs/v7/right-click.mdx} +3 -3
- package/{ai/skills/testdriver:running-tests/SKILL.md → docs/v7/running-tests.mdx} +7 -3
- package/{ai/skills/testdriver:screenshot/SKILL.md → docs/v7/screenshot.mdx} +88 -6
- package/{ai/skills/testdriver:scroll/SKILL.md → docs/v7/scroll.mdx} +40 -3
- package/{ai/skills/testdriver:secrets/SKILL.md → docs/v7/secrets.mdx} +3 -3
- package/{ai/skills/testdriver:self-hosted/SKILL.md → docs/v7/self-hosted.mdx} +4 -3
- package/{ai/skills/testdriver:type/SKILL.md → docs/v7/type.mdx} +4 -3
- package/{ai/skills/testdriver:variables/SKILL.md → docs/v7/variables.mdx} +3 -3
- package/{ai/skills/testdriver:waiting-for-elements/SKILL.md → docs/v7/waiting-for-elements.mdx} +3 -3
- package/{ai/skills/testdriver:what-is-testdriver/SKILL.md → docs/v7/what-is-testdriver.mdx} +3 -3
- package/eslint.config.js +67 -0
- package/examples/ai.test.mjs +30 -0
- package/examples/assert.test.mjs +47 -0
- package/examples/captcha-api.test.mjs +50 -0
- package/examples/chrome-extension.test.mjs +94 -0
- package/examples/drag-and-drop.test.mjs +58 -0
- package/examples/element-not-found.test.mjs +26 -0
- package/examples/exec-output.test.mjs +59 -0
- package/examples/exec-pwsh.test.mjs +57 -0
- package/examples/focus-window.test.mjs +36 -0
- package/examples/formatted-logging.test.mjs +26 -0
- package/examples/hover-image.test.mjs +52 -0
- package/examples/hover-text-with-description.test.mjs +56 -0
- package/examples/hover-text.test.mjs +27 -0
- package/examples/installer.test.mjs +49 -0
- package/examples/launch-vscode-linux.test.mjs +54 -0
- package/examples/match-image.test.mjs +54 -0
- package/examples/no-provision.test.mjs +23 -0
- package/examples/press-keys.test.mjs +50 -0
- package/examples/prompt.test.mjs +33 -0
- package/examples/scroll-keyboard.test.mjs +37 -0
- package/examples/scroll-until-image.test.mjs +39 -0
- package/examples/scroll-until-text.test.mjs +67 -0
- package/examples/scroll.test.mjs +41 -0
- package/examples/type.test.mjs +45 -0
- package/examples/windows-installer.test.mjs +53 -0
- package/jsconfig.json +26 -0
- package/manual/test-init-command.js +223 -0
- package/mcp-server/README.md +312 -0
- package/mcp-server/mcp-app.html +28 -0
- package/mcp-server/mcp-config.example.json +19 -0
- package/mcp-server/package-lock.json +4018 -0
- package/mcp-server/package.json +29 -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 +2313 -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 +2 -17
- package/scripts/generate-skills.js +94 -0
- package/setup/aws/cloudformation.yaml +470 -0
- package/setup/aws/spawn-runner.sh +190 -0
- package/test/api-resilience.test.mjs +0 -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/test-ide-preview.mjs +17 -0
- package/tests/airbnb-booking.test.mjs +39 -0
- package/tests/airbnb-search.test.mjs +43 -0
- package/tests/example.test.js +33 -0
- package/tests/login.js +28 -0
- package/vitest.config.mjs +24 -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
- package/ai/skills/testdriver:examples/SKILL.md +0 -7
- package/ai/skills/testdriver:mcp-workflow/SKILL.md +0 -410
- package/ai/skills/testdriver:testdriver/SKILL.md +0 -523
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const OpenAI = require("openai");
|
|
6
|
+
const { glob } = require("glob");
|
|
7
|
+
|
|
8
|
+
// Configuration
|
|
9
|
+
const DOCS_DIR = path.join(__dirname, "docs");
|
|
10
|
+
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
|
|
11
|
+
const VECTOR_STORE_NAME = "testdriverai-docs";
|
|
12
|
+
|
|
13
|
+
if (!OPENAI_API_KEY) {
|
|
14
|
+
console.error("Error: OPENAI_API_KEY environment variable is required");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Initialize OpenAI client
|
|
19
|
+
const openai = new OpenAI({
|
|
20
|
+
apiKey: OPENAI_API_KEY,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Parse MDX file to extract frontmatter and content
|
|
25
|
+
*/
|
|
26
|
+
function parseMdxFile(filePath) {
|
|
27
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
28
|
+
|
|
29
|
+
// Extract frontmatter
|
|
30
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
31
|
+
|
|
32
|
+
if (!frontmatterMatch) {
|
|
33
|
+
return {
|
|
34
|
+
metadata: {},
|
|
35
|
+
content: content,
|
|
36
|
+
title: path.basename(filePath, ".mdx"),
|
|
37
|
+
filePath: path.relative(DOCS_DIR, filePath),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const frontmatter = frontmatterMatch[1];
|
|
42
|
+
const mainContent = frontmatterMatch[2];
|
|
43
|
+
|
|
44
|
+
// Parse frontmatter (simple YAML-like parsing)
|
|
45
|
+
const metadata = {};
|
|
46
|
+
frontmatter.split("\n").forEach((line) => {
|
|
47
|
+
const match = line.match(/^([^:]+):\s*"?([^"]*)"?$/);
|
|
48
|
+
if (match) {
|
|
49
|
+
metadata[match[1].trim()] = match[2].trim();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
metadata,
|
|
55
|
+
content: mainContent,
|
|
56
|
+
title: metadata.title || path.basename(filePath, ".mdx"),
|
|
57
|
+
filePath: path.relative(DOCS_DIR, filePath),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get all MDX files in the docs directory
|
|
63
|
+
*/
|
|
64
|
+
async function getAllMdxFiles() {
|
|
65
|
+
const pattern = path.join(DOCS_DIR, "**/*.mdx");
|
|
66
|
+
const files = await glob(pattern);
|
|
67
|
+
return files;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Create a vector store
|
|
72
|
+
*/
|
|
73
|
+
async function createVectorStore() {
|
|
74
|
+
try {
|
|
75
|
+
const vectorStore = await openai.vectorStores.create({
|
|
76
|
+
name: VECTOR_STORE_NAME,
|
|
77
|
+
expires_after: {
|
|
78
|
+
anchor: "last_active_at",
|
|
79
|
+
days: 365,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
console.log(`✅ Created vector store: ${vectorStore.id}`);
|
|
84
|
+
return vectorStore;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error("Error creating vector store:", error);
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Upload a single file to the vector store
|
|
93
|
+
*/
|
|
94
|
+
async function uploadSingleFile(vectorStoreId, file) {
|
|
95
|
+
try {
|
|
96
|
+
console.log(`📁 Processing: ${file.filePath}`);
|
|
97
|
+
|
|
98
|
+
// Create a temporary file with processed content
|
|
99
|
+
const tempFilePath = `/tmp/testdriverai-${Date.now()}-${Math.random()}-${path.basename(file.filePath)}.txt`;
|
|
100
|
+
|
|
101
|
+
// Format the content for better vector search
|
|
102
|
+
const formattedContent = `Title: ${file.title}
|
|
103
|
+
File: ${file.filePath}
|
|
104
|
+
${file.metadata.description ? `Description: ${file.metadata.description}` : ""}
|
|
105
|
+
${file.metadata.sidebarTitle ? `Sidebar Title: ${file.metadata.sidebarTitle}` : ""}
|
|
106
|
+
|
|
107
|
+
${file.content}`;
|
|
108
|
+
|
|
109
|
+
fs.writeFileSync(tempFilePath, formattedContent);
|
|
110
|
+
|
|
111
|
+
// Upload to OpenAI and add to vector store
|
|
112
|
+
const vectorStoreFile = await openai.vectorStores.files.createAndPoll(
|
|
113
|
+
vectorStoreId,
|
|
114
|
+
{
|
|
115
|
+
file_id: (
|
|
116
|
+
await openai.files.create({
|
|
117
|
+
file: fs.createReadStream(tempFilePath),
|
|
118
|
+
purpose: "assistants",
|
|
119
|
+
})
|
|
120
|
+
).id,
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Clean up temp file
|
|
125
|
+
fs.unlinkSync(tempFilePath);
|
|
126
|
+
|
|
127
|
+
console.log(`✅ Uploaded: ${file.title} (${vectorStoreFile.id})`);
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
vectorStoreFileId: vectorStoreFile.id,
|
|
131
|
+
originalPath: file.filePath,
|
|
132
|
+
title: file.title,
|
|
133
|
+
};
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error(`❌ Error uploading ${file.filePath}:`, error);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Upload files to the vector store in parallel
|
|
142
|
+
*/
|
|
143
|
+
async function uploadFilesToVectorStore(vectorStoreId, files) {
|
|
144
|
+
console.log(`📤 Uploading ${files.length} files in parallel...`);
|
|
145
|
+
|
|
146
|
+
// Process files in parallel with a concurrency limit
|
|
147
|
+
const BATCH_SIZE = 10; // Process 10 files at a time to avoid overwhelming the API
|
|
148
|
+
const uploadedFiles = [];
|
|
149
|
+
|
|
150
|
+
for (let i = 0; i < files.length; i += BATCH_SIZE) {
|
|
151
|
+
const batch = files.slice(i, i + BATCH_SIZE);
|
|
152
|
+
console.log(
|
|
153
|
+
`Processing batch ${Math.floor(i / BATCH_SIZE) + 1}/${Math.ceil(files.length / BATCH_SIZE)} (${batch.length} files)`,
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const batchPromises = batch.map((file) =>
|
|
157
|
+
uploadSingleFile(vectorStoreId, file),
|
|
158
|
+
);
|
|
159
|
+
const batchResults = await Promise.all(batchPromises);
|
|
160
|
+
|
|
161
|
+
// Filter out failed uploads (null results)
|
|
162
|
+
const successfulUploads = batchResults.filter((result) => result !== null);
|
|
163
|
+
uploadedFiles.push(...successfulUploads);
|
|
164
|
+
|
|
165
|
+
console.log(
|
|
166
|
+
`✅ Batch complete: ${successfulUploads.length}/${batch.length} files uploaded successfully`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return uploadedFiles;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Wait for vector store to be ready
|
|
175
|
+
*/
|
|
176
|
+
async function waitForVectorStoreReady(vectorStoreId) {
|
|
177
|
+
console.log("⏳ Waiting for vector store to process files...");
|
|
178
|
+
|
|
179
|
+
let attempts = 0;
|
|
180
|
+
const maxAttempts = 30;
|
|
181
|
+
|
|
182
|
+
while (attempts < maxAttempts) {
|
|
183
|
+
try {
|
|
184
|
+
const vectorStore = await openai.vectorStores.retrieve(vectorStoreId);
|
|
185
|
+
|
|
186
|
+
if (vectorStore.status === "completed") {
|
|
187
|
+
console.log("✅ Vector store is ready!");
|
|
188
|
+
return vectorStore;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (vectorStore.status === "failed") {
|
|
192
|
+
throw new Error("Vector store processing failed");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
console.log(
|
|
196
|
+
`⏳ Status: ${vectorStore.status}, Files: ${vectorStore.file_counts.completed}/${vectorStore.file_counts.total}`,
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
200
|
+
attempts++;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error("Error checking vector store status:", error);
|
|
203
|
+
attempts++;
|
|
204
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
throw new Error("Timeout waiting for vector store to be ready");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Main function
|
|
213
|
+
*/
|
|
214
|
+
async function main() {
|
|
215
|
+
try {
|
|
216
|
+
console.log(
|
|
217
|
+
"🚀 Starting TestDriver.ai docs upload to OpenAI Vector Store...\n",
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Get all MDX files
|
|
221
|
+
console.log("📂 Finding MDX files...");
|
|
222
|
+
const mdxFilePaths = await getAllMdxFiles();
|
|
223
|
+
console.log(`Found ${mdxFilePaths.length} MDX files\n`);
|
|
224
|
+
|
|
225
|
+
// Parse all MDX files
|
|
226
|
+
console.log("📝 Parsing MDX files...");
|
|
227
|
+
const parsedFiles = mdxFilePaths.map((filePath) => parseMdxFile(filePath));
|
|
228
|
+
console.log(`Parsed ${parsedFiles.length} files\n`);
|
|
229
|
+
|
|
230
|
+
// Create vector store
|
|
231
|
+
console.log("🗂️ Creating vector store...");
|
|
232
|
+
const vectorStore = await createVectorStore();
|
|
233
|
+
console.log("");
|
|
234
|
+
|
|
235
|
+
// Upload files to vector store
|
|
236
|
+
console.log("📤 Uploading files to OpenAI Vector Store...");
|
|
237
|
+
const uploadedFiles = await uploadFilesToVectorStore(
|
|
238
|
+
vectorStore.id,
|
|
239
|
+
parsedFiles,
|
|
240
|
+
);
|
|
241
|
+
console.log("");
|
|
242
|
+
|
|
243
|
+
// Wait for processing
|
|
244
|
+
await waitForVectorStoreReady(vectorStore.id);
|
|
245
|
+
|
|
246
|
+
console.log("\n🎉 Upload complete!");
|
|
247
|
+
console.log(`Vector Store ID: ${vectorStore.id}`);
|
|
248
|
+
console.log(`Files uploaded: ${uploadedFiles.length}`);
|
|
249
|
+
console.log(
|
|
250
|
+
"\nYou can now use this vector store ID in your OpenAI Assistant or for retrieval.",
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
// Save results to file
|
|
254
|
+
const results = {
|
|
255
|
+
vectorStoreId: vectorStore.id,
|
|
256
|
+
uploadedFiles: uploadedFiles,
|
|
257
|
+
timestamp: new Date().toISOString(),
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
fs.writeFileSync(
|
|
261
|
+
path.join(__dirname, "openai-vector-store-results.json"),
|
|
262
|
+
JSON.stringify(results, null, 2),
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
console.log("\n📄 Results saved to openai-vector-store-results.json");
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error("\n❌ Error:", error);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Run the script
|
|
273
|
+
if (require.main === module) {
|
|
274
|
+
main();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
module.exports = {
|
|
278
|
+
main,
|
|
279
|
+
parseMdxFile,
|
|
280
|
+
getAllMdxFiles,
|
|
281
|
+
createVectorStore,
|
|
282
|
+
uploadSingleFile,
|
|
283
|
+
uploadFilesToVectorStore,
|
|
284
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Using TestDriver with Claude Code (MCP)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
TestDriver exposes test results and analytics over an **HTTP MCP server**, so Claude Code (or any MCP-compatible client) can inspect your test runs, failures, and filters.
|
|
6
|
+
|
|
7
|
+
This guide assumes:
|
|
8
|
+
|
|
9
|
+
- Your API server is running the MCP endpoint at `POST /api/v1/mcp`
|
|
10
|
+
- You have a **team or user API key** for authentication
|
|
11
|
+
- You are using this repo (`testdriverai`) as the SDK / local tooling
|
|
12
|
+
|
|
13
|
+
## 1. Configure an API key
|
|
14
|
+
|
|
15
|
+
Get your API key from the team settings:
|
|
16
|
+
|
|
17
|
+
- Visit your team page (e.g. `https://console.testdriver.ai/team`)
|
|
18
|
+
- Create or copy a **Team API Key** (or User API Key)
|
|
19
|
+
- Store it locally as an environment variable, for example:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
export TD_API_KEY="your_api_key_here"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The MCP server expects this API key in the `X-Api-Key` header (or `Authorization: Bearer <key>`).
|
|
26
|
+
|
|
27
|
+
## 2. HTTP MCP endpoint contract
|
|
28
|
+
|
|
29
|
+
The HTTP endpoint lives at:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
POST /api/v1/mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Common request shapes:
|
|
36
|
+
|
|
37
|
+
- **List tools**
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"kind": "list_tools"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- **Call a tool**
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"kind": "call_tool",
|
|
50
|
+
"tool": "list_test_runs",
|
|
51
|
+
"arguments": {
|
|
52
|
+
"status": "failed",
|
|
53
|
+
"page": 1,
|
|
54
|
+
"limit": 20
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Responses from tool calls follow the MCP content convention:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"content": [
|
|
64
|
+
{
|
|
65
|
+
"type": "json",
|
|
66
|
+
"json": {
|
|
67
|
+
"testRuns": [],
|
|
68
|
+
"totalCount": 0,
|
|
69
|
+
"hasMore": false
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Available tools
|
|
77
|
+
|
|
78
|
+
The MCP server advertises at least these tools in `list_tools`:
|
|
79
|
+
|
|
80
|
+
- `list_test_runs`
|
|
81
|
+
List recent TestDriver test runs for the current team, with filters and pagination.
|
|
82
|
+
|
|
83
|
+
- `get_test_run_detail`
|
|
84
|
+
Get a single test run and its test cases (including replay IDs / share keys when available).
|
|
85
|
+
|
|
86
|
+
- `list_test_cases`
|
|
87
|
+
List individual test cases for the team with status, duration, error messages, and replay info.
|
|
88
|
+
|
|
89
|
+
- `get_filter_options`
|
|
90
|
+
Get branch, suite, repo, filename, commit, status, platform, and test name options for building queries.
|
|
91
|
+
|
|
92
|
+
## 3. Claude Code MCP server configuration
|
|
93
|
+
|
|
94
|
+
You can point Claude Code at the HTTP MCP endpoint using a JSON configuration similar to:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"$schema": "https://schema.anthropic.com/mcp/servers.json",
|
|
99
|
+
"mcpServers": {
|
|
100
|
+
"testdriver-cloud": {
|
|
101
|
+
"type": "sse",
|
|
102
|
+
"url": "https://your-api-host.example.com/api/v1/mcp",
|
|
103
|
+
"requestHeaders": {
|
|
104
|
+
"X-Api-Key": "${TD_API_KEY}"
|
|
105
|
+
},
|
|
106
|
+
"description": "Query TestDriver test runs, test cases, and filters for your team using an API key."
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
You can find this exact snippet in the repo at:
|
|
113
|
+
|
|
114
|
+
- `claude-mcp-config.example.json`
|
|
115
|
+
|
|
116
|
+
Replace `https://your-api-host.example.com` with your actual API origin (e.g. `https://api.testdriver.ai` or `http://localhost:1337` in development).
|
|
117
|
+
|
|
118
|
+
### Local development
|
|
119
|
+
|
|
120
|
+
For local development:
|
|
121
|
+
|
|
122
|
+
- Run your API server on `http://localhost:1337`
|
|
123
|
+
- Point `baseUrl` at `http://localhost:1337/api/v1/mcp`
|
|
124
|
+
- Use a local team or user API key in `TD_API_KEY`
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"mcpServers": {
|
|
129
|
+
"testdriver-cloud-local": {
|
|
130
|
+
"type": "sse",
|
|
131
|
+
"url": "http://localhost:1337/api/v1/mcp",
|
|
132
|
+
"requestHeaders": {
|
|
133
|
+
"X-Api-Key": "${TD_API_KEY}"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 4. Skills documentation for Claude
|
|
141
|
+
|
|
142
|
+
Claude Code expects a `SKILLs.md` file to explain how to use a server. In this repo:
|
|
143
|
+
|
|
144
|
+
- `ai/agents/testdriver.md` contains the **full TestDriver Agent Guide**
|
|
145
|
+
- `SKILLs.md` acts as a short wrapper that points Claude (and other agents) to the agent guide
|
|
146
|
+
|
|
147
|
+
Use these as the primary reference for:
|
|
148
|
+
|
|
149
|
+
- How to initialize the `TestDriver` SDK in Vitest
|
|
150
|
+
- The MCP workflow for building tests interactively with visual feedback
|
|
151
|
+
- How to find elements, click, type, scroll, assert, and capture screenshots
|
|
152
|
+
|
|
153
|
+
The MCP tools described above are **read-only** helpers for:
|
|
154
|
+
|
|
155
|
+
- Inspecting recent test runs and failures
|
|
156
|
+
- Discovering branches, files, and suites to focus on
|
|
157
|
+
- Pulling detailed test case and replay information into Claude for analysis
|
|
158
|
+
|
|
159
|
+
Use the SDK (`testdriverai`) for **driving tests**, and the HTTP MCP server (`/api/v1/mcp`) for **observing and debugging** them from Claude Code.
|
|
160
|
+
|