@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,266 @@
|
|
|
1
|
+
# GitHub Integration Setup
|
|
2
|
+
|
|
3
|
+
TestDriver automatically posts beautiful test result comments to GitHub Pull Requests, including:
|
|
4
|
+
- ✅ Test results summary with pass/fail counts
|
|
5
|
+
- 🎥 Dashcam GIF replays embedded directly in comments
|
|
6
|
+
- 📊 Detailed test statistics and duration
|
|
7
|
+
- 🔴 Exception details with stack traces
|
|
8
|
+
- 📋 Links to full test runs
|
|
9
|
+
|
|
10
|
+
This guide explains how to configure GitHub authentication so TestDriver can post these comments.
|
|
11
|
+
|
|
12
|
+
## How It Works
|
|
13
|
+
|
|
14
|
+
TestDriver's Vitest plugin automatically detects GitHub context and posts comments when tests complete. Here's what it needs:
|
|
15
|
+
|
|
16
|
+
### Required Environment Variables
|
|
17
|
+
|
|
18
|
+
1. **GITHUB_TOKEN** or **GH_TOKEN** - GitHub Personal Access Token for authentication
|
|
19
|
+
2. **GITHUB_REPOSITORY** - Repository in `owner/repo` format (auto-detected in GitHub Actions)
|
|
20
|
+
3. **GITHUB_PR_NUMBER** - Pull Request number (auto-detected in GitHub Actions)
|
|
21
|
+
4. **GITHUB_SHA** - Commit SHA (optional, auto-detected in GitHub Actions)
|
|
22
|
+
|
|
23
|
+
### Auto-Detection in GitHub Actions
|
|
24
|
+
|
|
25
|
+
When running in GitHub Actions, most variables are automatically available:
|
|
26
|
+
- `GITHUB_REPOSITORY` - Set automatically
|
|
27
|
+
- `GITHUB_SHA` - Set automatically
|
|
28
|
+
- `GITHUB_REF` - Used to detect PR number
|
|
29
|
+
- Pull request info extracted from event data
|
|
30
|
+
|
|
31
|
+
You only need to configure the token permissions!
|
|
32
|
+
|
|
33
|
+
### Method 1: GitHub Actions (Recommended)
|
|
34
|
+
|
|
35
|
+
GitHub Actions provides automatic authentication. TestDriver will detect the context automatically.
|
|
36
|
+
|
|
37
|
+
**Required Permissions:**
|
|
38
|
+
|
|
39
|
+
In your workflow file, use the built-in `GITHUB_TOKEN` with write permissions:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
name: TestDriver Tests
|
|
43
|
+
|
|
44
|
+
on:
|
|
45
|
+
pull_request:
|
|
46
|
+
types: [opened, synchronize]
|
|
47
|
+
|
|
48
|
+
jobs:
|
|
49
|
+
test:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
permissions:
|
|
52
|
+
contents: read
|
|
53
|
+
pull-requests: write # Required to post comments
|
|
54
|
+
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- name: Setup Node.js
|
|
59
|
+
uses: actions/setup-node@v4
|
|
60
|
+
with:
|
|
61
|
+
node-version: '20'
|
|
62
|
+
|
|
63
|
+
- name: Install dependencies
|
|
64
|
+
run: npm ci
|
|
65
|
+
|
|
66
|
+
- name: Run TestDriver tests
|
|
67
|
+
env:
|
|
68
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
69
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Automatically provided
|
|
70
|
+
run: vitest run
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**What happens automatically:**
|
|
74
|
+
- `GITHUB_TOKEN`: Provided by GitHub Actions
|
|
75
|
+
- `GITHUB_REPOSITORY`: Automatically set (e.g., `testdriverai/testdriverai`)
|
|
76
|
+
- `GITHUB_REF`: Automatically set (e.g., `refs/pull/123/merge`)
|
|
77
|
+
- PR number: Extracted automatically from `GITHUB_REF` or event data
|
|
78
|
+
|
|
79
|
+
### Method 2: Manual Setup (Local or Other CI)
|
|
80
|
+
|
|
81
|
+
For local development or other CI systems, set these environment variables:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# .env or export in your shell
|
|
85
|
+
GITHUB_TOKEN=ghp_your_personal_access_token_here
|
|
86
|
+
GITHUB_PR_NUMBER=123
|
|
87
|
+
# GITHUB_REPOSITORY is auto-detected from git if not set
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Creating a Personal Access Token:**
|
|
91
|
+
|
|
92
|
+
1. Go to [GitHub Settings → Developer settings → Personal access tokens](https://github.com/settings/tokens)
|
|
93
|
+
2. Click "Generate new token" → "Generate new token (classic)"
|
|
94
|
+
3. Give it a descriptive name (e.g., "TestDriver CI")
|
|
95
|
+
4. Select scopes:
|
|
96
|
+
- ✅ `repo` (Full control of private repositories)
|
|
97
|
+
- Or just ✅ `public_repo` (for public repositories only)
|
|
98
|
+
5. Click "Generate token"
|
|
99
|
+
6. Copy the token immediately (you won't see it again!)
|
|
100
|
+
7. Store it securely:
|
|
101
|
+
- **In GitHub Actions**: Add as repository secret (`Settings → Secrets and variables → Actions → New repository secret`)
|
|
102
|
+
- **Locally**: Add to `.env` file (and add `.env` to `.gitignore`!)
|
|
103
|
+
|
|
104
|
+
### Method 3: Other CI Systems
|
|
105
|
+
|
|
106
|
+
#### CircleCI
|
|
107
|
+
```yaml
|
|
108
|
+
environment:
|
|
109
|
+
GITHUB_TOKEN: $GITHUB_TOKEN
|
|
110
|
+
GITHUB_REPOSITORY: $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
|
|
111
|
+
GITHUB_PR_NUMBER: $CIRCLE_PR_NUMBER
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### GitLab CI
|
|
115
|
+
```yaml
|
|
116
|
+
variables:
|
|
117
|
+
GITHUB_TOKEN: $GITHUB_TOKEN
|
|
118
|
+
GITHUB_REPOSITORY: "your-org/your-repo"
|
|
119
|
+
GITHUB_PR_NUMBER: $CI_MERGE_REQUEST_IID
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### Jenkins
|
|
123
|
+
```groovy
|
|
124
|
+
environment {
|
|
125
|
+
GITHUB_TOKEN = credentials('github-token')
|
|
126
|
+
GITHUB_REPOSITORY = "${env.GITHUB_ORG}/${env.GITHUB_REPO}"
|
|
127
|
+
GITHUB_PR_NUMBER = "${env.CHANGE_ID}"
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Environment Variables Reference
|
|
132
|
+
|
|
133
|
+
| Variable | Priority | Description | Example | Source |
|
|
134
|
+
|----------|----------|-------------|---------|--------|
|
|
135
|
+
| `GITHUB_TOKEN` | 1 | GitHub personal access token | `ghp_abc...` | Auto-provided in GitHub Actions |
|
|
136
|
+
| `GH_TOKEN` | 2 | Alternative GitHub token | `ghp_xyz...` | Manual setup |
|
|
137
|
+
| `GITHUB_REPOSITORY` | - | Repository in `owner/repo` format | `testdriverai/testdriverai` | Auto-set in GitHub Actions |
|
|
138
|
+
| `GITHUB_PR_NUMBER` | - | Pull request number | `123` | Must be set manually or by CI |
|
|
139
|
+
| `GITHUB_SHA` | - | Commit SHA | `abc1234def...` | Auto-set in GitHub Actions |
|
|
140
|
+
| `TESTDRIVER_SKIP_GITHUB_COMMENT` | - | Disable comment posting | `true` | Set to skip comments |
|
|
141
|
+
|
|
142
|
+
**Note**: Git repository info (owner/repo, branch, commit) is auto-detected from your local `.git` directory if not provided via environment variables.
|
|
143
|
+
|
|
144
|
+
## Disabling GitHub Comments
|
|
145
|
+
|
|
146
|
+
To disable GitHub comments:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Method 1: Set environment variable
|
|
150
|
+
TESTDRIVER_SKIP_GITHUB_COMMENT=true npm run test
|
|
151
|
+
|
|
152
|
+
# Method 2: Remove/unset the GitHub token
|
|
153
|
+
unset GITHUB_TOKEN
|
|
154
|
+
unset GH_TOKEN
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
In GitHub Actions workflow:
|
|
158
|
+
```yaml
|
|
159
|
+
- name: Run tests without GitHub comments
|
|
160
|
+
env:
|
|
161
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
162
|
+
TESTDRIVER_SKIP_GITHUB_COMMENT: true
|
|
163
|
+
run: vitest run
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Troubleshooting
|
|
167
|
+
|
|
168
|
+
### "GitHub token not found, skipping comment posting"
|
|
169
|
+
|
|
170
|
+
Check that the token is set:
|
|
171
|
+
```bash
|
|
172
|
+
echo $GITHUB_TOKEN # or GH_TOKEN
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### "Neither PR number nor commit SHA found"
|
|
176
|
+
|
|
177
|
+
Set the PR number:
|
|
178
|
+
```bash
|
|
179
|
+
export GITHUB_PR_NUMBER=123
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Or ensure `GITHUB_SHA` is set (auto-set in GitHub Actions).
|
|
183
|
+
|
|
184
|
+
### "Repository info not available"
|
|
185
|
+
|
|
186
|
+
The plugin auto-detects repo info from your `.git` directory. If that fails, set:
|
|
187
|
+
```bash
|
|
188
|
+
export GITHUB_REPOSITORY=owner/repo
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### "Resource not accessible by integration"
|
|
192
|
+
|
|
193
|
+
Your token doesn't have `pull-requests: write` permission. Check:
|
|
194
|
+
- GitHub Actions: Add `permissions.pull-requests: write` to workflow
|
|
195
|
+
- Personal token: Ensure it has `repo` or `public_repo` scope
|
|
196
|
+
|
|
197
|
+
### "Not Found" or "403 Forbidden"
|
|
198
|
+
|
|
199
|
+
- Token doesn't have access to the repository
|
|
200
|
+
- Repository name format is incorrect (must be `owner/repo`)
|
|
201
|
+
- PR number is invalid
|
|
202
|
+
|
|
203
|
+
### Comments not appearing
|
|
204
|
+
|
|
205
|
+
- Check that tests are running in the context of a pull request
|
|
206
|
+
- Verify the token has write access
|
|
207
|
+
- Look for error messages in the test output
|
|
208
|
+
- Run with `DEBUG=testdriver:github` for verbose logging
|
|
209
|
+
|
|
210
|
+
## Security Best Practices
|
|
211
|
+
|
|
212
|
+
1. **Never commit tokens** to git repositories
|
|
213
|
+
2. **Use GitHub Actions secrets** for CI/CD
|
|
214
|
+
3. **Use fine-grained tokens** with minimum required permissions
|
|
215
|
+
4. **Rotate tokens regularly** (at least every 90 days)
|
|
216
|
+
5. **Revoke tokens** immediately if compromised
|
|
217
|
+
6. **Use organization secrets** for shared tokens across repos
|
|
218
|
+
|
|
219
|
+
## Example Comment Output
|
|
220
|
+
|
|
221
|
+
When properly configured, TestDriver will post comments like:
|
|
222
|
+
|
|
223
|
+
```markdown
|
|
224
|
+
# 🟢 TestDriver Test Results
|
|
225
|
+
|
|
226
|
+
**Status:** ✅ PASSED
|
|
227
|
+
**Duration:** 45.23s
|
|
228
|
+
**Platform:** linux
|
|
229
|
+
**Branch:** `feature/new-login`
|
|
230
|
+
**Commit:** `abc1234`
|
|
231
|
+
|
|
232
|
+
## 📊 Test Summary
|
|
233
|
+
|
|
234
|
+
Total: 3
|
|
235
|
+
Passed: 3 ✅
|
|
236
|
+
Failed: 0 ❌
|
|
237
|
+
Skipped: 0 ⏭️
|
|
238
|
+
|
|
239
|
+
### [📋 View Full Test Run](https://app.testdriver.ai/runs/...)
|
|
240
|
+
|
|
241
|
+
## 📝 Test Results
|
|
242
|
+
|
|
243
|
+
| Status | Test | File | Duration | Replay |
|
|
244
|
+
|--------|------|------|----------|--------|
|
|
245
|
+
| ✅ | should log in successfully | `login.test.mjs` | 12.34s | [🎥 View](https://app.testdriver.ai/replay/...) |
|
|
246
|
+
| ✅ | should navigate to dashboard | `navigation.test.mjs` | 8.91s | [🎥 View](https://app.testdriver.ai/replay/...) |
|
|
247
|
+
|
|
248
|
+
## 🎥 Dashcam Replays
|
|
249
|
+
|
|
250
|
+
### should log in successfully
|
|
251
|
+
|
|
252
|
+
[](https://app.testdriver.ai/replay/...)
|
|
253
|
+
|
|
254
|
+
[🎬 View Full Replay](https://app.testdriver.ai/replay/...)
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
<sub>Generated by [TestDriver](https://testdriver.ai) • Run ID: `run_abc123`</sub>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The GIF replays are automatically embedded so reviewers can see what happened without leaving GitHub!
|
|
261
|
+
|
|
262
|
+
## Getting Help
|
|
263
|
+
|
|
264
|
+
- 📚 [Full Documentation](https://docs.testdriver.ai)
|
|
265
|
+
- 💬 [Discord Community](https://discord.gg/testdriver)
|
|
266
|
+
- 🐛 [Report Issues](https://github.com/testdriverai/testdriverai/issues)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Best Practices: Element Polling
|
|
2
|
+
|
|
3
|
+
**When waiting for elements to appear, prefer `find()` with a `timeout` option over `wait()`.**
|
|
4
|
+
|
|
5
|
+
## When to Use `wait()` vs `find()` with Timeout
|
|
6
|
+
|
|
7
|
+
`wait()` is useful for **simple pauses** — after actions, for animations, or for state changes to settle:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
await testdriver.find('submit button').click();
|
|
11
|
+
await testdriver.wait(2000); // Wait for animation to complete
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
However, **don't use `wait()` to wait for elements to appear**. For that, use `find()` with a `timeout`:
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
// ✅ GOOD: Polls until the element appears (up to 30s)
|
|
18
|
+
const element = await testdriver.find('success message', { timeout: 30000 });
|
|
19
|
+
|
|
20
|
+
// ❌ BAD: Arbitrary wait then hope the element is there
|
|
21
|
+
await testdriver.wait(5000);
|
|
22
|
+
const element = await testdriver.find('success message');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Why Prefer `find()` with Timeout for Element Waiting?
|
|
26
|
+
|
|
27
|
+
Using arbitrary waits for element detection has problems:
|
|
28
|
+
|
|
29
|
+
1. **Brittle**: Fixed timeouts may be too short (causing flaky tests) or too long (wasting time)
|
|
30
|
+
2. **Slow**: You always wait the full duration, even if the element appears sooner
|
|
31
|
+
3. **Unreliable**: Network conditions, system load, and other factors affect timing
|
|
32
|
+
4. **Hard to debug**: When tests fail, you don't know if it was a timing issue or actual failure
|
|
33
|
+
|
|
34
|
+
## The Right Way: Element Polling with `find()`
|
|
35
|
+
|
|
36
|
+
TestDriver's `find()` method is designed for element detection. Use it in a polling loop to wait for elements:
|
|
37
|
+
|
|
38
|
+
### Basic Polling Pattern
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
// ❌ WRONG: Using wait()
|
|
42
|
+
await testdriver.wait(2000);
|
|
43
|
+
const button = await testdriver.find("Submit button");
|
|
44
|
+
|
|
45
|
+
// ✅ CORRECT: Polling with find()
|
|
46
|
+
let button;
|
|
47
|
+
for (let i = 0; i < 10; i++) {
|
|
48
|
+
try {
|
|
49
|
+
button = await testdriver.find("Submit button");
|
|
50
|
+
if (button.found()) break;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
if (i === 9) throw e; // Re-throw on last attempt
|
|
53
|
+
}
|
|
54
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Helper Function for Polling
|
|
59
|
+
|
|
60
|
+
Create a reusable helper function:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
async function waitForElement(testdriver, description, maxAttempts = 10, delayMs = 1000) {
|
|
64
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
65
|
+
try {
|
|
66
|
+
const element = await testdriver.find(description);
|
|
67
|
+
if (element.found()) {
|
|
68
|
+
return element;
|
|
69
|
+
}
|
|
70
|
+
} catch (e) {
|
|
71
|
+
if (i === maxAttempts - 1) throw e;
|
|
72
|
+
}
|
|
73
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Element not found after ${maxAttempts} attempts: ${description}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Usage
|
|
79
|
+
const emailField = await waitForElement(testdriver, "Email input field");
|
|
80
|
+
await emailField.click();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## When to Use Polling
|
|
84
|
+
|
|
85
|
+
Use element polling in these scenarios:
|
|
86
|
+
|
|
87
|
+
- **After navigation**: Waiting for a new page to load
|
|
88
|
+
- **After user action**: Waiting for UI updates (form submission, modal opening, etc.)
|
|
89
|
+
- **Dynamic content**: Waiting for AJAX-loaded elements
|
|
90
|
+
- **State transitions**: Waiting for loading spinners to disappear or success messages to appear
|
|
91
|
+
|
|
92
|
+
## Example: Complete Login Flow
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
import { chrome } from "testdriverai/presets";
|
|
96
|
+
|
|
97
|
+
// Helper function
|
|
98
|
+
async function waitForElement(testdriver, description, maxAttempts = 10, delayMs = 1000) {
|
|
99
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
100
|
+
try {
|
|
101
|
+
const element = await testdriver.find(description);
|
|
102
|
+
if (element.found()) return element;
|
|
103
|
+
} catch (e) {
|
|
104
|
+
if (i === maxAttempts - 1) throw e;
|
|
105
|
+
}
|
|
106
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
107
|
+
}
|
|
108
|
+
throw new Error(`Element not found after ${maxAttempts} attempts: ${description}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
it("should log in successfully", async (context) => {
|
|
112
|
+
const { testdriver } = await chrome(context, {
|
|
113
|
+
url: 'https://example.com/login',
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Wait for login page to load
|
|
117
|
+
const emailField = await waitForElement(testdriver, "Email input field");
|
|
118
|
+
await emailField.click();
|
|
119
|
+
await testdriver.type("user@example.com");
|
|
120
|
+
|
|
121
|
+
const passwordField = await testdriver.find("Password input field");
|
|
122
|
+
await passwordField.click();
|
|
123
|
+
await testdriver.type("password123");
|
|
124
|
+
|
|
125
|
+
const loginButton = await testdriver.find("Login button");
|
|
126
|
+
await loginButton.click();
|
|
127
|
+
|
|
128
|
+
// Wait for dashboard to load after login
|
|
129
|
+
await waitForElement(testdriver, "Dashboard welcome message");
|
|
130
|
+
|
|
131
|
+
// Verify login successful
|
|
132
|
+
const isLoggedIn = await testdriver.assert("user is logged in to dashboard");
|
|
133
|
+
expect(isLoggedIn).toBeTruthy();
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Advanced: Conditional Polling
|
|
138
|
+
|
|
139
|
+
For elements that may or may not appear (like dialogs or notifications):
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Try to find and dismiss optional dialog
|
|
143
|
+
try {
|
|
144
|
+
const dialog = await waitForElement(testdriver, "Cookie consent dialog", 3, 500);
|
|
145
|
+
const acceptButton = await testdriver.find("Accept button");
|
|
146
|
+
await acceptButton.click();
|
|
147
|
+
console.log("Dismissed cookie dialog");
|
|
148
|
+
} catch {
|
|
149
|
+
console.log("No cookie dialog found, continuing...");
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Configuration
|
|
154
|
+
|
|
155
|
+
Adjust polling parameters based on your needs:
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// Quick polling for fast UI updates (check every 300ms, up to 3 seconds)
|
|
159
|
+
await waitForElement(testdriver, "Success message", 10, 300);
|
|
160
|
+
|
|
161
|
+
// Patient polling for slow operations (check every 2s, up to 20 seconds)
|
|
162
|
+
await waitForElement(testdriver, "Processing complete indicator", 10, 2000);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Summary
|
|
166
|
+
|
|
167
|
+
| Pattern | Use Case |
|
|
168
|
+
|---------|----------|
|
|
169
|
+
| **Polling with `find()`** | ✅ Waiting for UI elements to appear or disappear |
|
|
170
|
+
| **`wait()`** | ✅ Simple delays (animations, state changes) — ❌ Don't use for element waiting |
|
|
171
|
+
| **Helper function** | ✅ Recommended for cleaner, reusable code |
|
|
172
|
+
| **Conditional polling** | ✅ For optional elements (dialogs, notifications) |
|
|
173
|
+
|
|
174
|
+
Remember: **If you're waiting for something to appear on screen, use `find()` with a `timeout` option, not `wait()`. Use `wait()` for simple pauses between actions.**
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|