testdriverai 7.1.0 → 7.1.2
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/.env.example +2 -0
- package/.github/workflows/linux-tests.yml +28 -0
- package/agent/index.js +18 -45
- package/agent/interface.js +13 -2
- package/agent/lib/commands.js +1 -1
- package/agent/lib/redraw.js +1 -1
- package/agent/lib/sandbox.js +30 -2
- package/agent/lib/valid-version.js +2 -2
- package/debugger/index.html +1 -1
- package/docs/docs.json +140 -131
- package/docs/v6/getting-started/self-hosting.mdx +3 -2
- package/docs/v7/_drafts/agents.mdx +852 -0
- package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
- package/docs/v7/{guides → _drafts}/caching-selectors.mdx +125 -17
- package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
- package/docs/v7/_drafts/error-handling.mdx +501 -0
- package/docs/v7/_drafts/implementation-plan.mdx +994 -0
- package/docs/v7/_drafts/init-command.mdx +95 -0
- package/docs/v7/_drafts/optimal-sdk-design.mdx +1348 -0
- package/docs/v7/_drafts/plugin-migration.mdx +222 -0
- package/docs/v7/_drafts/prompt-cache.mdx +200 -0
- package/docs/{QUICK_START_TEST_RECORDING.md → v7/_drafts/quick-start-test-recording.mdx} +3 -3
- package/docs/v7/_drafts/sdk-logging.mdx +222 -0
- package/docs/v7/_drafts/sdk-migration.mdx +474 -0
- package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
- package/docs/v7/{guides → _drafts}/self-hosting.mdx +1 -1
- package/docs/v7/{guides → _drafts}/troubleshooting.mdx +2 -2
- package/docs/v7/{guides → _drafts}/vitest-plugin.mdx +4 -4
- package/docs/v7/api/{ai.mdx → act.mdx} +24 -24
- package/docs/v7/api/client.mdx +1 -1
- package/docs/v7/api/dashcam.mdx +2 -2
- package/docs/v7/api/elements.mdx +143 -41
- package/docs/v7/api/find.mdx +258 -0
- package/docs/v7/api/type.mdx +51 -7
- package/docs/v7/features/ai-native.mdx +427 -0
- package/docs/v7/features/easy-to-write.mdx +351 -0
- package/docs/v7/features/enterprise.mdx +540 -0
- package/docs/v7/features/fast.mdx +424 -0
- package/docs/v7/features/observable.mdx +623 -0
- package/docs/v7/features/powerful.mdx +531 -0
- package/docs/v7/features/scalable.mdx +417 -0
- package/docs/v7/features/stable.mdx +514 -0
- package/docs/v7/getting-started/configuration.mdx +1 -1
- package/docs/v7/getting-started/generating-tests.mdx +525 -0
- package/docs/v7/getting-started/installation.mdx +486 -0
- package/docs/v7/getting-started/quickstart.mdx +51 -5
- package/docs/v7/getting-started/running-and-debugging.mdx +511 -0
- package/docs/v7/getting-started/setting-up-in-ci.mdx +612 -0
- package/docs/v7/getting-started/writing-tests.mdx +535 -0
- package/docs/v7/overview/what-is-testdriver.mdx +398 -0
- package/docs/v7/playwright.mdx +3 -3
- package/docs/v7/presets/chrome.mdx +16 -0
- package/docs/v7/presets/electron.mdx +18 -0
- package/docs/v7/presets/vscode.mdx +19 -0
- package/examples/run-tests-with-recording.sh +70 -0
- package/examples/screenshot-example.js +63 -0
- package/examples/sdk-awesome-logs-demo.js +177 -0
- package/examples/sdk-cache-thresholds.js +96 -0
- package/examples/sdk-element-properties.js +155 -0
- package/examples/sdk-simple-example.js +65 -0
- package/examples/test-recording-example.test.js +166 -0
- package/interfaces/cli/commands/init.js +358 -0
- package/interfaces/vitest-plugin.mjs +214 -10
- package/{src → lib}/core/Dashcam.js +41 -4
- package/{src → lib}/vitest/hooks.mjs +118 -100
- package/lib/vitest/setup.mjs +44 -0
- package/package.json +9 -10
- package/sdk.d.ts +15 -2
- package/sdk.js +72 -17
- package/{self-hosted.yml → setup/aws/self-hosted.yml} +1 -1
- package/{testdriver/acceptance-sdk → test/manual}/test-console-logs.test.mjs +1 -1
- package/test/manual/test-find-api.js +73 -0
- package/test/manual/test-init.sh +54 -0
- package/test/manual/test-prompt-cache.js +96 -0
- package/test/manual/test-provision-auth.mjs +22 -0
- package/test/manual/test-sandbox-render.js +28 -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/testdriver/assert.test.mjs +41 -0
- package/{testdriver/acceptance-sdk → test/testdriver}/auto-cache-key-demo.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/drag-and-drop.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/element-not-found.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-js.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-output.test.mjs +3 -3
- package/{testdriver/acceptance-sdk → test/testdriver}/exec-pwsh.test.mjs +3 -3
- package/{testdriver/acceptance-sdk → test/testdriver}/focus-window.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/formatted-logging.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-image.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-text-with-description.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/hover-text.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/match-image.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/press-keys.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/prompt.test.mjs +2 -2
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-keyboard.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-image.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll-until-text.test.mjs +1 -1
- package/{testdriver/acceptance-sdk → test/testdriver}/scroll.test.mjs +1 -1
- package/{src/vitest/lifecycle.mjs → test/testdriver/setup/lifecycleHelpers.mjs} +84 -99
- package/test/testdriver/setup/testHelpers.mjs +653 -0
- package/{testdriver/acceptance-sdk → test/testdriver}/type.test.mjs +1 -1
- package/vitest.config.mjs +8 -59
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/acceptance-linux.yml +0 -75
- package/.github/workflows/acceptance-sdk-tests.yml +0 -133
- package/.github/workflows/acceptance-tests.yml +0 -130
- package/.github/workflows/lint.yml +0 -27
- package/.github/workflows/publish-canary.yml +0 -40
- package/.github/workflows/publish-latest.yml +0 -61
- package/.github/workflows/test-install.yml +0 -29
- package/.vscode/extensions.json +0 -3
- package/.vscode/launch.json +0 -22
- package/.vscode/settings.json +0 -14
- package/AGENTS.md +0 -550
- package/CODEOWNERS +0 -2
- package/_testdriver/acceptance/assert.yaml +0 -7
- package/_testdriver/acceptance/dashcam.yaml +0 -9
- package/_testdriver/acceptance/drag-and-drop.yaml +0 -49
- package/_testdriver/acceptance/embed.yaml +0 -9
- package/_testdriver/acceptance/exec-js.yaml +0 -29
- package/_testdriver/acceptance/exec-output.yaml +0 -43
- package/_testdriver/acceptance/exec-shell.yaml +0 -40
- package/_testdriver/acceptance/focus-window.yaml +0 -16
- package/_testdriver/acceptance/hover-image.yaml +0 -18
- package/_testdriver/acceptance/hover-text-with-description.yaml +0 -29
- package/_testdriver/acceptance/hover-text.yaml +0 -14
- package/_testdriver/acceptance/if-else.yaml +0 -31
- package/_testdriver/acceptance/match-image.yaml +0 -15
- package/_testdriver/acceptance/press-keys.yaml +0 -35
- package/_testdriver/acceptance/prompt.yaml +0 -11
- package/_testdriver/acceptance/remember.yaml +0 -27
- package/_testdriver/acceptance/screenshots/cart.png +0 -0
- package/_testdriver/acceptance/scroll-keyboard.yaml +0 -34
- package/_testdriver/acceptance/scroll-until-image.yaml +0 -26
- package/_testdriver/acceptance/scroll-until-text.yaml +0 -20
- package/_testdriver/acceptance/scroll.yaml +0 -33
- package/_testdriver/acceptance/snippets/login.yaml +0 -29
- package/_testdriver/acceptance/snippets/match-cart.yaml +0 -8
- package/_testdriver/acceptance/type.yaml +0 -29
- package/_testdriver/behavior/failure.yaml +0 -7
- package/_testdriver/behavior/hover-text.yaml +0 -13
- package/_testdriver/behavior/lifecycle/postrun.yaml +0 -10
- package/_testdriver/behavior/lifecycle/prerun.yaml +0 -8
- package/_testdriver/behavior/lifecycle/provision.yaml +0 -8
- package/_testdriver/behavior/secrets.yaml +0 -7
- package/_testdriver/edge-cases/dashcam-chrome.yaml +0 -8
- package/_testdriver/edge-cases/exec-pwsh-multiline.yaml +0 -10
- package/_testdriver/edge-cases/js-exception.yaml +0 -8
- package/_testdriver/edge-cases/js-promise.yaml +0 -19
- package/_testdriver/edge-cases/lifecycle/postrun.yaml +0 -10
- package/_testdriver/edge-cases/prompt-in-middle.yaml +0 -23
- package/_testdriver/edge-cases/prompt-nested.yaml +0 -7
- package/_testdriver/edge-cases/success-test.yaml +0 -9
- package/_testdriver/examples/android/example.yaml +0 -12
- package/_testdriver/examples/android/lifecycle/postrun.yaml +0 -11
- package/_testdriver/examples/android/lifecycle/provision.yaml +0 -47
- package/_testdriver/examples/android/readme.md +0 -7
- package/_testdriver/examples/chrome-extension/lifecycle/provision.yaml +0 -74
- package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
- package/_testdriver/examples/desktop/lifecycle/provision.yaml +0 -64
- package/_testdriver/examples/vscode-extension/lifecycle/provision.yaml +0 -73
- package/_testdriver/examples/web/lifecycle/postrun.yaml +0 -7
- package/_testdriver/examples/web/lifecycle/prerun.yaml +0 -22
- package/_testdriver/lifecycle/postrun.yaml +0 -8
- package/_testdriver/lifecycle/prerun.yaml +0 -15
- package/_testdriver/lifecycle/provision.yaml +0 -25
- package/docs/v7/guides/ci-cd/azure.mdx +0 -587
- package/docs/v7/guides/ci-cd/circleci.mdx +0 -523
- package/docs/v7/guides/ci-cd/github-actions.mdx +0 -457
- package/docs/v7/guides/ci-cd/gitlab.mdx +0 -498
- package/docs/v7/guides/ci-cd/jenkins.mdx +0 -664
- package/docs/v7/guides/ci-cd/travis.mdx +0 -438
- package/scripts/view-test-results.mjs +0 -96
- package/src/vitest/extended.mjs +0 -108
- package/src/vitest/index.mjs +0 -64
- package/src/vitest/utils.mjs +0 -150
- package/styles/.vale-config/2-MDX.ini +0 -5
- package/styles/Microsoft/AMPM.yml +0 -9
- package/styles/Microsoft/Accessibility.yml +0 -30
- package/styles/Microsoft/Acronyms.yml +0 -64
- package/styles/Microsoft/Adverbs.yml +0 -272
- package/styles/Microsoft/Auto.yml +0 -11
- package/styles/Microsoft/Avoid.yml +0 -14
- package/styles/Microsoft/Contractions.yml +0 -50
- package/styles/Microsoft/Dashes.yml +0 -13
- package/styles/Microsoft/DateFormat.yml +0 -8
- package/styles/Microsoft/DateNumbers.yml +0 -40
- package/styles/Microsoft/DateOrder.yml +0 -8
- package/styles/Microsoft/Ellipses.yml +0 -9
- package/styles/Microsoft/FirstPerson.yml +0 -16
- package/styles/Microsoft/Foreign.yml +0 -13
- package/styles/Microsoft/Gender.yml +0 -8
- package/styles/Microsoft/GenderBias.yml +0 -42
- package/styles/Microsoft/GeneralURL.yml +0 -11
- package/styles/Microsoft/HeadingAcronyms.yml +0 -7
- package/styles/Microsoft/HeadingColons.yml +0 -8
- package/styles/Microsoft/HeadingPunctuation.yml +0 -13
- package/styles/Microsoft/Headings.yml +0 -28
- package/styles/Microsoft/Hyphens.yml +0 -14
- package/styles/Microsoft/Negative.yml +0 -13
- package/styles/Microsoft/Ordinal.yml +0 -13
- package/styles/Microsoft/OxfordComma.yml +0 -8
- package/styles/Microsoft/Passive.yml +0 -183
- package/styles/Microsoft/Percentages.yml +0 -7
- package/styles/Microsoft/Plurals.yml +0 -7
- package/styles/Microsoft/Quotes.yml +0 -7
- package/styles/Microsoft/RangeTime.yml +0 -13
- package/styles/Microsoft/Semicolon.yml +0 -8
- package/styles/Microsoft/SentenceLength.yml +0 -6
- package/styles/Microsoft/Spacing.yml +0 -8
- package/styles/Microsoft/Suspended.yml +0 -7
- package/styles/Microsoft/Terms.yml +0 -42
- package/styles/Microsoft/URLFormat.yml +0 -9
- package/styles/Microsoft/Units.yml +0 -16
- package/styles/Microsoft/Vocab.yml +0 -25
- package/styles/Microsoft/We.yml +0 -11
- package/styles/Microsoft/Wordiness.yml +0 -127
- package/styles/Microsoft/meta.json +0 -4
- package/styles/alex/Ablist.yml +0 -274
- package/styles/alex/Condescending.yml +0 -16
- package/styles/alex/Gendered.yml +0 -110
- package/styles/alex/LGBTQ.yml +0 -55
- package/styles/alex/OCD.yml +0 -10
- package/styles/alex/Press.yml +0 -12
- package/styles/alex/ProfanityLikely.yml +0 -1289
- package/styles/alex/ProfanityMaybe.yml +0 -282
- package/styles/alex/ProfanityUnlikely.yml +0 -251
- package/styles/alex/README.md +0 -27
- package/styles/alex/Race.yml +0 -85
- package/styles/alex/Suicide.yml +0 -26
- package/styles/alex/meta.json +0 -4
- package/styles/config/vocabularies/Docs/accept.txt +0 -47
- package/styles/config/vocabularies/Docs/reject.txt +0 -4
- package/styles/proselint/Airlinese.yml +0 -8
- package/styles/proselint/AnimalLabels.yml +0 -48
- package/styles/proselint/Annotations.yml +0 -9
- package/styles/proselint/Apologizing.yml +0 -8
- package/styles/proselint/Archaisms.yml +0 -52
- package/styles/proselint/But.yml +0 -8
- package/styles/proselint/Cliches.yml +0 -782
- package/styles/proselint/CorporateSpeak.yml +0 -30
- package/styles/proselint/Currency.yml +0 -5
- package/styles/proselint/Cursing.yml +0 -15
- package/styles/proselint/DateCase.yml +0 -7
- package/styles/proselint/DateMidnight.yml +0 -7
- package/styles/proselint/DateRedundancy.yml +0 -10
- package/styles/proselint/DateSpacing.yml +0 -7
- package/styles/proselint/DenizenLabels.yml +0 -52
- package/styles/proselint/Diacritical.yml +0 -95
- package/styles/proselint/GenderBias.yml +0 -45
- package/styles/proselint/GroupTerms.yml +0 -39
- package/styles/proselint/Hedging.yml +0 -8
- package/styles/proselint/Hyperbole.yml +0 -6
- package/styles/proselint/Jargon.yml +0 -11
- package/styles/proselint/LGBTOffensive.yml +0 -13
- package/styles/proselint/LGBTTerms.yml +0 -15
- package/styles/proselint/Malapropisms.yml +0 -8
- package/styles/proselint/Needless.yml +0 -358
- package/styles/proselint/Nonwords.yml +0 -38
- package/styles/proselint/Oxymorons.yml +0 -22
- package/styles/proselint/P-Value.yml +0 -6
- package/styles/proselint/RASSyndrome.yml +0 -30
- package/styles/proselint/README.md +0 -12
- package/styles/proselint/Skunked.yml +0 -13
- package/styles/proselint/Spelling.yml +0 -17
- package/styles/proselint/Typography.yml +0 -11
- package/styles/proselint/Uncomparables.yml +0 -50
- package/styles/proselint/Very.yml +0 -6
- package/styles/proselint/meta.json +0 -15
- package/styles/write-good/Cliches.yml +0 -702
- package/styles/write-good/E-Prime.yml +0 -32
- package/styles/write-good/Illusions.yml +0 -11
- package/styles/write-good/Passive.yml +0 -183
- package/styles/write-good/README.md +0 -27
- package/styles/write-good/So.yml +0 -5
- package/styles/write-good/ThereIs.yml +0 -6
- package/styles/write-good/TooWordy.yml +0 -221
- package/styles/write-good/Weasel.yml +0 -29
- package/styles/write-good/meta.json +0 -4
- package/test/dashcam.test.js +0 -137
- package/test/mcp-example-test.yaml +0 -27
- package/test/test_parser.js +0 -47
- package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +0 -61
- package/testdriver/acceptance-sdk/README.md +0 -128
- package/testdriver/acceptance-sdk/TEST_REPORTING.md +0 -245
- package/testdriver/acceptance-sdk/assert.test.mjs +0 -26
- package/testdriver/acceptance-sdk/hooks-example.test.mjs +0 -38
- package/testdriver/acceptance-sdk/presets-example.test.mjs +0 -87
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +0 -420
- package/testdriver/acceptance-sdk/sully-ai.test.mjs +0 -234
- package/testdriver/acceptance-sdk/type-checking-demo.js +0 -49
- package/vale.ini +0 -18
- package/vitest.config.example.js +0 -19
- package/vitest.config.mjs.bak +0 -44
- /package/docs/{ARCHITECTURE.md → v7/_drafts/architecture.mdx} +0 -0
- /package/docs/{AWESOME_LOGS_QUICK_REF.md → v7/_drafts/awesome-logs-quick-ref.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/best-practices.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/caching-ai.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/caching.mdx +0 -0
- /package/docs/{MIGRATION.md → v7/_drafts/cli-to-sdk-migration.mdx} +0 -0
- /package/{CONTRIBUTING.md → docs/v7/_drafts/contributing.mdx} +0 -0
- /package/docs/v7/{progressive-apis/CORE.md → _drafts/core.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/debugging.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/faq.mdx +0 -0
- /package/docs/v7/{progressive-apis/HOOKS.md → _drafts/hooks.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/migration.mdx +0 -0
- /package/docs/v7/{guides → _drafts}/performance.mdx +0 -0
- /package/docs/{PRESETS.md → v7/_drafts/presets.mdx} +0 -0
- /package/docs/v7/{progressive-apis/PROGRESSIVE_DISCLOSURE.md → _drafts/progressive-disclosure.mdx} +0 -0
- /package/docs/v7/{progressive-apis/PROVISION.md → _drafts/provision.mdx} +0 -0
- /package/docs/{SDK_AWESOME_LOGS.md → v7/_drafts/sdk-awesome-logs.mdx} +0 -0
- /package/docs/{sdk-browser-rendering.md → v7/_drafts/sdk-browser-rendering.mdx} +0 -0
- /package/docs/{TEST_RECORDING.md → v7/_drafts/test-recording.mdx} +0 -0
- /package/docs/v7/{guides → _drafts}/vitest.mdx +0 -0
- /package/docs/v7/{README.md → overview/readme.mdx} +0 -0
- /package/{src → lib}/core/index.d.ts +0 -0
- /package/{src → lib}/core/index.js +0 -0
- /package/{src → lib}/presets/index.mjs +0 -0
- /package/{src → lib}/vitest/hooks.d.ts +0 -0
- /package/{debug-locate-response.js → test/manual/debug-locate-response.js} +0 -0
- /package/{verify-element-api.js → test/manual/verify-element-api.js} +0 -0
- /package/{verify-types.js → test/manual/verify-types.js} +0 -0
- /package/{testdriver/acceptance-sdk → test/testdriver}/chrome-extension.test.mjs +0 -0
- /package/{testdriver/acceptance-sdk → test/testdriver}/setup/globalTeardown.mjs +0 -0
- /package/{testdriver/acceptance-sdk → test/testdriver}/setup/vitestSetup.mjs +0 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Error Handling & Debugging"
|
|
3
|
+
sidebarTitle: "Error Handling"
|
|
4
|
+
description: "Understanding and resolving TestDriver errors"
|
|
5
|
+
icon: "bug"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
TestDriver provides detailed debugging information when elements can't be found or operations fail. This guide explains how to interpret and resolve common errors.
|
|
11
|
+
|
|
12
|
+
## Element Not Found Errors
|
|
13
|
+
|
|
14
|
+
The most common error is `ElementNotFoundError`, thrown when `.find()` can't locate an element.
|
|
15
|
+
|
|
16
|
+
### Error Structure
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
try {
|
|
20
|
+
await testdriver.find('submit button').click();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error(error.message);
|
|
23
|
+
console.log('Screenshot:', error.screenshotPath);
|
|
24
|
+
console.log('Cache hit:', error.aiResponse?.cacheHit);
|
|
25
|
+
console.log('Similarity:', error.aiResponse?.similarity);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Example Error Message
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
ElementNotFoundError: Element "submit button" not found.
|
|
33
|
+
|
|
34
|
+
=== Debug Information ===
|
|
35
|
+
Element searched for: "submit button"
|
|
36
|
+
Cache threshold: 0.05 (95.0% similarity required)
|
|
37
|
+
Cache: HIT (perceptual-hash strategy)
|
|
38
|
+
Cache created: 2024-12-02T10:30:45.123Z (15s ago)
|
|
39
|
+
Cache pixel diff: 2.34%
|
|
40
|
+
Similarity score: 92.50% (below threshold)
|
|
41
|
+
Input text: "submit button"
|
|
42
|
+
Current screenshot: /tmp/testdriver-debug/screenshot-1234567890.png
|
|
43
|
+
Cached image URL: https://s3.amazonaws.com/...
|
|
44
|
+
Pixel diff image: /tmp/testdriver-debug/pixel-diff-error-1234567890.png
|
|
45
|
+
|
|
46
|
+
AI Response:
|
|
47
|
+
The submit button appears to have moved slightly to the right.
|
|
48
|
+
The cached position shows it at (100, 200) but the current
|
|
49
|
+
position is approximately (105, 200). This 5px horizontal shift
|
|
50
|
+
caused the pixel difference to exceed the 5% threshold.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Debug Information Fields
|
|
54
|
+
|
|
55
|
+
### Cache Information
|
|
56
|
+
|
|
57
|
+
<ParamField path="cacheHit" type="boolean">
|
|
58
|
+
Whether cache was used for this find attempt
|
|
59
|
+
</ParamField>
|
|
60
|
+
|
|
61
|
+
<ParamField path="cacheStrategy" type="string">
|
|
62
|
+
Strategy used for cache matching:
|
|
63
|
+
- `perceptual-hash` - Fastest, hash-based matching
|
|
64
|
+
- `pixel-diff` - Pixel-by-pixel comparison
|
|
65
|
+
- `template-match` - Visual template matching
|
|
66
|
+
</ParamField>
|
|
67
|
+
|
|
68
|
+
<ParamField path="cacheCreatedAt" type="string">
|
|
69
|
+
ISO timestamp when cache entry was created
|
|
70
|
+
</ParamField>
|
|
71
|
+
|
|
72
|
+
<ParamField path="cacheDiffPercent" type="number">
|
|
73
|
+
Pixel difference percentage from cached image (0-1)
|
|
74
|
+
</ParamField>
|
|
75
|
+
|
|
76
|
+
### Similarity Scores
|
|
77
|
+
|
|
78
|
+
<ParamField path="similarity" type="number">
|
|
79
|
+
AI confidence score (0-1) where:
|
|
80
|
+
- `1.0` = Perfect match
|
|
81
|
+
- `0.95+` = High confidence
|
|
82
|
+
- `0.80-0.95` = Medium confidence
|
|
83
|
+
- `<0.80` = Low confidence (likely wrong element)
|
|
84
|
+
</ParamField>
|
|
85
|
+
|
|
86
|
+
<ParamField path="threshold" type="number">
|
|
87
|
+
Required similarity threshold for cache match
|
|
88
|
+
- Default: `0.05` (95% similarity required)
|
|
89
|
+
- Formula: `similarityRequired = (1 - threshold) * 100`
|
|
90
|
+
</ParamField>
|
|
91
|
+
|
|
92
|
+
### Debug Images
|
|
93
|
+
|
|
94
|
+
<ParamField path="screenshotPath" type="string">
|
|
95
|
+
Path to current screen state screenshot
|
|
96
|
+
|
|
97
|
+
Example: `/tmp/testdriver-debug/screenshot-1234567890.png`
|
|
98
|
+
</ParamField>
|
|
99
|
+
|
|
100
|
+
<ParamField path="cachedImagePath" type="string">
|
|
101
|
+
URL to cached screenshot (if cache hit)
|
|
102
|
+
|
|
103
|
+
Example: `https://s3.amazonaws.com/testdriver-cache/...`
|
|
104
|
+
</ParamField>
|
|
105
|
+
|
|
106
|
+
<ParamField path="pixelDiffPath" type="string">
|
|
107
|
+
Path to pixel difference visualization
|
|
108
|
+
|
|
109
|
+
Shows visual diff between current and cached screenshots
|
|
110
|
+
</ParamField>
|
|
111
|
+
|
|
112
|
+
## Common Error Scenarios
|
|
113
|
+
|
|
114
|
+
### Scenario 1: Cache Miss (UI Changed)
|
|
115
|
+
|
|
116
|
+
**Error:**
|
|
117
|
+
```
|
|
118
|
+
Cache: HIT
|
|
119
|
+
Similarity score: 92.50% (below threshold)
|
|
120
|
+
Cache pixel diff: 7.50%
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Cause:** UI changed more than allowed threshold (5% default)
|
|
124
|
+
|
|
125
|
+
**Solutions:**
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
// Option 1: Increase threshold (more lenient)
|
|
129
|
+
await testdriver.find('button', {
|
|
130
|
+
cacheThreshold: 0.10 // Allow 10% difference
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Option 2: Force fresh AI analysis
|
|
134
|
+
await testdriver.find('button', {
|
|
135
|
+
cacheThreshold: -1 // Bypass cache
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Option 3: Update cache by running test again
|
|
139
|
+
// The new screenshot will replace the old cache entry
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Scenario 2: Element Moved
|
|
143
|
+
|
|
144
|
+
**Error:**
|
|
145
|
+
```
|
|
146
|
+
AI Response:
|
|
147
|
+
The submit button appears to have moved from (100, 200) to (105, 200).
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Cause:** Element position changed, cache outdated
|
|
151
|
+
|
|
152
|
+
**Solutions:**
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
// Disable cache to get fresh coordinates
|
|
156
|
+
await testdriver.find('submit button', { cacheThreshold: -1 });
|
|
157
|
+
|
|
158
|
+
// Or wait for UI to settle before finding
|
|
159
|
+
await testdriver.scroll('down', 100);
|
|
160
|
+
await new Promise(r => setTimeout(r, 1000)); // Wait for scroll
|
|
161
|
+
await testdriver.find('submit button');
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Scenario 3: Wrong Element Found
|
|
165
|
+
|
|
166
|
+
**Error:**
|
|
167
|
+
```
|
|
168
|
+
Similarity score: 0.65 (65% confidence)
|
|
169
|
+
AI Response: Found "cancel button" instead of requested "submit button"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Cause:** Element description too vague
|
|
173
|
+
|
|
174
|
+
**Solutions:**
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
// ❌ Too vague
|
|
178
|
+
await testdriver.find('button');
|
|
179
|
+
|
|
180
|
+
// ✅ More specific
|
|
181
|
+
await testdriver.find('blue submit button at bottom of form');
|
|
182
|
+
|
|
183
|
+
// ✅ Include position context
|
|
184
|
+
await testdriver.find('submit button below the email field');
|
|
185
|
+
|
|
186
|
+
// ✅ Include visual details
|
|
187
|
+
await testdriver.find('green button with text Submit');
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Scenario 4: Element Not Visible Yet
|
|
191
|
+
|
|
192
|
+
**Error:**
|
|
193
|
+
```
|
|
194
|
+
AI Response: Element not visible in current viewport.
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Cause:** Element hasn't loaded or is off-screen
|
|
198
|
+
|
|
199
|
+
**Solutions:**
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
// Polling approach
|
|
203
|
+
async function waitForElement(testdriver, description, timeout = 30000) {
|
|
204
|
+
const startTime = Date.now();
|
|
205
|
+
|
|
206
|
+
while (Date.now() - startTime < timeout) {
|
|
207
|
+
try {
|
|
208
|
+
const element = await testdriver.find(description);
|
|
209
|
+
if (element.found()) return element;
|
|
210
|
+
} catch (error) {
|
|
211
|
+
// Element not found, keep trying
|
|
212
|
+
}
|
|
213
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
throw new Error(`Element "${description}" not found after ${timeout}ms`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Usage
|
|
220
|
+
const button = await waitForElement(testdriver, 'submit button', 10000);
|
|
221
|
+
await button.click();
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Scenario 5: Dynamic Content
|
|
225
|
+
|
|
226
|
+
**Error:**
|
|
227
|
+
```
|
|
228
|
+
Cache: MISS
|
|
229
|
+
AI Response: Found multiple elements matching description.
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Cause:** Multiple similar elements on screen
|
|
233
|
+
|
|
234
|
+
**Solutions:**
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
// Use findAll() for multiple elements
|
|
238
|
+
const buttons = await testdriver.findAll('button');
|
|
239
|
+
await buttons[0].click(); // Click first one
|
|
240
|
+
|
|
241
|
+
// Or be more specific
|
|
242
|
+
await testdriver.find('first button in the top navigation');
|
|
243
|
+
await testdriver.find('button with text Submit');
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Error Handling Patterns
|
|
247
|
+
|
|
248
|
+
### Pattern 1: Try/Catch with Fallback
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
try {
|
|
252
|
+
await testdriver.find('submit button').click();
|
|
253
|
+
} catch (error) {
|
|
254
|
+
if (error instanceof ElementNotFoundError) {
|
|
255
|
+
// Try alternative description
|
|
256
|
+
await testdriver.find('blue button at bottom').click();
|
|
257
|
+
} else {
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Pattern 2: Optional Elements
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
// Handle optional popup
|
|
267
|
+
try {
|
|
268
|
+
const popup = await testdriver.find('cookie consent popup');
|
|
269
|
+
await popup.find('accept button').click();
|
|
270
|
+
console.log('Popup dismissed');
|
|
271
|
+
} catch (error) {
|
|
272
|
+
console.log('No popup to dismiss');
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Pattern 3: Retry with Different Descriptions
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
async function findWithAlternatives(testdriver, descriptions) {
|
|
280
|
+
for (const desc of descriptions) {
|
|
281
|
+
try {
|
|
282
|
+
const element = await testdriver.find(desc);
|
|
283
|
+
if (element.found()) {
|
|
284
|
+
console.log(`Found using: "${desc}"`);
|
|
285
|
+
return element;
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
throw new Error('Element not found with any description');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Usage
|
|
295
|
+
const button = await findWithAlternatives(testdriver, [
|
|
296
|
+
'submit button',
|
|
297
|
+
'blue button at bottom',
|
|
298
|
+
'button with text Submit',
|
|
299
|
+
'send button'
|
|
300
|
+
]);
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Pattern 4: Debug Mode
|
|
304
|
+
|
|
305
|
+
```javascript
|
|
306
|
+
async function findWithDebug(testdriver, description) {
|
|
307
|
+
try {
|
|
308
|
+
return await testdriver.find(description);
|
|
309
|
+
} catch (error) {
|
|
310
|
+
if (error instanceof ElementNotFoundError) {
|
|
311
|
+
console.error('Element not found:', description);
|
|
312
|
+
console.error('Screenshot:', error.screenshotPath);
|
|
313
|
+
console.error('Cache hit:', error.aiResponse?.cacheHit);
|
|
314
|
+
console.error('Similarity:', error.aiResponse?.similarity);
|
|
315
|
+
console.error('AI response:', error.aiResponse?.response);
|
|
316
|
+
|
|
317
|
+
// Save screenshot for manual inspection
|
|
318
|
+
if (error.screenshotPath) {
|
|
319
|
+
const fs = require('fs');
|
|
320
|
+
fs.copyFileSync(error.screenshotPath, `./debug-${Date.now()}.png`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
throw error;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Debugging Tools
|
|
329
|
+
|
|
330
|
+
### 1. Save Debug Screenshots
|
|
331
|
+
|
|
332
|
+
```javascript
|
|
333
|
+
const element = await testdriver.find('button');
|
|
334
|
+
|
|
335
|
+
// Save screenshot to file
|
|
336
|
+
const path = await element.saveDebugScreenshot('./debug.png');
|
|
337
|
+
console.log('Screenshot saved:', path);
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### 2. Check Element Properties
|
|
341
|
+
|
|
342
|
+
```javascript
|
|
343
|
+
const element = await testdriver.find('button');
|
|
344
|
+
|
|
345
|
+
console.log('Found:', element.found());
|
|
346
|
+
console.log('Position:', element.x, element.y);
|
|
347
|
+
console.log('Size:', element.width, element.height);
|
|
348
|
+
console.log('Confidence:', element.confidence);
|
|
349
|
+
console.log('Text:', element.text);
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### 3. View Pixel Diff Images
|
|
353
|
+
|
|
354
|
+
When cache misses occur, TestDriver generates pixel diff images showing the differences:
|
|
355
|
+
|
|
356
|
+
```javascript
|
|
357
|
+
try {
|
|
358
|
+
await testdriver.find('button');
|
|
359
|
+
} catch (error) {
|
|
360
|
+
if (error.pixelDiffPath) {
|
|
361
|
+
console.log('Visual diff:', error.pixelDiffPath);
|
|
362
|
+
// Open in image viewer to see exactly what changed
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### 4. Enable Verbose Logging
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
const testdriver = new TestDriver(apiKey, {
|
|
371
|
+
loggingEnabled: true // Enable detailed logs
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// Now all operations log detailed information
|
|
375
|
+
await testdriver.find('button'); // Logs AI calls, cache hits, etc.
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Best Practices
|
|
379
|
+
|
|
380
|
+
<Check>
|
|
381
|
+
**Always handle ElementNotFoundError**
|
|
382
|
+
|
|
383
|
+
```javascript
|
|
384
|
+
// ✅ Good - explicit error handling
|
|
385
|
+
try {
|
|
386
|
+
await testdriver.find('optional popup').click();
|
|
387
|
+
} catch (error) {
|
|
388
|
+
if (error instanceof ElementNotFoundError) {
|
|
389
|
+
console.log('Popup not found, continuing');
|
|
390
|
+
} else {
|
|
391
|
+
throw error;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ❌ Bad - unhandled errors crash test
|
|
396
|
+
await testdriver.find('optional popup').click();
|
|
397
|
+
```
|
|
398
|
+
</Check>
|
|
399
|
+
|
|
400
|
+
<Check>
|
|
401
|
+
**Save screenshots on failure**
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
test('my test', async (context) => {
|
|
405
|
+
try {
|
|
406
|
+
await testdriver.find('button').click();
|
|
407
|
+
} catch (error) {
|
|
408
|
+
// Save screenshot before test fails
|
|
409
|
+
if (error.screenshotPath) {
|
|
410
|
+
const fs = require('fs');
|
|
411
|
+
const dest = `./failures/${context.test.name}-${Date.now()}.png`;
|
|
412
|
+
fs.copyFileSync(error.screenshotPath, dest);
|
|
413
|
+
console.log('Failure screenshot:', dest);
|
|
414
|
+
}
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
```
|
|
419
|
+
</Check>
|
|
420
|
+
|
|
421
|
+
<Check>
|
|
422
|
+
**Use polling for dynamic content**
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
// ✅ Good - polls until element appears
|
|
426
|
+
async function waitFor(testdriver, desc, timeout = 30000) {
|
|
427
|
+
const start = Date.now();
|
|
428
|
+
while (Date.now() - start < timeout) {
|
|
429
|
+
try {
|
|
430
|
+
const el = await testdriver.find(desc);
|
|
431
|
+
if (el.found()) return el;
|
|
432
|
+
} catch {}
|
|
433
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
434
|
+
}
|
|
435
|
+
throw new Error(`Timeout waiting for: ${desc}`);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// ❌ Bad - fails immediately if not ready
|
|
439
|
+
await testdriver.find('loading complete message');
|
|
440
|
+
```
|
|
441
|
+
</Check>
|
|
442
|
+
|
|
443
|
+
<Check>
|
|
444
|
+
**Inspect AI responses when debugging**
|
|
445
|
+
|
|
446
|
+
```javascript
|
|
447
|
+
try {
|
|
448
|
+
await testdriver.find('button');
|
|
449
|
+
} catch (error) {
|
|
450
|
+
// Read what the AI saw
|
|
451
|
+
const aiResponse = error.aiResponse?.response?.content?.[0]?.text;
|
|
452
|
+
console.log('AI analysis:', aiResponse);
|
|
453
|
+
|
|
454
|
+
// Common patterns:
|
|
455
|
+
// "Found multiple buttons..."
|
|
456
|
+
// "Element not visible in viewport..."
|
|
457
|
+
// "No element matching description..."
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
</Check>
|
|
461
|
+
|
|
462
|
+
## Troubleshooting Checklist
|
|
463
|
+
|
|
464
|
+
When an element can't be found:
|
|
465
|
+
|
|
466
|
+
1. **Check the screenshot**
|
|
467
|
+
- View `error.screenshotPath` to see what TestDriver sees
|
|
468
|
+
- Is the element actually visible?
|
|
469
|
+
- Is the UI in the expected state?
|
|
470
|
+
|
|
471
|
+
2. **Review the description**
|
|
472
|
+
- Is it specific enough?
|
|
473
|
+
- Does it match what's on screen?
|
|
474
|
+
- Try adding more context (position, color, nearby text)
|
|
475
|
+
|
|
476
|
+
3. **Check cache status**
|
|
477
|
+
- Is cache hitting but UI changed? (`error.aiResponse.cacheHit === true`)
|
|
478
|
+
- Is similarity below threshold? (`error.aiResponse.similarity < 0.95`)
|
|
479
|
+
- Try disabling cache: `{ cacheThreshold: -1 }`
|
|
480
|
+
|
|
481
|
+
4. **Look at pixel diff**
|
|
482
|
+
- If `error.pixelDiffPath` exists, open it
|
|
483
|
+
- Visual diff shows exactly what changed
|
|
484
|
+
- Helps identify UI shifts, color changes, etc.
|
|
485
|
+
|
|
486
|
+
5. **Read AI response**
|
|
487
|
+
- `error.aiResponse.response` contains AI's reasoning
|
|
488
|
+
- Often explains why element wasn't found
|
|
489
|
+
- May suggest alternative descriptions
|
|
490
|
+
|
|
491
|
+
6. **Try alternatives**
|
|
492
|
+
- Use `findAll()` to see all matches
|
|
493
|
+
- Try different description wordings
|
|
494
|
+
- Add more visual context
|
|
495
|
+
|
|
496
|
+
## Related Guides
|
|
497
|
+
|
|
498
|
+
- [Element Finding](/v7/api/find) - Basic element finding
|
|
499
|
+
- [Caching](/v7/guides/caching-selectors) - Cache configuration
|
|
500
|
+
- [Best Practices](/v7/guides/best-practices) - General testing tips
|
|
501
|
+
- [Debugging](/v7/guides/debugging) - Advanced debugging techniques
|