@testdriverai/agent 7.11.240-test → 7.11.241-test

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.
Files changed (52) hide show
  1. package/ai/skills/testdriver-agent/SKILL.md +174 -91
  2. package/ai/skills/testdriver-assert/SKILL.md +73 -269
  3. package/ai/skills/testdriver-aws-setup/SKILL.md +194 -312
  4. package/ai/skills/testdriver-bring-your-own-machine/SKILL.md +137 -204
  5. package/ai/skills/testdriver-cache/SKILL.md +142 -149
  6. package/ai/skills/testdriver-caching/SKILL.md +97 -87
  7. package/ai/skills/testdriver-captcha/SKILL.md +126 -111
  8. package/ai/skills/testdriver-ci-cd/SKILL.md +153 -542
  9. package/ai/skills/testdriver-click/SKILL.md +74 -229
  10. package/ai/skills/testdriver-client/SKILL.md +175 -229
  11. package/ai/skills/testdriver-customizing-devices/SKILL.md +72 -250
  12. package/ai/skills/testdriver-dashcam/SKILL.md +71 -404
  13. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +103 -369
  14. package/ai/skills/testdriver-double-click/SKILL.md +46 -67
  15. package/ai/skills/testdriver-errors/SKILL.md +102 -176
  16. package/ai/skills/testdriver-events/SKILL.md +170 -327
  17. package/ai/skills/testdriver-exec/SKILL.md +92 -256
  18. package/ai/skills/testdriver-extract/SKILL.md +69 -170
  19. package/ai/skills/testdriver-find/SKILL.md +140 -736
  20. package/ai/skills/testdriver-focus-application/SKILL.md +69 -246
  21. package/ai/skills/testdriver-generating-tests/SKILL.md +102 -136
  22. package/ai/skills/testdriver-hosted/SKILL.md +79 -143
  23. package/ai/skills/testdriver-hover/SKILL.md +62 -235
  24. package/ai/skills/testdriver-locating-elements/SKILL.md +71 -366
  25. package/ai/skills/testdriver-making-assertions/SKILL.md +114 -72
  26. package/ai/skills/testdriver-mcp-setup/SKILL.md +79 -62
  27. package/ai/skills/testdriver-mouse-down/SKILL.md +46 -124
  28. package/ai/skills/testdriver-mouse-up/SKILL.md +45 -128
  29. package/ai/skills/testdriver-options/SKILL.md +73 -46
  30. package/ai/skills/testdriver-parse/SKILL.md +95 -184
  31. package/ai/skills/testdriver-performing-actions/SKILL.md +101 -91
  32. package/ai/skills/testdriver-press-keys/SKILL.md +59 -299
  33. package/ai/skills/testdriver-provision/SKILL.md +135 -179
  34. package/ai/skills/testdriver-quickstart/SKILL.md +24 -8
  35. package/ai/skills/testdriver-quickstart-claude/SKILL.md +84 -0
  36. package/ai/skills/testdriver-quickstart-github/SKILL.md +62 -32
  37. package/ai/skills/testdriver-quickstart-manual/SKILL.md +59 -32
  38. package/ai/skills/testdriver-quickstart-vscode/SKILL.md +96 -0
  39. package/ai/skills/testdriver-redraw/SKILL.md +100 -164
  40. package/ai/skills/testdriver-reusable-code/SKILL.md +95 -199
  41. package/ai/skills/testdriver-right-click/SKILL.md +45 -88
  42. package/ai/skills/testdriver-screenshot/SKILL.md +47 -201
  43. package/ai/skills/testdriver-screenshots/SKILL.md +86 -136
  44. package/ai/skills/testdriver-scroll/SKILL.md +71 -154
  45. package/ai/skills/testdriver-secrets/SKILL.md +94 -90
  46. package/ai/skills/testdriver-self-hosted/SKILL.md +82 -140
  47. package/ai/skills/testdriver-test-results-json/SKILL.md +165 -202
  48. package/ai/skills/testdriver-type/SKILL.md +56 -304
  49. package/ai/skills/testdriver-variables/SKILL.md +119 -80
  50. package/ai/skills/testdriver-wait/SKILL.md +31 -29
  51. package/ai/skills/testdriver-what-is-testdriver/SKILL.md +80 -32
  52. package/package.json +1 -1
