@testdriverai/agent 7.8.0-canary.10
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,167 @@
|
|
|
1
|
+
# SDK Browser Rendering Feature
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The TestDriver SDK now supports automatic browser rendering of the sandbox environment, matching the behavior of the existing agent CLI. When connecting to a sandbox, the SDK will automatically open a browser window showing the live VNC session, allowing you to watch test execution in real-time.
|
|
6
|
+
|
|
7
|
+
## Changes Made
|
|
8
|
+
|
|
9
|
+
### 1. SDK Core (`sdk.js`)
|
|
10
|
+
|
|
11
|
+
#### Added Dependencies
|
|
12
|
+
- Imported `createDebuggerProcess` from `./agent/lib/debugger.js` to enable the debugger server
|
|
13
|
+
|
|
14
|
+
#### New Instance Variables
|
|
15
|
+
- `debuggerProcess`: Reference to the debugger server process
|
|
16
|
+
- `debuggerUrl`: URL of the debugger web interface
|
|
17
|
+
|
|
18
|
+
#### Enhanced `connect()` Method
|
|
19
|
+
- Automatically starts the debugger server when connecting (unless in headless mode)
|
|
20
|
+
- Calls `_renderSandbox()` after successful connection to open the browser window
|
|
21
|
+
- Supports new `headless` option to disable browser rendering
|
|
22
|
+
|
|
23
|
+
#### New Methods
|
|
24
|
+
|
|
25
|
+
**`_renderSandbox(instance)`**
|
|
26
|
+
- Constructs the VNC URL from the sandbox instance details
|
|
27
|
+
- Creates encoded data payload for the debugger
|
|
28
|
+
- Emits the `show-window` event with the debugger URL
|
|
29
|
+
|
|
30
|
+
**`_openBrowser(url)`**
|
|
31
|
+
- Uses the `open` npm package to launch the default browser
|
|
32
|
+
- Handles errors gracefully with fallback to manual URL copy
|
|
33
|
+
- Uses dynamic import for ES module compatibility
|
|
34
|
+
|
|
35
|
+
#### Enhanced `_setupLogging()` Method
|
|
36
|
+
- Added event listener for `show-window` events
|
|
37
|
+
- Automatically opens browser when event is emitted
|
|
38
|
+
- Respects CI mode (prints view-only URL instead of opening browser)
|
|
39
|
+
|
|
40
|
+
### 2. Documentation Updates
|
|
41
|
+
|
|
42
|
+
#### SDK README (`SDK_README.md`)
|
|
43
|
+
- Updated `connect()` method documentation
|
|
44
|
+
- Added `headless` parameter description
|
|
45
|
+
- Added note about automatic browser rendering behavior
|
|
46
|
+
- Provided examples for both headless and non-headless modes
|
|
47
|
+
|
|
48
|
+
### 3. Examples
|
|
49
|
+
|
|
50
|
+
#### `examples/sdk-with-browser.js`
|
|
51
|
+
- Demonstrates default behavior with browser rendering
|
|
52
|
+
- Shows how to use the SDK with visual feedback
|
|
53
|
+
- Includes detailed console output explaining what's happening
|
|
54
|
+
|
|
55
|
+
#### `examples/sdk-headless.js`
|
|
56
|
+
- Demonstrates headless mode for CI/CD environments
|
|
57
|
+
- Shows how to disable browser rendering
|
|
58
|
+
- Useful for automated testing scenarios
|
|
59
|
+
|
|
60
|
+
### 4. Tests
|
|
61
|
+
|
|
62
|
+
#### `testdriver/acceptance-sdk/sandbox-render.test.mjs`
|
|
63
|
+
- Verifies that the `show-window` event is emitted
|
|
64
|
+
- Tests basic interaction with the rendered sandbox
|
|
65
|
+
- Includes timeout handling for sandbox creation
|
|
66
|
+
|
|
67
|
+
## How It Works
|
|
68
|
+
|
|
69
|
+
1. **Connection Phase**
|
|
70
|
+
- When `connect()` is called without `headless: true`
|
|
71
|
+
- The debugger server is started on port 3000 (by default)
|
|
72
|
+
- The sandbox is created/connected as usual
|
|
73
|
+
|
|
74
|
+
2. **Rendering Phase**
|
|
75
|
+
- After successful connection, `_renderSandbox()` is called
|
|
76
|
+
- It constructs the VNC URL: `http://{instance.ip}:{vncPort}/vnc_lite.html?token=V3b8wG9`
|
|
77
|
+
- Creates data payload with resolution, URL, and token
|
|
78
|
+
- Builds debugger URL: `{debuggerUrl}?data={encodedData}`
|
|
79
|
+
|
|
80
|
+
3. **Browser Opening**
|
|
81
|
+
- The `show-window` event is emitted with the debugger URL
|
|
82
|
+
- The event listener in `_setupLogging()` catches it
|
|
83
|
+
- The `_openBrowser()` method is called
|
|
84
|
+
- Default browser opens to the debugger interface
|
|
85
|
+
- User can watch live test execution
|
|
86
|
+
|
|
87
|
+
## Usage Examples
|
|
88
|
+
|
|
89
|
+
### Default Behavior (Browser Opens)
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
const TestDriver = require('testdriverai');
|
|
93
|
+
|
|
94
|
+
const client = new TestDriver(process.env.TD_API_KEY, {
|
|
95
|
+
logging: true
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
await client.auth();
|
|
99
|
+
await client.connect(); // Browser opens automatically
|
|
100
|
+
|
|
101
|
+
await client.hoverText('Submit');
|
|
102
|
+
await client.click();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Headless Mode (No Browser)
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
const TestDriver = require('testdriverai');
|
|
109
|
+
|
|
110
|
+
const client = new TestDriver(process.env.TD_API_KEY, {
|
|
111
|
+
logging: true
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
await client.auth();
|
|
115
|
+
await client.connect({ headless: true }); // No browser
|
|
116
|
+
|
|
117
|
+
await client.hoverText('Submit');
|
|
118
|
+
await client.click();
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### CI/CD Mode
|
|
122
|
+
|
|
123
|
+
When `CI` environment variable is set or `config.CI` is true, the SDK will:
|
|
124
|
+
- Print the view-only URL instead of opening a browser
|
|
125
|
+
- Allow monitoring without interrupting the test flow
|
|
126
|
+
|
|
127
|
+
## Benefits
|
|
128
|
+
|
|
129
|
+
1. **Visual Feedback**: Developers can watch tests execute in real-time
|
|
130
|
+
2. **Debugging**: Easier to understand test failures by seeing what's happening
|
|
131
|
+
3. **Consistency**: Matches the behavior of the CLI tool
|
|
132
|
+
4. **Flexibility**: Can be disabled for CI/CD with `headless: true`
|
|
133
|
+
5. **No Code Changes**: Existing SDK code continues to work (default behavior adds browser)
|
|
134
|
+
|
|
135
|
+
## Compatibility
|
|
136
|
+
|
|
137
|
+
- Works on macOS, Linux, and Windows
|
|
138
|
+
- Requires the `open` npm package (already a dependency)
|
|
139
|
+
- Debugger server starts automatically when needed
|
|
140
|
+
- Falls back gracefully if browser can't be opened (prints URL)
|
|
141
|
+
|
|
142
|
+
## Testing
|
|
143
|
+
|
|
144
|
+
Run the test to verify functionality:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
TD_API_KEY=your_key vitest run testdriver/acceptance-sdk/sandbox-render.test.mjs
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Or try the examples:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# With browser rendering
|
|
154
|
+
TD_API_KEY=your_key node examples/sdk-with-browser.js
|
|
155
|
+
|
|
156
|
+
# Headless mode
|
|
157
|
+
TD_API_KEY=your_key node examples/sdk-headless.js
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Future Enhancements
|
|
161
|
+
|
|
162
|
+
Potential improvements:
|
|
163
|
+
- Allow custom debugger port configuration
|
|
164
|
+
- Support for multiple concurrent sandbox windows
|
|
165
|
+
- Option to disable debugger server entirely
|
|
166
|
+
- Custom browser selection
|
|
167
|
+
- Headless mode detection based on environment
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
# TestDriver SDK Migration Guide
|
|
2
|
+
|
|
3
|
+
## New Element Finding API
|
|
4
|
+
|
|
5
|
+
We've introduced a new, more flexible API for finding and interacting with elements. The new `find()` API provides better control and enables polling patterns for dynamic content.
|
|
6
|
+
|
|
7
|
+
## Quick Comparison
|
|
8
|
+
|
|
9
|
+
### Old API (Deprecated)
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
// Find and click text
|
|
13
|
+
await client.hoverText("Sign In", "black button below password", "click");
|
|
14
|
+
|
|
15
|
+
// Wait for text to appear
|
|
16
|
+
await client.waitForText("Login button", 10000);
|
|
17
|
+
|
|
18
|
+
// Find and click image
|
|
19
|
+
await client.hoverImage("submit button icon", "click");
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### New API (Recommended)
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
// Find and click text or image
|
|
26
|
+
const element = await client
|
|
27
|
+
.find("Sign In, black button below password")
|
|
28
|
+
.find();
|
|
29
|
+
await element.click();
|
|
30
|
+
|
|
31
|
+
// Poll until element appears (replaces waitForText/waitForImage)
|
|
32
|
+
let element = client.find("login button");
|
|
33
|
+
while (!element.found()) {
|
|
34
|
+
console.log("waiting for element to be found");
|
|
35
|
+
element = await element.find();
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
37
|
+
}
|
|
38
|
+
await element.click();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Migration Examples
|
|
42
|
+
|
|
43
|
+
### Example 1: Simple Click
|
|
44
|
+
|
|
45
|
+
**Before:**
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
await client.hoverText("Submit", "submit button", "click");
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**After:**
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
const submitBtn = await client.find("Submit button");
|
|
55
|
+
await submitBtn.click();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Example 2: Waiting for Elements
|
|
59
|
+
|
|
60
|
+
**Before:**
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
await client.waitForText("Welcome", 10000);
|
|
64
|
+
await client.hoverText("Welcome", null, "click");
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**After:**
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
let element;
|
|
71
|
+
const maxAttempts = 10;
|
|
72
|
+
let attempts = 0;
|
|
73
|
+
|
|
74
|
+
while (!element?.found() && attempts < maxAttempts) {
|
|
75
|
+
element = await client.find("Welcome");
|
|
76
|
+
if (!element.found()) {
|
|
77
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
78
|
+
}
|
|
79
|
+
attempts++;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (element?.found()) {
|
|
83
|
+
await element.click();
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Example 3: Hover Actions
|
|
88
|
+
|
|
89
|
+
**Before:**
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
await client.hoverText("Menu", null, "hover");
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**After:**
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const menu = await client.find("Menu").find();
|
|
99
|
+
await menu.hover();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Example 4: Different Click Types
|
|
103
|
+
|
|
104
|
+
**Before:**
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
await client.hoverText("File", null, "right-click");
|
|
108
|
+
await client.hoverText("Save", null, "double-click");
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**After:**
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
const file = await client.find("File").find();
|
|
115
|
+
await file.rightClick();
|
|
116
|
+
|
|
117
|
+
const save = await client.find("Save").find();
|
|
118
|
+
await save.doubleClick();
|
|
119
|
+
|
|
120
|
+
// Or use the generic click() method
|
|
121
|
+
await file.click("right-click");
|
|
122
|
+
await save.click("double-click");
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Example 5: Conditional Logic
|
|
126
|
+
|
|
127
|
+
**Before:**
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
try {
|
|
131
|
+
await client.waitForText("Error message", 2000);
|
|
132
|
+
// Handle error
|
|
133
|
+
} catch (e) {
|
|
134
|
+
// No error present
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**After:**
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
const errorMsg = await client.find("Error message").find();
|
|
142
|
+
if (errorMsg.found()) {
|
|
143
|
+
// Handle error
|
|
144
|
+
console.log("Error found at:", errorMsg.getCoordinates());
|
|
145
|
+
} else {
|
|
146
|
+
// No error present
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## New Element API Reference
|
|
151
|
+
|
|
152
|
+
### `client.find(description)`
|
|
153
|
+
|
|
154
|
+
Creates an Element instance for finding and interacting with elements.
|
|
155
|
+
|
|
156
|
+
**Parameters:**
|
|
157
|
+
|
|
158
|
+
- `description` (string): Natural language description of the element
|
|
159
|
+
|
|
160
|
+
**Returns:** `Element` instance
|
|
161
|
+
|
|
162
|
+
**Example:**
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
const button = client.find("the sign in button");
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `element.find([newDescription])`
|
|
169
|
+
|
|
170
|
+
Attempts to locate the element on screen.
|
|
171
|
+
|
|
172
|
+
**Parameters:**
|
|
173
|
+
|
|
174
|
+
- `newDescription` (optional string): New description to search for
|
|
175
|
+
|
|
176
|
+
**Returns:** `Promise<Element>` - The same Element instance (for chaining)
|
|
177
|
+
|
|
178
|
+
**Example:**
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
const element = await client.find("login button").find();
|
|
182
|
+
|
|
183
|
+
// Or with a new description
|
|
184
|
+
element = await element.find("sign in button");
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### `element.found()`
|
|
188
|
+
|
|
189
|
+
Check if the element was successfully located.
|
|
190
|
+
|
|
191
|
+
**Returns:** `boolean` - true if element coordinates were found
|
|
192
|
+
|
|
193
|
+
**Example:**
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
const element = await client.find("button").find();
|
|
197
|
+
if (element.found()) {
|
|
198
|
+
console.log("Element found!");
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### `element.click([action])`
|
|
203
|
+
|
|
204
|
+
Click on the element.
|
|
205
|
+
|
|
206
|
+
**Parameters:**
|
|
207
|
+
|
|
208
|
+
- `action` (optional): Click action type - `'click'`, `'right-click'`, `'double-click'`
|
|
209
|
+
|
|
210
|
+
**Returns:** `Promise<void>`
|
|
211
|
+
|
|
212
|
+
**Example:**
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
await element.click();
|
|
216
|
+
await element.click("right-click");
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### `element.hover()`
|
|
220
|
+
|
|
221
|
+
Hover over the element.
|
|
222
|
+
|
|
223
|
+
**Returns:** `Promise<void>`
|
|
224
|
+
|
|
225
|
+
**Example:**
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
await element.hover();
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### `element.doubleClick()`
|
|
232
|
+
|
|
233
|
+
Double-click on the element. Convenience method for `element.click('double-click')`.
|
|
234
|
+
|
|
235
|
+
**Returns:** `Promise<void>`
|
|
236
|
+
|
|
237
|
+
**Example:**
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
await element.doubleClick();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### `element.rightClick()`
|
|
244
|
+
|
|
245
|
+
Right-click on the element. Convenience method for `element.click('right-click')`.
|
|
246
|
+
|
|
247
|
+
**Returns:** `Promise<void>`
|
|
248
|
+
|
|
249
|
+
**Example:**
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
await element.rightClick();
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### `element.mouseDown()`
|
|
256
|
+
|
|
257
|
+
Press mouse button down on this element (useful for drag operations).
|
|
258
|
+
|
|
259
|
+
**Returns:** `Promise<void>`
|
|
260
|
+
|
|
261
|
+
**Example:**
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
const source = await client.find("draggable item").find();
|
|
265
|
+
await source.mouseDown();
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### `element.mouseUp()`
|
|
269
|
+
|
|
270
|
+
Release mouse button on this element (useful for drag operations).
|
|
271
|
+
|
|
272
|
+
**Returns:** `Promise<void>`
|
|
273
|
+
|
|
274
|
+
**Example:**
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
const target = await client.find("drop zone").find();
|
|
278
|
+
await target.mouseUp();
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### `element.getCoordinates()`
|
|
282
|
+
|
|
283
|
+
Get the screen coordinates of the element.
|
|
284
|
+
|
|
285
|
+
**Returns:** `{x, y, centerX, centerY}` or `null` if not found
|
|
286
|
+
|
|
287
|
+
**Example:**
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
const coords = element.getCoordinates();
|
|
291
|
+
if (coords) {
|
|
292
|
+
console.log(`Element at: ${coords.x}, ${coords.y}`);
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### `element.getResponse()`
|
|
297
|
+
|
|
298
|
+
Get the full API response data from the locate operation.
|
|
299
|
+
|
|
300
|
+
**Returns:** `Object | null` - Full response containing all available data
|
|
301
|
+
|
|
302
|
+
**Example:**
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
const response = element.getResponse();
|
|
306
|
+
console.log("Full response:", response);
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Element Properties
|
|
310
|
+
|
|
311
|
+
The Element class exposes many properties from the API response:
|
|
312
|
+
|
|
313
|
+
### Coordinate Properties
|
|
314
|
+
|
|
315
|
+
- `element.x` - X coordinate (top-left corner)
|
|
316
|
+
- `element.y` - Y coordinate (top-left corner)
|
|
317
|
+
- `element.centerX` - X coordinate of element center
|
|
318
|
+
- `element.centerY` - Y coordinate of element center
|
|
319
|
+
|
|
320
|
+
### Dimension Properties
|
|
321
|
+
|
|
322
|
+
- `element.width` - Width of the element (if available)
|
|
323
|
+
- `element.height` - Height of the element (if available)
|
|
324
|
+
- `element.boundingBox` - Bounding box data (if available)
|
|
325
|
+
|
|
326
|
+
### Match Quality Properties
|
|
327
|
+
|
|
328
|
+
- `element.confidence` - Confidence score of the match (0-1)
|
|
329
|
+
- `element.screenshot` - Base64 encoded screenshot of the element
|
|
330
|
+
- `element.text` - Text content of the element (if available)
|
|
331
|
+
- `element.label` - Label/aria-label of the element (if available)
|
|
332
|
+
|
|
333
|
+
### Example Usage
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
const button = await client.find("login button");
|
|
337
|
+
|
|
338
|
+
if (button.found()) {
|
|
339
|
+
console.log("Position:", { x: button.x, y: button.y });
|
|
340
|
+
console.log("Center:", { x: button.centerX, y: button.centerY });
|
|
341
|
+
console.log("Size:", { width: button.width, height: button.height });
|
|
342
|
+
console.log("Confidence:", button.confidence);
|
|
343
|
+
console.log("Text:", button.text);
|
|
344
|
+
|
|
345
|
+
// Save screenshot for debugging
|
|
346
|
+
if (button.screenshot) {
|
|
347
|
+
const fs = require("fs");
|
|
348
|
+
fs.writeFileSync("button.png", Buffer.from(button.screenshot, "base64"));
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Conditional actions based on properties
|
|
352
|
+
if (button.confidence > 0.8) {
|
|
353
|
+
await button.click();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
For a complete example, see `examples/sdk-element-properties.js`.
|
|
359
|
+
|
|
360
|
+
## Common Patterns
|
|
361
|
+
|
|
362
|
+
### Pattern 1: Find and Click
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
const element = await client.find("description").find();
|
|
366
|
+
if (element.found()) {
|
|
367
|
+
await element.click();
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Pattern 2: Polling with Timeout
|
|
372
|
+
|
|
373
|
+
```javascript
|
|
374
|
+
const element = client.find("element description");
|
|
375
|
+
const timeoutMs = 10000;
|
|
376
|
+
const startTime = Date.now();
|
|
377
|
+
|
|
378
|
+
while (!element.found() && Date.now() - startTime < timeoutMs) {
|
|
379
|
+
element = await element.find();
|
|
380
|
+
if (!element.found()) {
|
|
381
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (!element.found()) {
|
|
386
|
+
throw new Error("Element not found within timeout");
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Pattern 3: Retry with Different Descriptions
|
|
391
|
+
|
|
392
|
+
```javascript
|
|
393
|
+
let element = client.find("primary button");
|
|
394
|
+
element = await element.find();
|
|
395
|
+
|
|
396
|
+
if (!element.found()) {
|
|
397
|
+
element = await element.find("submit button");
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (!element.found()) {
|
|
401
|
+
element = await element.find("blue button on the right");
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (element.found()) {
|
|
405
|
+
await element.click();
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Pattern 4: Helper Function for Waiting
|
|
410
|
+
|
|
411
|
+
```javascript
|
|
412
|
+
async function waitForElement(client, description, timeoutMs = 10000) {
|
|
413
|
+
const element = client.find(description);
|
|
414
|
+
const startTime = Date.now();
|
|
415
|
+
|
|
416
|
+
while (!element.found() && Date.now() - startTime < timeoutMs) {
|
|
417
|
+
await element.find();
|
|
418
|
+
if (!element.found()) {
|
|
419
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (!element.found()) {
|
|
424
|
+
throw new Error(`Element "${description}" not found within ${timeoutMs}ms`);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return element;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Usage
|
|
431
|
+
const button = await waitForElement(client, "login button", 5000);
|
|
432
|
+
await button.click();
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Deprecated Methods
|
|
436
|
+
|
|
437
|
+
The following methods are now deprecated and will be removed in a future version:
|
|
438
|
+
|
|
439
|
+
- ❌ `client.hoverText()` → ✅ Use `client.find().find()` + `element.click()`
|
|
440
|
+
- ❌ `client.hoverImage()` → ✅ Use `client.find().find()` + `element.click()`
|
|
441
|
+
- ❌ `client.waitForText()` → ✅ Use polling pattern with `client.find()`
|
|
442
|
+
- ❌ `client.waitForImage()` → ✅ Use polling pattern with `client.find()`
|
|
443
|
+
- ❌ `client.wait()` → ✅ Use element polling instead of arbitrary waits when possible
|
|
444
|
+
|
|
445
|
+
## Benefits of the New API
|
|
446
|
+
|
|
447
|
+
1. **More Explicit**: Clear separation between finding and interacting
|
|
448
|
+
2. **Better Error Handling**: Can check if element exists before interacting
|
|
449
|
+
3. **Flexible Polling**: Custom polling logic for dynamic content
|
|
450
|
+
4. **Unified Interface**: Same API for text and images
|
|
451
|
+
5. **More Control**: Access to element state and coordinates
|
|
452
|
+
6. **Composable**: Element instances can be stored and reused
|
|
453
|
+
|
|
454
|
+
## TypeScript Support
|
|
455
|
+
|
|
456
|
+
The new API is fully typed:
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
import TestDriver, { Element } from "testdriverai";
|
|
460
|
+
|
|
461
|
+
const client = new TestDriver(process.env.TD_API_KEY);
|
|
462
|
+
await client.connect();
|
|
463
|
+
|
|
464
|
+
const element: Element = await client.find("button").find();
|
|
465
|
+
const found: boolean = element.found();
|
|
466
|
+
const coords = element.getCoordinates(); // {x, y, centerX, centerY} | null
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Questions?
|
|
470
|
+
|
|
471
|
+
For more examples, see:
|
|
472
|
+
|
|
473
|
+
- `examples/sdk-find-example.js` - Comprehensive examples of the new API
|
|
474
|
+
- `testdriver/acceptance-sdk/hover-text.test.mjs` - Updated test example
|