@testdriverai/agent 7.8.0-test.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +7 -0
- package/.env.example +4 -0
- package/.prettierignore +4 -0
- package/.prettierrc +1 -0
- package/CHANGELOG.md +953 -0
- package/README.md +81 -0
- package/agent/events.js +135 -0
- package/agent/index.js +2450 -0
- package/agent/interface.js +35 -0
- package/agent/lib/analytics.js +22 -0
- package/agent/lib/censorship.js +75 -0
- package/agent/lib/commander.js +246 -0
- package/agent/lib/commands.js +1684 -0
- package/agent/lib/config.js +60 -0
- package/agent/lib/generator.js +91 -0
- package/agent/lib/http.js +144 -0
- package/agent/lib/logger.js +56 -0
- package/agent/lib/outputs.js +29 -0
- package/agent/lib/parser.js +209 -0
- package/agent/lib/redraw.js +386 -0
- package/agent/lib/resources/cursor-2.png +0 -0
- package/agent/lib/sandbox.js +1104 -0
- package/agent/lib/sdk.js +633 -0
- package/agent/lib/session.js +25 -0
- package/agent/lib/source-mapper.js +342 -0
- package/agent/lib/subimage/index.js +77 -0
- package/agent/lib/subimage/opencv.js +69 -0
- package/agent/lib/system.js +204 -0
- package/agent/lib/theme.js +14 -0
- package/agent/lib/valid-version.js +21 -0
- package/agent/lib/validation.js +169 -0
- package/ai/.claude-plugin/plugin.json +9 -0
- package/ai/agents/testdriver.md +638 -0
- package/ai/skills/testdriver-ai/SKILL.md +204 -0
- package/ai/skills/testdriver-assert/SKILL.md +315 -0
- package/ai/skills/testdriver-aws-setup/SKILL.md +448 -0
- package/ai/skills/testdriver-cache/SKILL.md +221 -0
- package/ai/skills/testdriver-caching/SKILL.md +124 -0
- package/ai/skills/testdriver-captcha/SKILL.md +158 -0
- package/ai/skills/testdriver-ci-cd/SKILL.md +602 -0
- package/ai/skills/testdriver-click/SKILL.md +286 -0
- package/ai/skills/testdriver-client/SKILL.md +477 -0
- package/ai/skills/testdriver-cloud/SKILL.md +119 -0
- package/ai/skills/testdriver-customizing-devices/SKILL.md +319 -0
- package/ai/skills/testdriver-dashcam/SKILL.md +418 -0
- package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +401 -0
- package/ai/skills/testdriver-device-config/SKILL.md +317 -0
- package/ai/skills/testdriver-double-click/SKILL.md +102 -0
- package/ai/skills/testdriver-elements/SKILL.md +605 -0
- package/ai/skills/testdriver-enterprise/SKILL.md +114 -0
- package/ai/skills/testdriver-errors/SKILL.md +246 -0
- package/ai/skills/testdriver-events/SKILL.md +356 -0
- package/ai/skills/testdriver-examples/SKILL.md +7 -0
- package/ai/skills/testdriver-exec/SKILL.md +317 -0
- package/ai/skills/testdriver-find/SKILL.md +829 -0
- package/ai/skills/testdriver-focus-application/SKILL.md +293 -0
- package/ai/skills/testdriver-generating-tests/SKILL.md +36 -0
- package/ai/skills/testdriver-hover/SKILL.md +278 -0
- package/ai/skills/testdriver-locating-elements/SKILL.md +71 -0
- package/ai/skills/testdriver-making-assertions/SKILL.md +32 -0
- package/ai/skills/testdriver-mcp/SKILL.md +7 -0
- package/ai/skills/testdriver-mcp-workflow/SKILL.md +410 -0
- package/ai/skills/testdriver-mouse-down/SKILL.md +161 -0
- package/ai/skills/testdriver-mouse-up/SKILL.md +164 -0
- package/ai/skills/testdriver-parse/SKILL.md +236 -0
- package/ai/skills/testdriver-performing-actions/SKILL.md +54 -0
- package/ai/skills/testdriver-press-keys/SKILL.md +348 -0
- package/ai/skills/testdriver-provision/SKILL.md +331 -0
- package/ai/skills/testdriver-quickstart/SKILL.md +144 -0
- package/ai/skills/testdriver-redraw/SKILL.md +214 -0
- package/ai/skills/testdriver-reusable-code/SKILL.md +249 -0
- package/ai/skills/testdriver-right-click/SKILL.md +123 -0
- package/ai/skills/testdriver-running-tests/SKILL.md +185 -0
- package/ai/skills/testdriver-screenshot/SKILL.md +248 -0
- package/ai/skills/testdriver-screenshots/SKILL.md +184 -0
- package/ai/skills/testdriver-scroll/SKILL.md +335 -0
- package/ai/skills/testdriver-secrets/SKILL.md +115 -0
- package/ai/skills/testdriver-self-hosted/SKILL.md +65 -0
- package/ai/skills/testdriver-test-writer/SKILL.md +448 -0
- package/ai/skills/testdriver-testdriver/SKILL.md +628 -0
- package/ai/skills/testdriver-testdriver-mechanic/SKILL.md +165 -0
- package/ai/skills/testdriver-type/SKILL.md +357 -0
- package/ai/skills/testdriver-variables/SKILL.md +111 -0
- package/ai/skills/testdriver-wait/SKILL.md +50 -0
- package/ai/skills/testdriver-waiting-for-elements/SKILL.md +90 -0
- package/ai/skills/testdriver-what-is-testdriver/SKILL.md +54 -0
- package/bin/testdriverai.js +22 -0
- package/debugger/bg.png +0 -0
- package/debugger/icon.png +0 -0
- package/debugger/index.html +469 -0
- package/debugger/td.png +0 -0
- package/debugger/tray-buffered.png +0 -0
- package/debugger/tray.png +0 -0
- package/docs/GITHUB_COMMENTS.md +330 -0
- package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
- package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
- package/docs/TEST-GITHUB-COMMENTS.md +129 -0
- package/docs/_data/examples-manifest.json +177 -0
- package/docs/_data/examples-manifest.schema.json +41 -0
- package/docs/_scripts/extract-example-urls.js +165 -0
- package/docs/_scripts/generate-examples.js +560 -0
- package/docs/_scripts/generate-skills.js +154 -0
- package/docs/_scripts/link-replacer.js +164 -0
- package/docs/_scripts/upload-docs-to-openai.js +284 -0
- package/docs/changelog.mdx +161 -0
- package/docs/claude-mcp-plugin.mdx +160 -0
- package/docs/docs.json +442 -0
- package/docs/github-integration-setup.md +266 -0
- package/docs/guide/best-practices-polling.mdx +174 -0
- package/docs/images/content/account/newprojectsettings.png +0 -0
- package/docs/images/content/account/projectpage.png +0 -0
- package/docs/images/content/account/projectreplays.png +0 -0
- package/docs/images/content/account/team-manage.png +0 -0
- package/docs/images/content/account/teampage.png +0 -0
- package/docs/images/content/extension/cursor.svg +1 -0
- package/docs/images/content/extension/vscode.svg +57 -0
- package/docs/images/content/extension/windsurf.svg +3 -0
- package/docs/images/content/parse/output.png +0 -0
- package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
- package/docs/images/content/side-by-side.png +0 -0
- package/docs/images/content/vscode/ide-full.png +0 -0
- package/docs/images/content/vscode/running.png +0 -0
- package/docs/images/content/vscode/v7-chat.png +0 -0
- package/docs/images/content/vscode/v7-choose-agent.png +0 -0
- package/docs/images/content/vscode/v7-full.png +0 -0
- package/docs/images/content/vscode/v7-onboarding.png +0 -0
- package/docs/images/content/vscode/vscode-2-assert.png +0 -0
- package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
- package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
- package/docs/images/content/vscode/vscode-file-creation.png +0 -0
- package/docs/images/content/vscode/vscode-install.png +0 -0
- package/docs/images/content/vscode/vscode-overview.png +0 -0
- package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
- package/docs/images/content/vscode/vscode-stopchat.png +0 -0
- package/docs/images/content/vscode/vscode-stoptest.png +0 -0
- package/docs/images/content/vscode/vscode-tdservice.png +0 -0
- package/docs/images/content/vscode/vscode-test-output.png +0 -0
- package/docs/images/content/vscode/vscode-testhistory.png +0 -0
- package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
- package/docs/images/content/vscode/vscode-testpane.png +0 -0
- package/docs/images/template/dark.png +0 -0
- package/docs/images/template/icon.png +0 -0
- package/docs/images/template/light.png +0 -0
- package/docs/snippets/calendar-link.mdx +4 -0
- package/docs/snippets/gitignore-warning.mdx +7 -0
- package/docs/snippets/lifecycle-warning.mdx +6 -0
- package/docs/snippets/test-prereqs.mdx +12 -0
- package/docs/snippets/tests/assert-replay.mdx +7 -0
- package/docs/snippets/tests/assert-yaml.mdx +8 -0
- package/docs/snippets/tests/exec-js-replay.mdx +7 -0
- package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
- package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
- package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
- package/docs/snippets/tests/hover-image-replay.mdx +7 -0
- package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
- package/docs/snippets/tests/hover-text-replay.mdx +7 -0
- package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
- package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
- package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
- package/docs/snippets/tests/match-image-replay.mdx +7 -0
- package/docs/snippets/tests/match-image-yaml.mdx +17 -0
- package/docs/snippets/tests/press-keys-replay.mdx +7 -0
- package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
- package/docs/snippets/tests/remember-replay.mdx +7 -0
- package/docs/snippets/tests/remember-yaml.mdx +28 -0
- package/docs/snippets/tests/scroll-replay.mdx +7 -0
- package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
- package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
- package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
- package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
- package/docs/snippets/tests/scroll-yaml.mdx +30 -0
- package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
- package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
- package/docs/snippets/tests/type-replay.mdx +7 -0
- package/docs/snippets/tests/type-yaml.mdx +28 -0
- package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
- package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
- package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
- package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
- package/docs/snippets/tests/wait-replay.mdx +7 -0
- package/docs/snippets/tests/wait-yaml.mdx +13 -0
- package/docs/styles.css +65 -0
- package/docs/v6/account/dashboard.mdx +16 -0
- package/docs/v6/account/enterprise.mdx +110 -0
- package/docs/v6/account/pricing.mdx +33 -0
- package/docs/v6/account/projects.mdx +33 -0
- package/docs/v6/account/team.mdx +35 -0
- package/docs/v6/action/ami.mdx +109 -0
- package/docs/v6/action/performance.mdx +105 -0
- package/docs/v6/action/secrets.mdx +93 -0
- package/docs/v6/apps/chrome-extensions.mdx +48 -0
- package/docs/v6/apps/desktop-apps.mdx +93 -0
- package/docs/v6/apps/mobile-apps.mdx +26 -0
- package/docs/v6/apps/static-websites.mdx +54 -0
- package/docs/v6/apps/tauri-apps.mdx +361 -0
- package/docs/v6/bugs/jira.mdx +232 -0
- package/docs/v6/cli/overview.mdx +66 -0
- package/docs/v6/commands/assert.mdx +45 -0
- package/docs/v6/commands/exec.mdx +276 -0
- package/docs/v6/commands/focus-application.mdx +44 -0
- package/docs/v6/commands/hover-image.mdx +69 -0
- package/docs/v6/commands/hover-text.mdx +47 -0
- package/docs/v6/commands/if.mdx +53 -0
- package/docs/v6/commands/match-image.mdx +67 -0
- package/docs/v6/commands/press-keys.mdx +87 -0
- package/docs/v6/commands/remember.mdx +49 -0
- package/docs/v6/commands/run.mdx +44 -0
- package/docs/v6/commands/scroll-until-image.mdx +66 -0
- package/docs/v6/commands/scroll-until-text.mdx +60 -0
- package/docs/v6/commands/scroll.mdx +69 -0
- package/docs/v6/commands/type.mdx +45 -0
- package/docs/v6/commands/wait-for-image.mdx +54 -0
- package/docs/v6/commands/wait-for-text.mdx +48 -0
- package/docs/v6/commands/wait.mdx +45 -0
- package/docs/v6/exporting/junit.mdx +218 -0
- package/docs/v6/exporting/playwright.mdx +197 -0
- package/docs/v6/features/auto-healing.mdx +144 -0
- package/docs/v6/features/generation.mdx +116 -0
- package/docs/v6/features/parallel-testing.mdx +151 -0
- package/docs/v6/features/reusable-snippets.mdx +131 -0
- package/docs/v6/features/selectorless.mdx +80 -0
- package/docs/v6/features/visual-assertions.mdx +139 -0
- package/docs/v6/getting-started/ci.mdx +146 -0
- package/docs/v6/getting-started/cli.mdx +91 -0
- package/docs/v6/getting-started/editing.mdx +100 -0
- package/docs/v6/getting-started/playwright.mdx +342 -0
- package/docs/v6/getting-started/running.mdx +48 -0
- package/docs/v6/getting-started/self-hosting.mdx +408 -0
- package/docs/v6/getting-started/vscode.mdx +88 -0
- package/docs/v6/guide/assertions.mdx +189 -0
- package/docs/v6/guide/authentication.mdx +136 -0
- package/docs/v6/guide/code.mdx +65 -0
- package/docs/v6/guide/dashcam.mdx +118 -0
- package/docs/v6/guide/environment-variables.mdx +26 -0
- package/docs/v6/guide/lifecycle.mdx +242 -0
- package/docs/v6/guide/locating.mdx +141 -0
- package/docs/v6/guide/protips.mdx +43 -0
- package/docs/v6/guide/variables.mdx +143 -0
- package/docs/v6/guide/waiting.mdx +130 -0
- package/docs/v6/importing/csv.mdx +196 -0
- package/docs/v6/importing/gherkin.mdx +143 -0
- package/docs/v6/importing/jira.mdx +164 -0
- package/docs/v6/importing/testrail.mdx +162 -0
- package/docs/v6/integrations/electron.mdx +146 -0
- package/docs/v6/integrations/netlify.mdx +100 -0
- package/docs/v6/integrations/vercel.mdx +125 -0
- package/docs/v6/interactive/explore.mdx +99 -0
- package/docs/v6/interactive/run.mdx +52 -0
- package/docs/v6/interactive/save.mdx +63 -0
- package/docs/v6/overview/comparison.mdx +101 -0
- package/docs/v6/overview/faq.mdx +162 -0
- package/docs/v6/overview/performance.mdx +52 -0
- package/docs/v6/overview/quickstart.mdx +137 -0
- package/docs/v6/overview/what-is-testdriver.mdx +85 -0
- package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
- package/docs/v6/scenarios/cookie-banner.mdx +32 -0
- package/docs/v6/scenarios/file-upload.mdx +33 -0
- package/docs/v6/scenarios/form-filling.mdx +32 -0
- package/docs/v6/scenarios/log-in.mdx +75 -0
- package/docs/v6/scenarios/pdf-generation.mdx +25 -0
- package/docs/v6/scenarios/spell-check.mdx +22 -0
- package/docs/v6/security/action.mdx +84 -0
- package/docs/v6/security/agent.mdx +73 -0
- package/docs/v6/security/platform.mdx +77 -0
- package/docs/v6/tutorials/advanced-test.mdx +81 -0
- package/docs/v6/tutorials/basic-test.mdx +45 -0
- package/docs/v7/_drafts/agents.mdx +843 -0
- package/docs/v7/_drafts/architecture.mdx +399 -0
- package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
- package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
- package/docs/v7/_drafts/best-practices.mdx +486 -0
- package/docs/v7/_drafts/caching-ai.mdx +215 -0
- package/docs/v7/_drafts/caching-selectors.mdx +424 -0
- package/docs/v7/_drafts/caching.mdx +366 -0
- package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
- package/docs/v7/_drafts/commands/assert.mdx +45 -0
- package/docs/v7/_drafts/commands/exec.mdx +276 -0
- package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
- package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
- package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
- package/docs/v7/_drafts/commands/if.mdx +53 -0
- package/docs/v7/_drafts/commands/match-image.mdx +67 -0
- package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
- package/docs/v7/_drafts/commands/remember.mdx +49 -0
- package/docs/v7/_drafts/commands/run.mdx +44 -0
- package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
- package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
- package/docs/v7/_drafts/commands/scroll.mdx +69 -0
- package/docs/v7/_drafts/commands/type.mdx +45 -0
- package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
- package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
- package/docs/v7/_drafts/commands/wait.mdx +45 -0
- package/docs/v7/_drafts/configuration.mdx +378 -0
- package/docs/v7/_drafts/contributing.mdx +174 -0
- package/docs/v7/_drafts/core.mdx +458 -0
- package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
- package/docs/v7/_drafts/debugging.mdx +349 -0
- package/docs/v7/_drafts/error-handling.mdx +501 -0
- package/docs/v7/_drafts/faq.mdx +393 -0
- package/docs/v7/_drafts/hooks.mdx +360 -0
- package/docs/v7/_drafts/init-command.mdx +95 -0
- package/docs/v7/_drafts/installation.mdx +420 -0
- package/docs/v7/_drafts/migration.mdx +562 -0
- package/docs/v7/_drafts/observable.mdx +604 -0
- package/docs/v7/_drafts/playwright.mdx +342 -0
- package/docs/v7/_drafts/plugin-migration.mdx +220 -0
- package/docs/v7/_drafts/powerful.mdx +419 -0
- package/docs/v7/_drafts/presets.mdx +210 -0
- package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
- package/docs/v7/_drafts/prompt-cache.mdx +200 -0
- package/docs/v7/_drafts/provision.mdx +390 -0
- package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
- package/docs/v7/_drafts/readme.mdx +135 -0
- package/docs/v7/_drafts/reports.mdx +414 -0
- package/docs/v7/_drafts/scalable.mdx +763 -0
- package/docs/v7/_drafts/screenshot.mdx +155 -0
- package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
- package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
- package/docs/v7/_drafts/sdk-migration.mdx +474 -0
- package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
- package/docs/v7/_drafts/self-hosting.mdx +369 -0
- package/docs/v7/_drafts/test-recording.mdx +382 -0
- package/docs/v7/_drafts/troubleshooting.mdx +526 -0
- package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
- package/docs/v7/_drafts/vitest.mdx +535 -0
- package/docs/v7/_drafts/writing-tests.mdx +25 -0
- package/docs/v7/ai.mdx +205 -0
- package/docs/v7/assert.mdx +316 -0
- package/docs/v7/aws-setup.mdx +449 -0
- package/docs/v7/cache.mdx +223 -0
- package/docs/v7/caching.mdx +128 -0
- package/docs/v7/captcha.mdx +159 -0
- package/docs/v7/ci-cd.mdx +603 -0
- package/docs/v7/click.mdx +287 -0
- package/docs/v7/client.mdx +478 -0
- package/docs/v7/copilot/auto-healing.mdx +265 -0
- package/docs/v7/copilot/creating-tests.mdx +156 -0
- package/docs/v7/copilot/github.mdx +143 -0
- package/docs/v7/copilot/running-tests.mdx +149 -0
- package/docs/v7/copilot/setup.mdx +143 -0
- package/docs/v7/customizing-devices.mdx +319 -0
- package/docs/v7/dashcam.mdx +419 -0
- package/docs/v7/debugging-with-screenshots.mdx +402 -0
- package/docs/v7/device-config.mdx +317 -0
- package/docs/v7/double-click.mdx +102 -0
- package/docs/v7/elements.mdx +606 -0
- package/docs/v7/enterprise.mdx +9 -0
- package/docs/v7/errors.mdx +248 -0
- package/docs/v7/events.mdx +358 -0
- package/docs/v7/examples/ai.mdx +72 -0
- package/docs/v7/examples/assert.mdx +72 -0
- package/docs/v7/examples/captcha-api.mdx +92 -0
- package/docs/v7/examples/chrome-extension.mdx +132 -0
- package/docs/v7/examples/drag-and-drop.mdx +100 -0
- package/docs/v7/examples/element-not-found.mdx +67 -0
- package/docs/v7/examples/exec-output.mdx +85 -0
- package/docs/v7/examples/exec-pwsh.mdx +83 -0
- package/docs/v7/examples/focus-window.mdx +62 -0
- package/docs/v7/examples/hover-image.mdx +94 -0
- package/docs/v7/examples/hover-text.mdx +69 -0
- package/docs/v7/examples/installer.mdx +91 -0
- package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
- package/docs/v7/examples/match-image.mdx +96 -0
- package/docs/v7/examples/press-keys.mdx +92 -0
- package/docs/v7/examples/scroll-keyboard.mdx +79 -0
- package/docs/v7/examples/scroll-until-image.mdx +81 -0
- package/docs/v7/examples/scroll-until-text.mdx +109 -0
- package/docs/v7/examples/scroll.mdx +81 -0
- package/docs/v7/examples/type.mdx +92 -0
- package/docs/v7/examples/windows-installer.mdx +89 -0
- package/docs/v7/exec.mdx +318 -0
- package/docs/v7/find.mdx +830 -0
- package/docs/v7/focus-application.mdx +294 -0
- package/docs/v7/generating-tests.mdx +36 -0
- package/docs/v7/hosted.mdx +158 -0
- package/docs/v7/hover.mdx +279 -0
- package/docs/v7/locating-elements.mdx +71 -0
- package/docs/v7/making-assertions.mdx +32 -0
- package/docs/v7/mcp.mdx +9 -0
- package/docs/v7/mouse-down.mdx +161 -0
- package/docs/v7/mouse-up.mdx +164 -0
- package/docs/v7/parse.mdx +237 -0
- package/docs/v7/performing-actions.mdx +54 -0
- package/docs/v7/press-keys.mdx +349 -0
- package/docs/v7/provision.mdx +333 -0
- package/docs/v7/quickstart.mdx +173 -0
- package/docs/v7/redraw.mdx +216 -0
- package/docs/v7/reusable-code.mdx +249 -0
- package/docs/v7/right-click.mdx +123 -0
- package/docs/v7/running-tests.mdx +185 -0
- package/docs/v7/screenshot.mdx +249 -0
- package/docs/v7/screenshots.mdx +186 -0
- package/docs/v7/scroll.mdx +336 -0
- package/docs/v7/secrets.mdx +115 -0
- package/docs/v7/self-hosted.mdx +149 -0
- package/docs/v7/type.mdx +358 -0
- package/docs/v7/variables.mdx +111 -0
- package/docs/v7/wait.mdx +52 -0
- package/docs/v7/waiting-for-elements.mdx +90 -0
- package/docs/v7/what-is-testdriver.mdx +54 -0
- package/eslint.config.js +67 -0
- package/examples/ai.test.mjs +31 -0
- package/examples/assert.test.mjs +47 -0
- package/examples/chrome-extension.test.mjs +97 -0
- package/examples/config.mjs +5 -0
- package/examples/element-not-found.test.mjs +27 -0
- package/examples/exec-output.test.mjs +60 -0
- package/examples/exec-pwsh.test.mjs +58 -0
- package/examples/findall-coffee-icons.test.mjs +42 -0
- package/examples/focus-window.test.mjs +37 -0
- package/examples/formatted-logging.test.mjs +27 -0
- package/examples/hover-image.test.mjs +53 -0
- package/examples/hover-text-with-description.test.mjs +57 -0
- package/examples/hover-text.test.mjs +28 -0
- package/examples/installer.test.mjs +50 -0
- package/examples/launch-vscode-linux.test.mjs +55 -0
- package/examples/match-image.test.mjs +55 -0
- package/examples/parse.test.mjs +19 -0
- package/examples/press-keys.test.mjs +44 -0
- package/examples/prompt.test.mjs +34 -0
- package/examples/scroll-keyboard.test.mjs +38 -0
- package/examples/scroll-until-image.test.mjs +40 -0
- package/examples/scroll.test.mjs +42 -0
- package/examples/type.test.mjs +46 -0
- package/examples/windows-installer.test.mjs +54 -0
- package/index.js +2 -0
- package/interfaces/cli/commands/init.js +438 -0
- package/interfaces/cli/commands/setup.js +382 -0
- package/interfaces/cli/lib/base.js +285 -0
- package/interfaces/cli.js +20 -0
- package/interfaces/junit-reporter.js +290 -0
- package/interfaces/logger.js +388 -0
- package/interfaces/readline.js +234 -0
- package/interfaces/shared-test-state.mjs +64 -0
- package/interfaces/vitest-plugin.d.ts +115 -0
- package/interfaces/vitest-plugin.mjs +1698 -0
- package/lib/captcha/solver.js +358 -0
- package/lib/core/Dashcam.js +533 -0
- package/lib/core/index.d.ts +172 -0
- package/lib/core/index.js +12 -0
- package/lib/environments.json +18 -0
- package/lib/github-comment-formatter.js +263 -0
- package/lib/github-comment.mjs +452 -0
- package/lib/init-project.js +575 -0
- package/lib/presets/index.mjs +331 -0
- package/lib/resolve-channel.js +46 -0
- package/lib/sentry.js +417 -0
- package/lib/vitest/hooks.d.ts +57 -0
- package/lib/vitest/hooks.mjs +674 -0
- package/lib/vitest/setup-aws.mjs +247 -0
- package/lib/vitest/setup-self-hosted.mjs +151 -0
- package/lib/vitest/setup.mjs +46 -0
- package/manual/captcha-api.test.mjs +51 -0
- package/manual/drag-and-drop.test.mjs +59 -0
- package/manual/flake-diffthreshold-001.test.mjs +9 -0
- package/manual/flake-diffthreshold-01.test.mjs +9 -0
- package/manual/flake-diffthreshold-05.test.mjs +9 -0
- package/manual/flake-noredraw-cache.test.mjs +9 -0
- package/manual/flake-noredraw-nocache.test.mjs +9 -0
- package/manual/flake-redraw-cache.test.mjs +9 -0
- package/manual/flake-redraw-nocache.test.mjs +9 -0
- package/manual/flake-rocket-match.test.mjs +30 -0
- package/manual/flake-shared.mjs +51 -0
- package/manual/no-provision.test.mjs +31 -0
- package/manual/packer-hover-image.test.mjs +176 -0
- package/manual/scroll-until-text.test.mjs +68 -0
- package/manual/test-init-command.js +223 -0
- package/mcp-server/README.md +322 -0
- package/mcp-server/dist/codegen.d.ts +9 -0
- package/mcp-server/dist/codegen.js +165 -0
- package/mcp-server/dist/mcp-app.html +114 -0
- package/mcp-server/dist/package.json +1 -0
- package/mcp-server/dist/provision-types.d.ts +290 -0
- package/mcp-server/dist/provision-types.js +174 -0
- package/mcp-server/dist/server.d.ts +6 -0
- package/mcp-server/dist/server.mjs +1925 -0
- package/mcp-server/dist/session.d.ts +85 -0
- package/mcp-server/dist/session.js +152 -0
- package/mcp-server/mcp-app.html +28 -0
- package/mcp-server/mcp-config.example.json +19 -0
- package/mcp-server/package-lock.json +4027 -0
- package/mcp-server/package.json +31 -0
- package/mcp-server/src/codegen.ts +189 -0
- package/mcp-server/src/mcp-app.css +360 -0
- package/mcp-server/src/mcp-app.ts +547 -0
- package/mcp-server/src/provision-types.ts +209 -0
- package/mcp-server/src/server.ts +2391 -0
- package/mcp-server/src/session.ts +194 -0
- package/mcp-server/tsconfig.json +16 -0
- package/mcp-server/vite.config.ts +23 -0
- package/package.json +158 -0
- package/schema.json +1046 -0
- package/scripts/generate-skills.js +94 -0
- package/sdk-log-formatter.js +1157 -0
- package/sdk.d.ts +1486 -0
- package/sdk.js +4336 -0
- package/setup/aws/cloudformation.yaml +463 -0
- package/setup/aws/disable-defender.sh +42 -0
- package/setup/aws/install-dev-runner.sh +79 -0
- package/setup/aws/spawn-runner.sh +289 -0
- package/test/captcha-solver.test.mjs +152 -0
- package/test/chrome-remote-debugging.test.mjs +66 -0
- package/test/duckduckgo/experiment.test.mjs +28 -0
- package/test/duckduckgo/setup.test.mjs +29 -0
- package/test/manual/debug-locate-response.js +82 -0
- package/test/manual/reconnect-provision.test.mjs +49 -0
- package/test/manual/test-console-logs.test.mjs +42 -0
- package/test/manual/test-find-api.js +73 -0
- package/test/manual/test-init.sh +54 -0
- package/test/manual/test-prompt-cache.js +97 -0
- package/test/manual/test-provision-auth.mjs +22 -0
- package/test/manual/test-sandbox-render.js +29 -0
- package/test/manual/test-sdk-methods.js +15 -0
- package/test/manual/test-sdk-refactor.js +53 -0
- package/test/manual/test-stack-trace.mjs +57 -0
- package/test/manual/verify-element-api.js +89 -0
- package/test/manual/verify-types.js +0 -0
- package/test/manual-unawaited-promise.test.mjs +31 -0
- package/vitest.config.mjs +58 -0
- package/vitest.runner.config.mjs +33 -0
- package/vscode-extension/.vscodeignore +12 -0
- package/vscode-extension/README.md +94 -0
- package/vscode-extension/media/icon.png +0 -0
- package/vscode-extension/package-lock.json +4126 -0
- package/vscode-extension/package.json +86 -0
- package/vscode-extension/src/extension.ts +829 -0
- package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
- package/vscode-extension/tsconfig.json +16 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
const { PNG } = require("pngjs");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const { events } = require("../events");
|
|
4
|
+
const theme = require("./theme");
|
|
5
|
+
|
|
6
|
+
// Default redraw options
|
|
7
|
+
const DEFAULT_REDRAW_OPTIONS = {
|
|
8
|
+
enabled: true, // Master switch to enable/disable redraw detection
|
|
9
|
+
screenRedraw: true, // Enable screen redraw detection
|
|
10
|
+
networkMonitor: false, // Enable network activity monitoring
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Factory function that creates redraw functionality with the provided system instance
|
|
14
|
+
const createRedraw = (
|
|
15
|
+
emitter,
|
|
16
|
+
system,
|
|
17
|
+
sandbox,
|
|
18
|
+
defaultOptions = {},
|
|
19
|
+
) => {
|
|
20
|
+
// Merge default options with provided defaults
|
|
21
|
+
const baseOptions = { ...DEFAULT_REDRAW_OPTIONS, ...defaultOptions };
|
|
22
|
+
|
|
23
|
+
// Network check interval (ms) - used for speed calculation display
|
|
24
|
+
const networkCheckInterval = 250;
|
|
25
|
+
|
|
26
|
+
let lastTxBytes = null;
|
|
27
|
+
let lastRxBytes = null;
|
|
28
|
+
|
|
29
|
+
let diffRxBytes = 0;
|
|
30
|
+
let diffTxBytes = 0;
|
|
31
|
+
|
|
32
|
+
let measurements = [];
|
|
33
|
+
let networkSettled = true;
|
|
34
|
+
|
|
35
|
+
// Screen stability tracking
|
|
36
|
+
let initialScreenImage = null; // The image captured at start() - reference point
|
|
37
|
+
let lastScreenImage = null; // Previous frame for consecutive comparison
|
|
38
|
+
let hasChangedFromInitial = false; // Has screen changed from initial state?
|
|
39
|
+
let consecutiveFramesStable = false; // Are consecutive frames now stable?
|
|
40
|
+
let screenMeasurements = []; // Track consecutive frame diffs for stability detection
|
|
41
|
+
|
|
42
|
+
// Track network interval to ensure only one exists
|
|
43
|
+
let networkInterval = null;
|
|
44
|
+
|
|
45
|
+
const resetState = () => {
|
|
46
|
+
lastTxBytes = null;
|
|
47
|
+
lastRxBytes = null;
|
|
48
|
+
measurements = [];
|
|
49
|
+
networkSettled = true;
|
|
50
|
+
initialScreenImage = null;
|
|
51
|
+
lastScreenImage = null;
|
|
52
|
+
hasChangedFromInitial = false;
|
|
53
|
+
consecutiveFramesStable = false;
|
|
54
|
+
screenMeasurements = [];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const parseNetworkStats = (thisRxBytes, thisTxBytes) => {
|
|
58
|
+
diffRxBytes = lastRxBytes !== null ? thisRxBytes - lastRxBytes : 0;
|
|
59
|
+
diffTxBytes = lastTxBytes !== null ? thisTxBytes - lastTxBytes : 0;
|
|
60
|
+
|
|
61
|
+
lastRxBytes = thisRxBytes;
|
|
62
|
+
lastTxBytes = thisTxBytes;
|
|
63
|
+
|
|
64
|
+
measurements.push({ rx: diffRxBytes, tx: diffTxBytes });
|
|
65
|
+
|
|
66
|
+
if (measurements.length > 60) {
|
|
67
|
+
measurements.shift();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let avgRx =
|
|
71
|
+
measurements.reduce((acc, m) => acc + m.rx, 0) / measurements.length;
|
|
72
|
+
let avgTx =
|
|
73
|
+
measurements.reduce((acc, m) => acc + m.tx, 0) / measurements.length;
|
|
74
|
+
|
|
75
|
+
let stdDevRx = Math.sqrt(
|
|
76
|
+
measurements.reduce((acc, m) => acc + Math.pow(m.rx - avgRx, 2), 0) /
|
|
77
|
+
measurements.length,
|
|
78
|
+
);
|
|
79
|
+
let stdDevTx = Math.sqrt(
|
|
80
|
+
measurements.reduce((acc, m) => acc + Math.pow(m.tx - avgTx, 2), 0) /
|
|
81
|
+
measurements.length,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
let zIndexRx = stdDevRx !== 0 ? (diffRxBytes - avgRx) / stdDevRx : 0;
|
|
85
|
+
let zIndexTx = stdDevTx !== 0 ? (diffTxBytes - avgTx) / stdDevTx : 0;
|
|
86
|
+
|
|
87
|
+
if (zIndexRx < 0 && zIndexTx < 0) {
|
|
88
|
+
networkSettled = true;
|
|
89
|
+
} else {
|
|
90
|
+
networkSettled = false;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Parse screen diff stats for consecutive frame stability
|
|
95
|
+
// Detects when consecutive frames have stopped changing
|
|
96
|
+
const parseConsecutiveDiffStats = (diffPercent) => {
|
|
97
|
+
screenMeasurements.push(diffPercent);
|
|
98
|
+
|
|
99
|
+
// Keep last 10 measurements for stability detection
|
|
100
|
+
if (screenMeasurements.length > 10) {
|
|
101
|
+
screenMeasurements.shift();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Need at least 2 measurements to determine stability
|
|
105
|
+
if (screenMeasurements.length < 2) {
|
|
106
|
+
consecutiveFramesStable = false;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let avgDiff = screenMeasurements.reduce((acc, d) => acc + d, 0) / screenMeasurements.length;
|
|
111
|
+
|
|
112
|
+
let stdDevDiff = Math.sqrt(
|
|
113
|
+
screenMeasurements.reduce((acc, d) => acc + Math.pow(d - avgDiff, 2), 0) /
|
|
114
|
+
screenMeasurements.length,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
let zIndexDiff = stdDevDiff !== 0 ? (diffPercent - avgDiff) / stdDevDiff : 0;
|
|
118
|
+
|
|
119
|
+
// Consecutive frames are stable when z-index is negative (current diff is below average)
|
|
120
|
+
// or diff is essentially zero (< 0.1% accounts for compression artifacts)
|
|
121
|
+
if (screenMeasurements.length >= 2 && (diffPercent < 0.1 || zIndexDiff < 0)) {
|
|
122
|
+
consecutiveFramesStable = true;
|
|
123
|
+
} else {
|
|
124
|
+
consecutiveFramesStable = false;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Track if a network request is in flight to prevent overlapping requests
|
|
129
|
+
let networkRequestInFlight = false;
|
|
130
|
+
|
|
131
|
+
async function updateNetwork() {
|
|
132
|
+
// Prevent overlapping requests - if one is already in flight, skip this cycle
|
|
133
|
+
if (networkRequestInFlight) {
|
|
134
|
+
emitter.emit(events.log.debug, '[redraw] updateNetwork() - skipping, request already in flight');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (sandbox && sandbox.instanceSocketConnected) {
|
|
139
|
+
networkRequestInFlight = true;
|
|
140
|
+
try {
|
|
141
|
+
let network = await sandbox.send({
|
|
142
|
+
type: "system.network",
|
|
143
|
+
}, 10000); // Use a shorter 10 second timeout for network stats
|
|
144
|
+
parseNetworkStats(
|
|
145
|
+
network.out.totalBytesReceived,
|
|
146
|
+
network.out.totalBytesSent,
|
|
147
|
+
);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
// Log the error but don't throw - network monitoring is non-critical
|
|
150
|
+
emitter.emit(events.log.debug, `[redraw] updateNetwork() failed: ${error.message}`);
|
|
151
|
+
} finally {
|
|
152
|
+
networkRequestInFlight = false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function imageDiffPercent(image1Url, image2Url) {
|
|
158
|
+
try {
|
|
159
|
+
// Dynamic import for ES module pixelmatch
|
|
160
|
+
const { default: pixelmatch } = await import("pixelmatch");
|
|
161
|
+
|
|
162
|
+
// Read PNG files
|
|
163
|
+
const img1Buffer = fs.readFileSync(image1Url);
|
|
164
|
+
const img2Buffer = fs.readFileSync(image2Url);
|
|
165
|
+
|
|
166
|
+
// Parse PNG data
|
|
167
|
+
const img1 = PNG.sync.read(img1Buffer);
|
|
168
|
+
const img2 = PNG.sync.read(img2Buffer);
|
|
169
|
+
|
|
170
|
+
// Ensure images have the same dimensions
|
|
171
|
+
if (img1.width !== img2.width || img1.height !== img2.height) {
|
|
172
|
+
throw new Error("Images must have the same dimensions");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const { width, height } = img1;
|
|
176
|
+
const totalPixels = width * height;
|
|
177
|
+
|
|
178
|
+
// Create diff image buffer
|
|
179
|
+
const diff = new PNG({ width, height });
|
|
180
|
+
|
|
181
|
+
// Compare images using pixelmatch
|
|
182
|
+
const differentPixels = pixelmatch(
|
|
183
|
+
img1.data,
|
|
184
|
+
img2.data,
|
|
185
|
+
diff.data,
|
|
186
|
+
width,
|
|
187
|
+
height,
|
|
188
|
+
{ threshold: 0.1 },
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Calculate percentage difference based on pixel differences
|
|
192
|
+
// Always return a number (0 if no difference)
|
|
193
|
+
const diffPercentage = (differentPixels / totalPixels) * 100;
|
|
194
|
+
return parseFloat(diffPercentage.toFixed(2));
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error("Error comparing images:", error);
|
|
197
|
+
return 0; // Return 0 on error instead of false
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Stop network monitoring (cleanup any residual interval)
|
|
202
|
+
function stopNetworkMonitoring() {
|
|
203
|
+
if (networkInterval) {
|
|
204
|
+
clearInterval(networkInterval);
|
|
205
|
+
networkInterval = null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Current options for the active redraw cycle
|
|
210
|
+
let currentOptions = { ...baseOptions };
|
|
211
|
+
|
|
212
|
+
async function start(options = {}) {
|
|
213
|
+
// Merge base options with per-call options
|
|
214
|
+
currentOptions = { ...baseOptions, ...options };
|
|
215
|
+
|
|
216
|
+
emitter.emit(events.log.debug, `[redraw] start() called with options: ${JSON.stringify(currentOptions)}`);
|
|
217
|
+
|
|
218
|
+
// If redraw is completely disabled, return early
|
|
219
|
+
if (!currentOptions.enabled) {
|
|
220
|
+
emitter.emit(events.log.debug, '[redraw] start() - redraw disabled, returning null');
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// If both screenRedraw and networkMonitor are disabled, disable redraw
|
|
225
|
+
if (!currentOptions.screenRedraw && !currentOptions.networkMonitor) {
|
|
226
|
+
currentOptions.enabled = false;
|
|
227
|
+
emitter.emit(events.log.debug, '[redraw] start() - both screenRedraw and networkMonitor disabled, returning null');
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
resetState();
|
|
232
|
+
|
|
233
|
+
// Capture initial image for screen stability monitoring
|
|
234
|
+
if (currentOptions.screenRedraw) {
|
|
235
|
+
initialScreenImage = await system.captureScreenPNG(0.25, true);
|
|
236
|
+
lastScreenImage = initialScreenImage;
|
|
237
|
+
emitter.emit(events.log.debug, `[redraw] start() - captured initial image: ${initialScreenImage}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return initialScreenImage;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function checkCondition(resolve, startTime, timeoutMs, options) {
|
|
244
|
+
const { enabled, screenRedraw, networkMonitor } = options;
|
|
245
|
+
|
|
246
|
+
// If redraw is disabled, resolve immediately
|
|
247
|
+
if (!enabled) {
|
|
248
|
+
resolve("true");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Update network stats on each check (with guard against overlapping requests)
|
|
253
|
+
if (networkMonitor) {
|
|
254
|
+
await updateNetwork();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
let nowImage = screenRedraw ? await system.captureScreenPNG(0.25, true) : null;
|
|
258
|
+
let timeElapsed = Date.now() - startTime;
|
|
259
|
+
let diffFromInitial = 0;
|
|
260
|
+
let diffFromLast = 0;
|
|
261
|
+
let isTimeout = timeElapsed > timeoutMs;
|
|
262
|
+
|
|
263
|
+
// Screen stability detection:
|
|
264
|
+
// 1. Check if screen has changed from initial (detect transition)
|
|
265
|
+
// 2. Check if consecutive frames are stable (detect settling)
|
|
266
|
+
if (screenRedraw && nowImage) {
|
|
267
|
+
// Compare to initial image - has the screen changed at all?
|
|
268
|
+
if (initialScreenImage && !hasChangedFromInitial) {
|
|
269
|
+
diffFromInitial = await imageDiffPercent(initialScreenImage, nowImage);
|
|
270
|
+
emitter.emit(events.log.debug, `[redraw] checkCondition() - diffFromInitial: ${diffFromInitial}`);
|
|
271
|
+
// Consider changed if diff > 0.1% (accounts for compression artifacts)
|
|
272
|
+
if (diffFromInitial > 0.1) {
|
|
273
|
+
hasChangedFromInitial = true;
|
|
274
|
+
emitter.emit(events.log.debug, `[redraw] checkCondition() - screen has changed from initial!`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Compare consecutive frames - has the screen stopped changing?
|
|
279
|
+
if (lastScreenImage && lastScreenImage !== initialScreenImage) {
|
|
280
|
+
diffFromLast = await imageDiffPercent(lastScreenImage, nowImage);
|
|
281
|
+
emitter.emit(events.log.debug, `[redraw] checkCondition() - diffFromLast: ${diffFromLast}`);
|
|
282
|
+
parseConsecutiveDiffStats(diffFromLast);
|
|
283
|
+
emitter.emit(events.log.debug, `[redraw] checkCondition() - consecutiveFramesStable: ${consecutiveFramesStable}, measurements: ${screenMeasurements.length}`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Update last image for next comparison
|
|
287
|
+
lastScreenImage = nowImage;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Screen is settled when it has changed from initial AND consecutive frames are now stable
|
|
291
|
+
const screenSettled = hasChangedFromInitial && consecutiveFramesStable;
|
|
292
|
+
|
|
293
|
+
// If screen redraw is disabled, consider it as "settled"
|
|
294
|
+
const effectiveScreenSettled = screenRedraw ? screenSettled : true;
|
|
295
|
+
// If network monitor is disabled, consider it as "settled"
|
|
296
|
+
const effectiveNetworkSettled = networkMonitor ? networkSettled : true;
|
|
297
|
+
|
|
298
|
+
// Log redraw status - show both change detection and stability
|
|
299
|
+
let redrawText = !screenRedraw
|
|
300
|
+
? theme.dim(`disabled`)
|
|
301
|
+
: effectiveScreenSettled
|
|
302
|
+
? theme.green(`y`)
|
|
303
|
+
: theme.dim(`${hasChangedFromInitial ? '✓' : '?'}→${consecutiveFramesStable ? '✓' : diffFromLast.toFixed(1)}%`);
|
|
304
|
+
let networkText = !networkMonitor
|
|
305
|
+
? theme.dim(`disabled`)
|
|
306
|
+
: effectiveNetworkSettled
|
|
307
|
+
? theme.green(`y`)
|
|
308
|
+
: theme.dim(
|
|
309
|
+
`${Math.trunc((diffRxBytes + diffTxBytes) / (networkCheckInterval / 1000))}b/s`,
|
|
310
|
+
);
|
|
311
|
+
let timeoutText = isTimeout
|
|
312
|
+
? theme.green(`y`)
|
|
313
|
+
: theme.dim(`${Math.floor(timeElapsed / 1000)}/${timeoutMs / 1000}s`);
|
|
314
|
+
|
|
315
|
+
emitter.emit(events.redraw.status, {
|
|
316
|
+
redraw: {
|
|
317
|
+
enabled: screenRedraw,
|
|
318
|
+
settled: effectiveScreenSettled,
|
|
319
|
+
hasChangedFromInitial,
|
|
320
|
+
consecutiveFramesStable,
|
|
321
|
+
diffFromInitial,
|
|
322
|
+
diffFromLast,
|
|
323
|
+
text: redrawText,
|
|
324
|
+
},
|
|
325
|
+
network: {
|
|
326
|
+
enabled: networkMonitor,
|
|
327
|
+
settled: effectiveNetworkSettled,
|
|
328
|
+
rxBytes: diffRxBytes,
|
|
329
|
+
txBytes: diffTxBytes,
|
|
330
|
+
text: networkText,
|
|
331
|
+
},
|
|
332
|
+
timeout: {
|
|
333
|
+
isTimeout,
|
|
334
|
+
elapsed: timeElapsed,
|
|
335
|
+
max: timeoutMs,
|
|
336
|
+
text: timeoutText,
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
if ((effectiveScreenSettled && effectiveNetworkSettled) || isTimeout) {
|
|
341
|
+
emitter.emit(events.redraw.complete, {
|
|
342
|
+
screenSettled: effectiveScreenSettled,
|
|
343
|
+
hasChangedFromInitial,
|
|
344
|
+
consecutiveFramesStable,
|
|
345
|
+
networkSettled: effectiveNetworkSettled,
|
|
346
|
+
isTimeout,
|
|
347
|
+
timeElapsed,
|
|
348
|
+
});
|
|
349
|
+
resolve("true");
|
|
350
|
+
} else {
|
|
351
|
+
// Poll at 500ms intervals to reduce websocket traffic
|
|
352
|
+
// (previously 250ms = up to 20 polls per 5s timeout, now max 10)
|
|
353
|
+
setTimeout(() => {
|
|
354
|
+
checkCondition(resolve, startTime, timeoutMs, options);
|
|
355
|
+
}, 500);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function wait(timeoutMs, options = {}) {
|
|
360
|
+
// Merge current options with any per-call overrides
|
|
361
|
+
const waitOptions = { ...currentOptions, ...options };
|
|
362
|
+
|
|
363
|
+
// If redraw is disabled, resolve immediately
|
|
364
|
+
if (!waitOptions.enabled) {
|
|
365
|
+
return Promise.resolve("true");
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// If both are disabled, resolve immediately
|
|
369
|
+
if (!waitOptions.screenRedraw && !waitOptions.networkMonitor) {
|
|
370
|
+
return Promise.resolve("true");
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return new Promise((resolve) => {
|
|
374
|
+
const startTime = Date.now();
|
|
375
|
+
checkCondition(resolve, startTime, timeoutMs, waitOptions);
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function cleanup() {
|
|
380
|
+
stopNetworkMonitoring(networkInterval);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return { start, wait, cleanup, DEFAULT_OPTIONS: DEFAULT_REDRAW_OPTIONS };
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
module.exports = { createRedraw, DEFAULT_REDRAW_OPTIONS };
|
|
Binary file
|