@@ -1,81 +1,51 @@
1
1
  ---
2
2
  name: testdriver:cache
3
- description: Speed up tests with screenshot-based caching
3
+ description: Every option that controls how find() and assert() reuse cached results.
4
4
  ---
5
5
  <!-- Generated from cache.mdx. DO NOT EDIT. -->
6
6
 
7
- ## Overview
7
+ This page lists every cache option, its default, and where you can set it. The cache is on by default, so you only need these to tune or turn it off.
8
8
 
9
- The cache system makes repeated test runs faster. It compares screenshots to cached results. When the screen did not change much, TestDriver uses the cached element positions again. It does not make an AI call.
10
-
11
- The cache works at two levels:
12
- - **Screen cache**: a pixel diff comparison between the present screenshot and the cached screenshot
13
- - **Element cache**: OpenCV template matching to make sure that the cached element position is still correct
14
-
15
- ## How It Works
16
-
17
- 1. On `find()`, the SDK sends the present screenshot and the cache metadata to the API.
18
- 2. The API compares the screenshot against the cached results for the same `cacheKey`.
19
- 3. If the screen pixel diff is in the `screen` threshold AND the element template match is more than the `element` threshold, TestDriver returns the cached position.
20
- 4. If not, TestDriver makes a new AI call and caches the result.
21
-
22
- ```mermaid
23
- flowchart LR
24
- A[Screenshot + cacheKey] --> B{Screen Diff\n< threshold?}
25
- B -- Yes --> C{Template\nMatch OK?}
26
- C -- Yes --> D[Return cached position]
27
- B -- No --> E[AI Call - fresh]
28
- C -- No --> F[AI Call - fresh]
29
- ```
30
-
31
- ## Configuration
32
-
33
- ### Constructor Options
9
+ For how caching works and when it helps, see [Speed up reruns with caching](/caching).
34
10
 
35
11
  ```javascript
36
- const testdriver = new TestDriver({
12
+ const testdriver = TestDriver(context, {
37
13
  cache: {
38
- enabled: true,
39
14
  thresholds: {
40
- find: {
41
- screen: 0.05, // 5% pixel diff allowed (default)
42
- element: 0.8, // 80% OpenCV correlation required (default)
43
- },
44
- assert: 0.05, // 5% pixel diff for assertions (default)
15
+ find: { screen: 0.05, element: 0.8 },
16
+ assert: 0.05,
45
17
  },
46
18
  },
47
- cacheKey: 'my-custom-key', // overrides auto-generated key
19
+ cacheKey: 'checkout-flow',
48
20
  });
49
21
  ```
50
22
 
51
- <ParamField path="cache" type="CacheConfig | false">
52
- Cache configuration object, or `false` to disable entirely.
23
+ ## Client options
53
24
 
54
- <Expandable title="properties">
55
- <ParamField path="enabled" type="boolean" default={true}>
56
- Enable or disable the cache system. Requires a valid `cacheKey` to actually activate.
57
- </ParamField>
58
-
59
- <ParamField path="thresholds" type="CacheThresholds">
60
- Threshold configuration for different command types.
25
+ Pass these to `TestDriver(context, options)` or `new TestDriver(options)`. They apply to every call the client makes.
61
26
 
27
+ <ParamField path="cache" type="boolean | object" default="true">
28
+ Pass `false` to turn the cache off. Pass an object to change the match thresholds.
29
+
30
+ <Expandable title="properties">
31
+ <ParamField path="thresholds" type="object">
62
32
  <Expandable title="properties">
63
- <ParamField path="find" type="FindCacheThresholds">
33
+ <ParamField path="find" type="object">
64
34
  Thresholds for `find()` and `findAll()`.
