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,167 @@
|
|
|
1
|
+
# Auto-Generated Cache Keys from File Hash
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
When you create a TestDriver instance without providing an explicit `cacheKey`, the SDK will automatically generate one based on the SHA-256 hash of the calling file. This provides automatic cache invalidation when your test file changes, while enabling cache hits for identical test runs.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
1. **Stack Trace Analysis**: When `TestDriver()` is called, the SDK analyzes the call stack to find the caller file
|
|
10
|
+
2. **File Hashing**: The content of the caller file is hashed using SHA-256
|
|
11
|
+
3. **Cache Key Generation**: The first 16 characters of the hash are used as the cache key
|
|
12
|
+
4. **Automatic Updates**: When the test file is modified, the hash changes, automatically invalidating the cache
|
|
13
|
+
|
|
14
|
+
## Benefits
|
|
15
|
+
|
|
16
|
+
- ✅ **No Manual Cache Management**: Cache keys are automatically generated and updated
|
|
17
|
+
- ✅ **File-Scoped Caching**: All tests in the same file share the same cache
|
|
18
|
+
- ✅ **Automatic Invalidation**: Cache is invalidated when the test file changes
|
|
19
|
+
- ✅ **Explicit Override**: You can still provide a manual `cacheKey` if needed
|
|
20
|
+
|
|
21
|
+
## Usage Examples
|
|
22
|
+
|
|
23
|
+
### Automatic Cache Key (Recommended)
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
27
|
+
|
|
28
|
+
test('login test', async (context) => {
|
|
29
|
+
// No cacheKey provided - will be auto-generated from this file's hash
|
|
30
|
+
const testdriver = TestDriver(context, {
|
|
31
|
+
headless: true
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Cache key is automatically set based on this file
|
|
35
|
+
console.log(testdriver.options.cacheKey); // e.g., "4cae7be040f293b9"
|
|
36
|
+
|
|
37
|
+
const button = await testdriver.find('login button');
|
|
38
|
+
// Subsequent calls in this test file will use the same cache
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Explicit Cache Key (Override)
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
46
|
+
|
|
47
|
+
test('login test', async (context) => {
|
|
48
|
+
// Explicit cacheKey provided - auto-generation is skipped
|
|
49
|
+
const testdriver = TestDriver(context, {
|
|
50
|
+
headless: true,
|
|
51
|
+
cacheKey: 'my-custom-key-v1'
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.log(testdriver.options.cacheKey); // "my-custom-key-v1"
|
|
55
|
+
|
|
56
|
+
const button = await testdriver.find('login button');
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Cache Behavior
|
|
61
|
+
|
|
62
|
+
### With Auto-Generated Key
|
|
63
|
+
|
|
64
|
+
1. **First Run**: Creates cache entries with key = hash of test file
|
|
65
|
+
2. **Subsequent Runs** (file unchanged): Cache hits
|
|
66
|
+
3. **After File Modification**: New hash = new cache key = cache miss
|
|
67
|
+
|
|
68
|
+
### Cache Hit Example
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
// File: login.test.mjs (hash: 4cae7be040f293b9)
|
|
72
|
+
|
|
73
|
+
const testdriver = TestDriver(context);
|
|
74
|
+
// Auto-generated cacheKey: "4cae7be040f293b9"
|
|
75
|
+
|
|
76
|
+
const button1 = await testdriver.find('login button'); // Cache MISS (first time)
|
|
77
|
+
const button2 = await testdriver.find('login button'); // Cache HIT (same file, same test run)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
After modifying the file (adding a comment, changing test logic, etc.):
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
// File: login.test.mjs (hash: 7f3d9a2b1c5e8f6a) <- changed!
|
|
84
|
+
|
|
85
|
+
const testdriver = TestDriver(context);
|
|
86
|
+
// Auto-generated cacheKey: "7f3d9a2b1c5e8f6a" <- different from before
|
|
87
|
+
|
|
88
|
+
const button1 = await testdriver.find('login button'); // Cache MISS (new hash)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Debug Mode
|
|
92
|
+
|
|
93
|
+
To see the auto-generated cache key in debug logs:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Set environment variable
|
|
97
|
+
export TD_DEBUG=1
|
|
98
|
+
|
|
99
|
+
# Or in your test
|
|
100
|
+
process.env.TD_DEBUG = '1';
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
With debug mode enabled, you'll see:
|
|
104
|
+
```
|
|
105
|
+
🔍 find() threshold: 0.05 (cache ENABLED, cacheKey: 4cae7be040f293b9 (auto-generated from file hash))
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Implementation Details
|
|
109
|
+
|
|
110
|
+
### Stack Trace Filtering
|
|
111
|
+
|
|
112
|
+
The auto-generation skips the following in the stack trace to find the actual test file:
|
|
113
|
+
- `sdk.js` (TestDriver SDK)
|
|
114
|
+
- `hooks.mjs` / `hooks.js` (Vitest hooks)
|
|
115
|
+
- `node_modules` (dependencies)
|
|
116
|
+
- `node:internal` (Node.js internals)
|
|
117
|
+
|
|
118
|
+
### File Path Handling
|
|
119
|
+
|
|
120
|
+
The implementation handles both:
|
|
121
|
+
- Regular file paths: `/Users/you/project/test.mjs`
|
|
122
|
+
- File URL format: `file:///Users/you/project/test.mjs`
|
|
123
|
+
|
|
124
|
+
### Hash Format
|
|
125
|
+
|
|
126
|
+
- Algorithm: SHA-256
|
|
127
|
+
- Output: First 16 hexadecimal characters (e.g., `4cae7be040f293b9`)
|
|
128
|
+
- Collision probability: Effectively zero for practical purposes
|
|
129
|
+
|
|
130
|
+
## When to Use Manual Cache Keys
|
|
131
|
+
|
|
132
|
+
Consider using manual `cacheKey` values when:
|
|
133
|
+
|
|
134
|
+
1. **Cross-File Caching**: You want to share cache across multiple test files
|
|
135
|
+
2. **Version-Based Caching**: You want explicit control over cache invalidation
|
|
136
|
+
3. **CI/CD Integration**: You want to tie caching to build numbers or git commits
|
|
137
|
+
|
|
138
|
+
Example:
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
const cacheKey = \`test-suite-\${process.env.GIT_COMMIT}\`;
|
|
142
|
+
const testdriver = TestDriver(context, { cacheKey });
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Migration from Manual Keys
|
|
146
|
+
|
|
147
|
+
If you currently use manual cache keys:
|
|
148
|
+
|
|
149
|
+
### Before
|
|
150
|
+
```javascript
|
|
151
|
+
const testdriver = TestDriver(context, {
|
|
152
|
+
cacheKey: 'login-test-v1'
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### After (automatic)
|
|
157
|
+
```javascript
|
|
158
|
+
// Just remove the cacheKey - it will be auto-generated!
|
|
159
|
+
const testdriver = TestDriver(context);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The cache will automatically invalidate when the test file changes, which is usually the desired behavior.
|
|
163
|
+
|
|
164
|
+
## See Also
|
|
165
|
+
|
|
166
|
+
- [SDK_README.md](./SDK_README.md) - Cache configuration options
|
|
167
|
+
- [CACHE_ARCHITECTURE.md](../api/CACHE_ARCHITECTURE.md) - Cache system architecture
|
|
@@ -9,12 +9,76 @@ icon: "crosshairs"
|
|
|
9
9
|
|
|
10
10
|
The Selector Cache stores element locations on the server, so `.find()` calls can skip the AI vision analysis.
|
|
11
11
|
|
|
12
|
+
**Important:** Selector caching is **disabled by default** as of v7.1. You must provide a `cacheKey` to enable caching.
|
|
13
|
+
|
|
12
14
|
This provides:
|
|
13
15
|
- ⚡ **Up to 10x faster** - Skip AI vision analysis
|
|
14
16
|
- 💰 **Lower AI costs** - Fewer vision API calls
|
|
15
17
|
- 🎯 **Consistent results** - Same UI = same coordinates
|
|
16
18
|
- 📊 **Metrics tracking** - See cache hit rates in console
|
|
17
19
|
|
|
20
|
+
## Enabling the Cache
|
|
21
|
+
|
|
22
|
+
### Auto-Generated Cache Keys (Recommended)
|
|
23
|
+
|
|
24
|
+
TestDriver automatically generates cache keys based on your test file:
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
// Cache automatically enabled - uses file hash as cache key
|
|
28
|
+
const button = await testdriver.find('submit button');
|
|
29
|
+
// Cache key: "a1b2c3d4e5f6..." (first 16 chars of file SHA-256)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Benefits:**
|
|
33
|
+
- ✅ **Per-file isolation** - Each test file has its own cache
|
|
34
|
+
- ✅ **Auto-invalidation** - Cache updates when test code changes
|
|
35
|
+
- ✅ **Zero configuration** - Works out of the box
|
|
36
|
+
- ✅ **Safe** - No cross-test pollution
|
|
37
|
+
|
|
38
|
+
### Custom Cache Keys
|
|
39
|
+
|
|
40
|
+
Provide your own cache key for more control:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
// Custom cache key
|
|
44
|
+
const button = await testdriver.find('submit button', {
|
|
45
|
+
cacheKey: 'my-test-key'
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Share cache across tests
|
|
49
|
+
const button = await testdriver.find('submit button', {
|
|
50
|
+
cacheKey: 'shared-submit-button'
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Global Cache Key
|
|
55
|
+
|
|
56
|
+
Enable caching for all finds in your test:
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
const client = new TestDriver(apiKey, {
|
|
60
|
+
cacheKey: 'my-global-key' // All finds will use this cache
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Now all finds are cached
|
|
64
|
+
await testdriver.find('button 1'); // Uses 'my-global-key'
|
|
65
|
+
await testdriver.find('button 2'); // Uses 'my-global-key'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Disable Auto-Cache
|
|
69
|
+
|
|
70
|
+
If you don't want automatic caching:
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
// Disable cache for this find
|
|
74
|
+
await testdriver.find('button', { cacheThreshold: -1 });
|
|
75
|
+
|
|
76
|
+
// Or use a threshold of -1 globally
|
|
77
|
+
const client = new TestDriver(apiKey, {
|
|
78
|
+
cacheThreshold: { find: -1, findAll: -1 }
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
18
82
|
## How It Works
|
|
19
83
|
|
|
20
84
|
```mermaid
|
|
@@ -65,22 +129,32 @@ The selector cache uses a three-tier matching system:
|
|
|
65
129
|
|
|
66
130
|
## Controlling Cache Threshold
|
|
67
131
|
|
|
68
|
-
Adjust similarity threshold
|
|
132
|
+
Adjust similarity threshold when cache is enabled:
|
|
69
133
|
|
|
70
134
|
```javascript
|
|
71
135
|
// Default: 95% similarity (5% difference allowed)
|
|
72
|
-
await testdriver.find('submit button');
|
|
136
|
+
await testdriver.find('submit button', { cacheKey: 'test-1' });
|
|
73
137
|
|
|
74
138
|
// Stricter: 99% similarity (1% difference allowed)
|
|
75
|
-
await testdriver.find('submit button', {
|
|
139
|
+
await testdriver.find('submit button', {
|
|
140
|
+
cacheKey: 'test-1',
|
|
141
|
+
cacheThreshold: 0.01
|
|
142
|
+
});
|
|
76
143
|
|
|
77
144
|
// More lenient: 90% similarity (10% difference allowed)
|
|
78
|
-
await testdriver.find('submit button', {
|
|
145
|
+
await testdriver.find('submit button', {
|
|
146
|
+
cacheKey: 'test-1',
|
|
147
|
+
cacheThreshold: 0.10
|
|
148
|
+
});
|
|
79
149
|
|
|
80
150
|
// Disable cache: force fresh AI analysis
|
|
81
|
-
await testdriver.find('submit button', {
|
|
151
|
+
await testdriver.find('submit button', { cacheThreshold: -1 });
|
|
82
152
|
```
|
|
83
153
|
|
|
154
|
+
<Note>
|
|
155
|
+
`cacheThreshold` only works when caching is enabled via `cacheKey` or global config.
|
|
156
|
+
</Note>
|
|
157
|
+
|
|
84
158
|
## Cache Filtering
|
|
85
159
|
|
|
86
160
|
The selector cache automatically filters by:
|
|
@@ -126,13 +200,19 @@ test('find element', async (context) => {
|
|
|
126
200
|
url: 'https://example.com'
|
|
127
201
|
});
|
|
128
202
|
|
|
203
|
+
// Auto-cache enabled (uses file hash as cache key)
|
|
129
204
|
// First call: AI vision analysis, saves to cache
|
|
130
205
|
const button = await testdriver.find('More information link');
|
|
131
|
-
console.log('Cache hit:', button.cacheHit); // false
|
|
206
|
+
console.log('Cache hit:', button.cacheHit); // false (first run)
|
|
132
207
|
|
|
133
208
|
// Second call: uses cache (instant)
|
|
134
209
|
const button2 = await testdriver.find('More information link');
|
|
135
|
-
console.log('Cache hit:', button2.cacheHit); // true
|
|
210
|
+
console.log('Cache hit:', button2.cacheHit); // true (cache hit)
|
|
211
|
+
|
|
212
|
+
// Custom cache key
|
|
213
|
+
const button3 = await testdriver.find('submit button', {
|
|
214
|
+
cacheKey: 'my-button'
|
|
215
|
+
});
|
|
136
216
|
});
|
|
137
217
|
```
|
|
138
218
|
|
|
@@ -142,14 +222,20 @@ test('find element', async (context) => {
|
|
|
142
222
|
test('strict vs lenient matching', async (context) => {
|
|
143
223
|
const { testdriver } = await chrome(context, { url });
|
|
144
224
|
|
|
145
|
-
// Strict: 99% similarity required
|
|
146
|
-
const elem1 = await testdriver.find('button', {
|
|
225
|
+
// Strict: 99% similarity required (auto-cache key)
|
|
226
|
+
const elem1 = await testdriver.find('button', { cacheThreshold: 0.01 });
|
|
147
227
|
|
|
148
228
|
// Lenient: 90% similarity acceptable
|
|
149
|
-
const elem2 = await testdriver.find('button', {
|
|
229
|
+
const elem2 = await testdriver.find('button', { cacheThreshold: 0.10 });
|
|
230
|
+
|
|
231
|
+
// Bypass cache entirely (no cacheKey needed)
|
|
232
|
+
const elem3 = await testdriver.find('button', { cacheThreshold: -1 });
|
|
150
233
|
|
|
151
|
-
//
|
|
152
|
-
const
|
|
234
|
+
// Custom cache key with threshold
|
|
235
|
+
const elem4 = await testdriver.find('button', {
|
|
236
|
+
cacheKey: 'my-button',
|
|
237
|
+
cacheThreshold: 0.05
|
|
238
|
+
});
|
|
153
239
|
});
|
|
154
240
|
```
|
|
155
241
|
|
|
@@ -159,12 +245,21 @@ test('strict vs lenient matching', async (context) => {
|
|
|
159
245
|
test('monitor cache performance', async (context) => {
|
|
160
246
|
const { testdriver } = await chrome(context, { url });
|
|
161
247
|
|
|
248
|
+
// Auto-cache enabled
|
|
162
249
|
const element = await testdriver.find('submit button');
|
|
163
250
|
|
|
164
251
|
if (element.cacheHit) {
|
|
165
252
|
console.log('✅ Cache hit - instant response');
|
|
253
|
+
console.log('Cache strategy:', element.cacheStrategy);
|
|
254
|
+
console.log('Cache age:', element.cacheCreatedAt);
|
|
166
255
|
} else {
|
|
167
256
|
console.log('⏱️ Cache miss - AI analysis performed');
|
|
257
|
+
console.log('New cache entry created');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Check similarity score
|
|
261
|
+
if (element.similarity) {
|
|
262
|
+
console.log(`Similarity: ${(element.similarity * 100).toFixed(1)}%`);
|
|
168
263
|
}
|
|
169
264
|
});
|
|
170
265
|
```
|
|
@@ -174,17 +269,30 @@ test('monitor cache performance', async (context) => {
|
|
|
174
269
|
### 1. Use Appropriate Thresholds
|
|
175
270
|
|
|
176
271
|
```javascript
|
|
177
|
-
// Stable UI: strict threshold
|
|
178
|
-
await testdriver.find('logo', {
|
|
272
|
+
// Stable UI: strict threshold (auto-cache)
|
|
273
|
+
await testdriver.find('logo', { cacheThreshold: 0.01 });
|
|
179
274
|
|
|
180
275
|
// Dynamic UI: lenient threshold
|
|
181
|
-
await testdriver.find('news feed item', {
|
|
276
|
+
await testdriver.find('news feed item', { cacheThreshold: 0.10 });
|
|
182
277
|
|
|
183
278
|
// Always fresh: disable cache
|
|
184
|
-
await testdriver.find('timestamp', {
|
|
279
|
+
await testdriver.find('timestamp', { cacheThreshold: -1 });
|
|
185
280
|
```
|
|
186
281
|
|
|
187
|
-
### 2.
|
|
282
|
+
### 2. Choose Cache Key Strategy
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
// Auto-cache (recommended) - per-file isolation
|
|
286
|
+
await testdriver.find('button');
|
|
287
|
+
|
|
288
|
+
// Custom key - share across tests
|
|
289
|
+
await testdriver.find('button', { cacheKey: 'global-submit' });
|
|
290
|
+
|
|
291
|
+
// Global key - all finds in test
|
|
292
|
+
const testdriver = new TestDriver(apiKey, {
|
|
293
|
+
cacheKey: 'test-suite-1'
|
|
294
|
+
});
|
|
295
|
+
```
|
|
188
296
|
|
|
189
297
|
Check [console.testdriver.ai](https://console.testdriver.ai) regularly to:
|
|
190
298
|
- See cache hit rates
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Dashcam Recording Titles
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Dashcam recordings now automatically use meaningful titles instead of the generic "Dashcam Recording" label.
|
|
6
|
+
|
|
7
|
+
## Automatic Title Generation
|
|
8
|
+
|
|
9
|
+
When using TestDriver with Vitest, the dashcam recording title is automatically generated from:
|
|
10
|
+
1. **Test file name** - Extracted from the test file path
|
|
11
|
+
2. **Test name** - The name of the test case
|
|
12
|
+
|
|
13
|
+
### Example
|
|
14
|
+
|
|
15
|
+
For a test file `login.test.mjs` with test case `"should login successfully"`:
|
|
16
|
+
```
|
|
17
|
+
Recording title: "login - should login successfully"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
For standalone usage without test context:
|
|
21
|
+
```
|
|
22
|
+
Recording title: "Recording 2025-12-02 14:30:45"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Custom Titles
|
|
26
|
+
|
|
27
|
+
You can set a custom title before starting the dashcam recording:
|
|
28
|
+
|
|
29
|
+
### With Vitest Integration
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
import { test } from 'vitest';
|
|
33
|
+
import { TestDriver } from 'testdriverai/vitest';
|
|
34
|
+
|
|
35
|
+
test('my test', async (context) => {
|
|
36
|
+
const testdriver = TestDriver(context, { headless: true });
|
|
37
|
+
|
|
38
|
+
// Set custom title before dashcam starts
|
|
39
|
+
testdriver.dashcam.setTitle('My Custom Recording Title');
|
|
40
|
+
|
|
41
|
+
// Start recording (provision methods start dashcam automatically)
|
|
42
|
+
await testdriver.provision.chrome({ url: 'https://example.com' });
|
|
43
|
+
|
|
44
|
+
await testdriver.find('button').click();
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Direct SDK Usage
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
const TestDriver = require('testdriverai');
|
|
52
|
+
|
|
53
|
+
const client = new TestDriver(process.env.TD_API_KEY);
|
|
54
|
+
await client.connect();
|
|
55
|
+
|
|
56
|
+
// Set custom title
|
|
57
|
+
client.dashcam.setTitle('Integration Test - Payment Flow');
|
|
58
|
+
|
|
59
|
+
// Start recording
|
|
60
|
+
await client.dashcam.start();
|
|
61
|
+
|
|
62
|
+
await client.provision.chrome({ url: 'https://example.com' });
|
|
63
|
+
await client.find('Checkout button').click();
|
|
64
|
+
|
|
65
|
+
// Stop recording and get URL
|
|
66
|
+
const dashcamUrl = await client.dashcam.stop();
|
|
67
|
+
console.log('Recording:', dashcamUrl);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Constructor Option
|
|
71
|
+
|
|
72
|
+
You can also pass a title when creating the Dashcam instance:
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
const { Dashcam } = require('testdriverai/core');
|
|
76
|
+
|
|
77
|
+
const dashcam = new Dashcam(client, {
|
|
78
|
+
title: 'Custom Title',
|
|
79
|
+
autoStart: true
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Implementation Details
|
|
84
|
+
|
|
85
|
+
- **Default title generation** uses test context (`__vitestContext`) when available
|
|
86
|
+
- **Test file names** are cleaned (removes `.test`, `.spec`, file extensions)
|
|
87
|
+
- **Fallback** to ISO timestamp if no test context is available
|
|
88
|
+
- **Title escaping** handles special characters in shell commands properly
|
|
89
|
+
- **Cross-platform** support for Windows (PowerShell) and Linux/Mac (bash/zsh)
|