65
35
 
66
36
  <Expandable title="properties">
67
- <ParamField path="screen" type="number" default={0.05}>
68
- Maximum pixel diff percentage allowed between the current screenshot and the cached screenshot. Lower values require a closer match. Range: `0` to `1`.
37
+ <ParamField path="screen" type="number" default="0.05">
38
+ The largest share of pixels that may differ between the current screen and the cached screen, from `0` to `1`. `0.05` allows a 5% difference. Lower values require a closer match.
69
39
  </ParamField>
70
-
71
- <ParamField path="element" type="number" default={0.8}>
72
- Minimum OpenCV template matching correlation required for the cached element crop. Higher values require a closer match. Range: `0` to `1`. Only used for `find()`, not `findAll()`.
40
+
41
+ <ParamField path="element" type="number" default="0.8">
42
+ How closely the cached image of the element must match what's on screen now, from `0` to `1`. Higher values require a closer match. Used by `find()` only, not `findAll()`.
73
43
  </ParamField>
74
44
  </Expandable>
75
45
  </ParamField>
76
-
77
- <ParamField path="assert" type="number" default={0.05}>
78
- Maximum pixel diff allowed for assertion cache hits.
46
+
47
+ <ParamField path="assert" type="number" default="0.05">
48
+ The largest share of pixels that may differ for `assert()` to reuse a cached result, from `0` to `1`.
79
49
  </ParamField>
80
50
  </Expandable>
81
51
  </ParamField>
@@ -83,139 +53,162 @@ const testdriver = new TestDriver({
83
53
  </ParamField>
84
54
 
85
55
  <ParamField path="cacheKey" type="string">
86
- Unique key for cache lookups. If not provided, an auto-generated key is created from a SHA-256 hash of the calling test file (first 16 hex characters). The cache key changes automatically when your test file changes, providing automatic cache invalidation.
56
+ The key cache entries are stored under. By default, TestDriver generates one from the test file. See [Cache keys](#cache-keys).
57
+ </ParamField>
58
+
59
+ <ParamField path="cacheThreshold" type="object">
60
+ **Deprecated.** Use `cache.thresholds` instead.
87
61
  </ParamField>
88
62
 
89
- ### Disabling Cache
63
+ ## Per-call options
90
64
 
91
- ```javascript
92
- // Via constructor
93
- const testdriver = new TestDriver({ cache: false });
65
+ Override the client settings for a single call.
66
+
67
+ ### find()
94
68
 
95
- // Via environment variable
96
- // TD_NO_CACHE=true vitest run
69
+ ```javascript
70
+ const priceLabel = await testdriver.find('Total price label', {
71
+ cacheKey: 'checkout-flow',
72
+ cache: { thresholds: { screen: 0.01, element: 0.95 } },
73
+ });
97
74
  ```
98
75
 
99
- When cache is disabled, all thresholds are set to `-1` internally, causing the API to skip cache lookups.
76
+ <ParamField path="cacheKey" type="string">
77
+ Use this key for this call instead of the client's key.
78
+ </ParamField>
100
79
 
101
- ### Per-Command Overrides
80
+ <ParamField path="cache.thresholds.screen" type="number">
81
+ Overrides `cache.thresholds.find.screen` for this call.
82
+ </ParamField>
102
83
 
103
- Override cache thresholds for individual commands:
84
+ <ParamField path="cache.thresholds.element" type="number">
85
+ Overrides `cache.thresholds.find.element` for this call.
86
+ </ParamField>
87
+
88
+ ### findAll()
89
+
90
+ `findAll()` takes `cacheKey` and `cache.thresholds.screen`. It doesn't use the `element` threshold.
104
91
 
105
92
  ```javascript
106
- // Stricter screen matching for this specific find
107
- const el = await testdriver.find('submit button', {
108
- cache: {
109
- thresholds: { screen: 0.01, element: 0.95 },
110
- },
93
+ const productCards = await testdriver.findAll('Product card in the results grid', {
94
+ cache: { thresholds: { screen: 0.02 } },
111
95
  });
96
+ ```
112
97
 
113
- // Custom cache key for a specific assertion
114
- await testdriver.assert('dashboard loaded', {
115
- cache: { threshold: 0.01 },
116
- cacheKey: 'dashboard-check',
98
+ ### assert()
99
+
100
+ ```javascript
101
+ await testdriver.assert('the order confirmation is visible', {
102
+ cacheKey: 'checkout-flow',
103
+ threshold: 0.01,
117
104
  });
118
105
  ```
119
106
 
120
- ## Threshold Priority
107
+ <ParamField path="cacheKey" type="string">
108
+ Use this key for this call instead of the client's key.
109
+ </ParamField>
121
110
 
122
- Thresholds are resolved in priority order (highest wins):
111
+ <ParamField path="threshold" type="number">
112
+ Overrides `cache.thresholds.assert` for this call.
113
+ </ParamField>
123
114
 
124
- | Priority | Source | Example |
125
- |----------|--------|---------|
126
- | 1 (highest) | Per-command option | `find(desc, { cache: { thresholds: { screen: 0.1 } } })` |
127
- | 2 | Legacy number argument | `find(desc, 0.1)` |
128
- | 3 | Global constructor config | `new TestDriver({ cache: { thresholds: { find: { screen: 0.1 } } } })` |
129
- | 4 (lowest) | Hard-coded defaults | `screen: 0.05`, `element: 0.8`, `assert: 0.05` |
115
+ ## Threshold priority
130
116
 
131
- ## Auto-Generated Cache Key
117
+ When a threshold is set in more than one place, the most specific wins:
132
118
 
133
- When you don't specify a `cacheKey`, the SDK automatically generates one:
119
+ 1. The per-call option, such as `find(description, { cache: { thresholds: { screen: 0.1 } } })`
120
+ 2. A legacy number argument, such as `find(description, 0.1)`
121
+ 3. The client option, `cache.thresholds`
122
+ 4. The defaults: `screen` 0.05, `element` 0.8, `assert` 0.05
134
123
 
135
- 1. Walks the call stack to find your test file
136
- 2. Reads the file content
137
- 3. Computes a **SHA-256 hash** of the content
138
- 4. Uses the **first 16 hex characters** as the cache key
124
+ ## Cache keys
139
125
 
140
- This means:
141
- - **Same test file** → same cache key → cache hits
142
- - **Modified test file** → different hash → automatic cache invalidation
143
- - **Different test files** → different keys → isolated caches
126
+ Cache entries are stored under a key. By default, TestDriver generates the key from the test file:
144
127
 
145
- ```javascript
146
- // Auto-generated cache key from test file hash
147
- const testdriver = new TestDriver();
148
- // cacheKey = "a3f2b1c4d5e6f7a8" (auto)
128
+ - It hashes the contents of the file that creates the client (SHA-256, first 16 hex characters).
129
+ - Editing the file changes the hash, so the file starts with a fresh cache.
130
+ - Each test file gets its own cache.
131
+
132
+ Set `cacheKey` to keep a cache across edits, or to share one between files that use the same screens:
149
133
 
150
- // Manual override
151
- const testdriver = new TestDriver({ cacheKey: 'login-test-v2' });
134
+ ```javascript
135
+ const testdriver = TestDriver(context, { cacheKey: 'checkout-flow' });
152
136
  ```
153
137
 
154
- ## Template Matching (OpenCV)
138
+ If TestDriver can't read the test file, it can't generate a key. `find()` and `findAll()` then skip the cache unless you set `cacheKey`.
155
139
 
156
- Element cache validation uses OpenCV's normalized cross-correlation coefficient (`TM_CCOEFF_NORMED`) to verify that the cached element is still visible at the expected position.
140
+ ## What must match
157
141
 
158
- **Algorithm:**
159
- 1. Load the cached element crop (needle) and current screenshot (haystack)
160
- 2. Run `cv.matchTemplate()` with `TM_CCOEFF_NORMED`
161
- 3. Binary threshold at the configured element threshold
162
- 4. Find contours to extract match positions
163
- 5. Return matches with `{ x, y, width, height, centerX, centerY }`
142
+ A cached entry is reused only when all of these match the run that created it:
164
143
 
165
- **Scale factors tried:** `[1, 0.5, 2, 0.75, 1.25, 1.5]`
166
- **Thresholds tried:** `[0.9, 0.8, 0.7]` (picks highest matching threshold)
144
+ - The cache key.
145
+ - The exact description passed to `find()`, or the exact assertion text.
146
+ - The sandbox OS and screen resolution.
167
147
 
168
- This accounts for minor scaling differences between screenshots taken at different times or resolutions.
148
+ Entries become usable only after the test that created them passes.
169
149
 
170
- ## Cache Partitioning
150
+ ## Turn the cache off
171
151
 
172
- Cache entries are partitioned by:
173
- - **`cacheKey`** — identifies the test file
174
- - **`os`** — operating system (linux, windows, darwin)
175
- - **`resolution`** — screen resolution
152
+ Turn the cache off for one client:
153
+
154
+ ```javascript
155
+ const testdriver = TestDriver(context, { cache: false });
156
+ ```
176
157
 
177
- This means cache from a Linux run won't be used for a Windows run, even with the same cache key.
158
+ Or for a whole run:
178
159
 
179
- ## Debugging Cache
160
+ ```bash
161
+ TD_NO_CACHE=true npx vitest run
162
+ ```
180
163
 
181
- API responses include cache metadata:
164
+ <Warning>
165
+ `cache: { enabled: false }` doesn't turn the cache off. Use `cache: false` or `TD_NO_CACHE=true`.
166
+ </Warning>
182
167
 
183
- | Field | Description |
184
- |---|---|
185
- | `cacheHit` | `true` if cache was used |
186
- | `similarity` | Pixel diff percentage between screenshots |
187
- | `cacheSimilarity` | OpenCV template match score |
168
+ ## Inspect a result
188
169
 
189
- Use `getDebugInfo()` on an element to inspect cache results:
170
+ Read the cache details from the element that `find()` returns:
190
171
 
191
172
  ```javascript
192
- const el = await testdriver.find('submit button');
193
- const debug = el.getDebugInfo();
194
- console.log(debug);
195
- // { cacheHit: true, similarity: 0.02, cacheSimilarity: 0.92, ... }
173
+ const submitButton = await testdriver.find('Submit button');
174
+ const { cache } = submitButton.toJSON();
196
175
  ```
197
176
 
198
- ## Types
199
-
200
- ```typescript
201
- interface CacheConfig {
202
- enabled?: boolean; // Default: true
203
- thresholds?: CacheThresholds;
204
- }
205
-
206
- interface CacheThresholds {
207
- find?: FindCacheThresholds;
208
- assert?: number; // Default: 0.05
209
- }
210
-
211
- interface FindCacheThresholds {
212
- screen?: number; // Default: 0.05
213
- element?: number; // Default: 0.8
214
- }
215
-
216
- interface CacheDebugInfo {
217
- cacheHit: boolean;
218
- similarity: number;
219
- cacheSimilarity: number;
220
- }
221
- ```
177
+ <ResponseField name="cache" type="object">
178
+ <Expandable title="properties">
179
+ <ResponseField name="hit" type="boolean">
180
+ `true` when the location came from the cache.
181
+ </ResponseField>
182
+ <ResponseField name="strategy" type="string">
183
+ How the cached entry was matched.
184
+ </ResponseField>
185
+ <ResponseField name="createdAt" type="string">
186
+ When the cached entry was created.
187
+ </ResponseField>
188
+ <ResponseField name="diffPercent" type="number">
189
+ The share of pixels that differed between the current screen and the cached screen, from `0` to `1`.
190
+ </ResponseField>
191
+ <ResponseField name="imageUrl" type="string">
192
+ A link to the cached screenshot.
193
+ </ResponseField>
194
+ </Expandable>
195
+ </ResponseField>
196
+
197
+ To browse or clear your team's cached entries, open the [Cache page in the TestDriver console](https://console.testdriver.ai/cache).
198
+
199
+ ## Related
200
+
201
+ <CardGroup cols={2}>
202
+ <Card title="Caching" icon="brain" href="/caching">
203
+ How the cache works and when it helps.
204
+ </Card>
205
+ <Card title="Options" icon="sliders" href="/options">
206
+ Every client option, with its default.
207
+ </Card>
208
+ <Card title="find()" icon="magnifying-glass" href="/find">
209
+ Locate an element by describing it.
210
+ </Card>
211
+ <Card title="assert()" icon="check" href="/assert">
212
+ Check the screen with an AI assertion.
213
+ </Card>
214
+ </CardGroup>
@@ -1,132 +1,142 @@
1
1
  ---
2
2
  name: testdriver:caching
3
- description: How TestDriver learns your app and caches what it discovers for instant, deterministic replays
3
+ description: Reuse element locations from passing runs to skip the AI when the screen is unchanged.
4
4
  ---
5
5
  <!-- Generated from caching.mdx. DO NOT EDIT. -->
6
6
 
7
- After the agent [explored your app](/generating-tests), TestDriver keeps what it found. TestDriver caches each element that the AI vision agent finds. It uses a vision fingerprint. This is a perceptual hash of the screen state at the element location. On the next run, TestDriver matches against that cache. It does not call the AI again. Tests that pass replay quickly, in the same way each time, and at a low cost.
7
+ After a test passes, TestDriver remembers where it found each element.
8
8
 
9
- This learning makes TestDriver fast. The cache makes the test run a maximum of **1.7x faster**. It does not do the same AI vision analysis again. The agent thinks only when it sees something new.
9
+ - When the screen looks the same on a later run, `find()` reuses that location instead of asking the AI.
10
+ - The step is faster, cheaper, and gives the same result every time.
11
+ - When the screen changes, TestDriver falls back to the AI and learns the new location.
10
12
 
13
+ Caching is on by default. You don't need to configure anything.
11
14
 
12
- ```javascript
13
- // First run: builds cache
14
- await testdriver.find('submit button');
15
+ ## How caching works
15
16
 
16
- // Second run: exact match
17
- await testdriver.find('submit button');
18
- ```
17
+ 1. **The first run learns.** Each `find()` asks the AI to locate the element. TestDriver saves the result with an image of the screen and of the element.
18
+ 2. **A passing run confirms.** Saved entries become usable only once the test passes. A failing run never teaches TestDriver a wrong location.
19
+ 3. **Later runs reuse.** On the next run, `find()` compares the current screen with the saved one. TestDriver returns the saved location without calling the AI when both are true:
20
+ - The screen differs by no more than 5% of its pixels.
21
+ - The saved image of the element still matches what's at that spot.
19
22
 
20
- ## Automatic Caching
23
+ Otherwise, it asks the AI and saves a new entry.
21
24
 
22
- TestDriver enables learning automatically. You do not need configuration. TestDriver computes the cache key from these. The cache key is the fingerprint that TestDriver uses to know what it learned:
25
+ `assert()` is cached the same way. When the screen matches a confirmed earlier run, the saved result is reused.
23
26
 
24
- - **File hash**: The SHA-256 hash of the test file contents
25
- - **Selector prompt**: The exact text description that you give to `find()`
26
- - **Screenshot context**: The perceptual hash of the present screen state
27
- - **Platform**: The operating system and the browser version
27
+ ## What has to match
28
28
 
29
- When you change your test file, the hash changes automatically. This makes the old cache entries not valid. Then TestDriver does a new AI analysis with your new test logic.
29
+ A saved entry is reused only when all of these match the run that created it:
30
30
 
31
- ```javascript
32
- import { test } from 'vitest';
33
- import { chrome } from 'testdriverai/presets';
31
+ - **The test file.** The cache is keyed on a hash of the test file's contents, so editing the file starts a fresh cache. A changed test can't reuse results that no longer apply.
32
+ - **The description.** The text you pass to `find()` must match exactly.
33
+ - **The OS and screen resolution** of the sandbox.
34
34
 
35
- test('auto-cached test', async (context) => {
36
- const { testdriver } = await chrome(context, {
37
- url: 'https://example.com'
38
- });
35
+ ## Keep changing values out of descriptions
39
36
 
40
- // First call: AI analyzes screen, saves to cache
41
- await testdriver.find('More information link'); // 2.1s
37
+ The description must match exactly. A description with a value that changes between runs misses the cache every time:
42
38
 
43
- // Second call: cache hit, instant response
44
- await testdriver.find('More information link'); // 12ms ⚡
45
- });
39
+ ```javascript
40
+ // Misses the cache whenever the email changes
41
+ const emailField = await testdriver.find(`input next to ${email}`);
46
42
  ```
47
43
 
48
- ## Managing the Cache
44
+ Describe the element itself, and pass the changing value to the action instead:
49
45
 
50
- You can clear the cache in the TestDriver console. There, you also find previews of cached elements, the input prompts, and analytics on the cache hit rates.
46
+ ```javascript
47
+ // Same description every run, so it can be cached
48
+ const emailField = await testdriver.find('Email input field');
49
+ await emailField.click();
50
+ await testdriver.type(email);
51
+ ```
51
52
 
52
- <Card href="https://console.testdriver.ai/cache" title="TestDriver Cache" icon="database">
53
- Manage and clear your test cache from the TestDriver console.
54
- </Card>
53
+ ## Choose your own cache key
55
54
 
56
- ## Debugging Cache Hits and Misses
55
+ By default, each test file has its own cache, which resets when you edit the file.
57
56
 
58
- You can track what TestDriver has learned by inspecting cache performance in your tests:
57
+ Set a `cacheKey` when you create the client to keep the cache across edits, or to share it between files that use the same screens:
59
58
 
60
59
  ```javascript
61
- test('monitor cache performance', async (context) => {
62
- const { testdriver } = await chrome(context, { url });
63
-
64
- const element = await testdriver.find('submit button');
65
-
66
- if (element.cacheHit) {
67
- console.log('✅ Cache hit - instant response');
68
- console.log('Strategy:', element.cacheStrategy); // 'exact', 'pixeldiff', or 'template'
69
- console.log('Similarity:', `${(element.similarity * 100).toFixed(1)}%`);
70
- console.log('Cache age:', element.cacheCreatedAt);
71
- } else {
72
- console.log('⏱️ Cache miss - AI analysis performed');
73
- console.log('New cache entry created');
74
- }
75
- });
60
+ const testdriver = TestDriver(context, { cacheKey: 'checkout-flow' });
76
61
  ```
77
62
 
78
- ## Configuring the Cache
63
+ You can also pass `cacheKey` to a single `find()` call.
64
+
65
+ A stable key doesn't make TestDriver reuse a location for a changed page. Entries are still reused only when the description, OS, and resolution match and the screen looks the same.
66
+
67
+ ## Adjust how closely the screen must match
79
68
 
80
- You can configure how TestDriver learns globally when initializing TestDriver:
69
+ Two thresholds control when a saved location is reused:
70
+
71
+ | Threshold | Default | Meaning |
72
+ | --- | --- | --- |
73
+ | `screen` | `0.05` | The largest share of pixels that may differ from the saved screen (5%) |
74
+ | `element` | `0.8` | How closely the saved element image must match what's on screen now (0 to 1) |
75
+
76
+ Set them for every call when you create the client:
81
77
 
82
78
  ```javascript
83
- import { TestDriver } from 'testdriverai';
84
-
85
- const testdriver = new TestDriver({
86
- apiKey: process.env.TD_API_KEY,
87
- cacheKey: 'my-test-suite', // cache-key for this instance
88
- cacheDefaults: {
89
- threshold: 0.05, // 95% similarity
90
- }
79
+ const testdriver = TestDriver(context, {
80
+ cache: {
81
+ thresholds: {
82
+ find: { screen: 0.02, element: 0.9 },
83
+ assert: 0.02,
84
+ },
85
+ },
91
86
  });
92
87
  ```
93
88
 
94
- It's also possible to override cache settings per `find()` call:
89
+ Or override them for one call:
95
90
 
96
91
  ```javascript
97
- // Default: 95% similarity required
98
- await testdriver.find('submit button');
99
-
100
- // Explicit strict threshold
101
- await testdriver.find('submit button', {
102
- cacheThreshold: 0.01 // 99% similarity
92
+ const priceLabel = await testdriver.find('Total price label', {
93
+ cache: { thresholds: { screen: 0.01 } },
103
94
  });
104
95
  ```
105
96
 
106
- ## Caching with Variables
97
+ Lower `screen` and higher `element` values make reuse stricter. That helps on screens where small details matter, but costs more AI calls.
107
98
 
108
- Custom cache keys prevent cache pollution when using variables in prompts, dramatically improving cache hit rates—so TestDriver reuses what it learned even when your data changes.
99
+ For every cache option, see [Configure the cache](/cache).
100
+
101
+ ## Turn caching off
102
+
103
+ Disable caching for a client with `cache: false`, or for a whole run with `TD_NO_CACHE`:
109
104
 
110
105
  ```javascript
111
- // ❌ Without cache key - creates new cache for each variable value
112
- const email = 'user@example.com';
113
- await testdriver.find(`input for ${email}`); // Cache miss every time
114
-
115
- // ✅ With cache key - reuses cache regardless of variable
116
- const email = 'user@example.com';
117
- await testdriver.find(`input for ${email}`, {
118
- cacheKey: 'email-input'
119
- });
106
+ const testdriver = TestDriver(context, { cache: false });
107
+ ```
120
108
 
121
- // Also useful for dynamic IDs, names, or other changing data
122
- const orderId = generateOrderId();
123
- await testdriver.find(`order ${orderId} status`, {
124
- cacheKey: 'order-status' // Same cache for all orders
125
- });
109
+ ```bash
110
+ TD_NO_CACHE=true npx vitest run
126
111
  ```
127
112
 
128
- ## Next
113
+ ## See what's cached
114
+
115
+ The [Cache page in the TestDriver console](https://console.testdriver.ai/cache) lists your team's cached elements and assertions. It shows a preview and the description for each, and lets you clear entries.
116
+
117
+ To check a single `find()` in your test, read the cache details from the element:
118
+
119
+ ```javascript
120
+ const submitButton = await testdriver.find('Submit button');
121
+ const { cache } = submitButton.toJSON();
122
+
123
+ console.log(cache.hit); // true when the location came from the cache
124
+ console.log(cache.strategy); // how the cached entry was matched
125
+ ```
129
126
 
130
- <Card href="/copilot/running-tests" title="Run" icon="play">
131
- Now that TestDriver has learned your app, run your tests in CI and locally—replaying the cache for fast, deterministic results.
132
- </Card>
127
+ ## Next steps
128
+
129
+ <CardGroup cols={2}>
130
+ <Card title="Configure the cache" icon="sliders" href="/cache">
131
+ Every cache option, threshold, and override.
132
+ </Card>
133
+ <Card title="Locate elements" icon="crosshairs" href="/locating-elements">
134
+ Write descriptions that find the right element and cache well.
135
+ </Card>
136
+ <Card title="Run tests" icon="play" href="/copilot/running-tests">
137
+ Run your tests locally and in parallel.
138
+ </Card>
139
+ <Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
140
+ Run cached tests on every pull request.
141
+ </Card>
142
+ </CardGroup>