testdriverai 7.0.0 → 7.1.0

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 (112) hide show
  1. package/AGENTS.md +550 -0
  2. package/CODEOWNERS +0 -1
  3. package/README.md +126 -0
  4. package/agent/index.js +43 -18
  5. package/agent/lib/commands.js +794 -135
  6. package/agent/lib/redraw.js +124 -39
  7. package/agent/lib/sandbox.js +10 -1
  8. package/agent/lib/sdk.js +21 -0
  9. package/docs/MIGRATION.md +425 -0
  10. package/docs/PRESETS.md +210 -0
  11. package/docs/docs.json +91 -37
  12. package/docs/guide/best-practices-polling.mdx +154 -0
  13. package/docs/v7/api/dashcam.mdx +497 -0
  14. package/docs/v7/api/doubleClick.mdx +102 -0
  15. package/docs/v7/api/mouseDown.mdx +161 -0
  16. package/docs/v7/api/mouseUp.mdx +164 -0
  17. package/docs/v7/api/rightClick.mdx +123 -0
  18. package/docs/v7/getting-started/configuration.mdx +380 -0
  19. package/docs/v7/getting-started/quickstart.mdx +273 -140
  20. package/docs/v7/guides/best-practices.mdx +486 -0
  21. package/docs/v7/guides/caching-ai.mdx +215 -0
  22. package/docs/v7/guides/caching-selectors.mdx +292 -0
  23. package/docs/v7/guides/caching.mdx +366 -0
  24. package/docs/v7/guides/ci-cd/azure.mdx +587 -0
  25. package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
  26. package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
  27. package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
  28. package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
  29. package/docs/v7/guides/ci-cd/travis.mdx +438 -0
  30. package/docs/v7/guides/debugging.mdx +349 -0
  31. package/docs/v7/guides/faq.mdx +393 -0
  32. package/docs/v7/guides/performance.mdx +517 -0
  33. package/docs/v7/guides/troubleshooting.mdx +526 -0
  34. package/docs/v7/guides/vitest-plugin.mdx +477 -0
  35. package/docs/v7/guides/vitest.mdx +535 -0
  36. package/docs/v7/platforms/linux.mdx +308 -0
  37. package/docs/v7/platforms/macos.mdx +433 -0
  38. package/docs/v7/platforms/windows.mdx +430 -0
  39. package/docs/v7/presets/chrome-extension.mdx +223 -0
  40. package/docs/v7/presets/chrome.mdx +287 -0
  41. package/docs/v7/presets/electron.mdx +435 -0
  42. package/docs/v7/presets/vscode.mdx +398 -0
  43. package/docs/v7/presets/webapp.mdx +396 -0
  44. package/docs/v7/progressive-apis/CORE.md +459 -0
  45. package/docs/v7/progressive-apis/HOOKS.md +360 -0
  46. package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
  47. package/docs/v7/progressive-apis/PROVISION.md +266 -0
  48. package/interfaces/vitest-plugin.mjs +186 -100
  49. package/package.json +12 -1
  50. package/sdk.d.ts +335 -42
  51. package/sdk.js +756 -95
  52. package/src/core/Dashcam.js +469 -0
  53. package/src/core/index.d.ts +150 -0
  54. package/src/core/index.js +12 -0
  55. package/src/presets/index.mjs +331 -0
  56. package/src/vitest/extended.mjs +108 -0
  57. package/src/vitest/hooks.d.ts +119 -0
  58. package/src/vitest/hooks.mjs +298 -0
  59. package/src/vitest/index.mjs +64 -0
  60. package/src/vitest/lifecycle.mjs +277 -0
  61. package/src/vitest/utils.mjs +150 -0
  62. package/test/dashcam.test.js +137 -0
  63. package/testdriver/acceptance-sdk/assert.test.mjs +13 -31
  64. package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
  65. package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
  66. package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +7 -19
  67. package/testdriver/acceptance-sdk/element-not-found.test.mjs +6 -19
  68. package/testdriver/acceptance-sdk/exec-js.test.mjs +6 -18
  69. package/testdriver/acceptance-sdk/exec-output.test.mjs +8 -20
  70. package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +13 -25
  71. package/testdriver/acceptance-sdk/focus-window.test.mjs +8 -20
  72. package/testdriver/acceptance-sdk/formatted-logging.test.mjs +5 -20
  73. package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
  74. package/testdriver/acceptance-sdk/hover-image.test.mjs +10 -19
  75. package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +7 -19
  76. package/testdriver/acceptance-sdk/hover-text.test.mjs +5 -19
  77. package/testdriver/acceptance-sdk/match-image.test.mjs +7 -19
  78. package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
  79. package/testdriver/acceptance-sdk/press-keys.test.mjs +5 -19
  80. package/testdriver/acceptance-sdk/prompt.test.mjs +6 -18
  81. package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +6 -20
  82. package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +6 -18
  83. package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +9 -23
  84. package/testdriver/acceptance-sdk/scroll.test.mjs +12 -21
  85. package/testdriver/acceptance-sdk/setup/testHelpers.mjs +124 -352
  86. package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
  87. package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
  88. package/testdriver/acceptance-sdk/type.test.mjs +19 -58
  89. package/vitest.config.mjs +1 -0
  90. package/.vscode/mcp.json +0 -9
  91. package/MIGRATION.md +0 -389
  92. package/PLUGIN_MIGRATION.md +0 -222
  93. package/PROMPT_CACHE.md +0 -200
  94. package/SDK_LOGGING.md +0 -222
  95. package/SDK_MIGRATION.md +0 -474
  96. package/SDK_README.md +0 -1122
  97. package/debug-screenshot-1763401388589.png +0 -0
  98. package/examples/run-tests-with-recording.sh +0 -70
  99. package/examples/screenshot-example.js +0 -63
  100. package/examples/sdk-awesome-logs-demo.js +0 -177
  101. package/examples/sdk-cache-thresholds.js +0 -96
  102. package/examples/sdk-element-properties.js +0 -155
  103. package/examples/sdk-simple-example.js +0 -65
  104. package/examples/test-recording-example.test.js +0 -166
  105. package/mcp-server/AI_GUIDELINES.md +0 -57
  106. package/test-find-api.js +0 -73
  107. package/test-prompt-cache.js +0 -96
  108. package/test-sandbox-render.js +0 -28
  109. package/test-sdk-methods.js +0 -15
  110. package/test-sdk-refactor.js +0 -53
  111. package/test-stack-trace.mjs +0 -57
  112. package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +0 -239
@@ -0,0 +1,292 @@
1
+ ---
2
+ title: "Selector Caching"
3
+ sidebarTitle: "Selector Caching"
4
+ description: "How TestDriver caches element locations for faster tests"
5
+ icon: "crosshairs"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ The Selector Cache stores element locations on the server, so `.find()` calls can skip the AI vision analysis.
11
+
12
+ This provides:
13
+ - ⚡ **Up to 10x faster** - Skip AI vision analysis
14
+ - 💰 **Lower AI costs** - Fewer vision API calls
15
+ - 🎯 **Consistent results** - Same UI = same coordinates
16
+ - 📊 **Metrics tracking** - See cache hit rates in console
17
+
18
+ ## How It Works
19
+
20
+ ```mermaid
21
+ sequenceDiagram
22
+ participant Test as Your Test
23
+ participant SDK as TestDriver SDK
24
+ participant API as TestDriver API
25
+ participant AI as Claude Vision
26
+ participant Cache as Selector Cache DB
27
+
28
+ Test->>SDK: testdriver.find('submit button')
29
+ SDK->>API: POST /locate (screenshot + prompt)
30
+
31
+ API->>Cache: Check for matching cache entry
32
+
33
+ alt Cache Hit (95%+ similar screenshot)
34
+ Cache-->>API: Return cached coordinates
35
+ API-->>SDK: {x, y, cacheHit: true}
36
+ SDK-->>Test: Element found (instant)
37
+ else Cache Miss
38
+ API->>AI: Analyze screenshot
39
+ AI-->>API: Element coordinates
40
+ API->>Cache: Save new cache entry
41
+ API-->>SDK: {x, y, cacheHit: false}
42
+ SDK-->>Test: Element found
43
+ end
44
+ ```
45
+
46
+ ## Cache Matching Strategy
47
+
48
+ The selector cache uses a three-tier matching system:
49
+
50
+ 1. **Exact Hash Match** (Fastest)
51
+ - Perceptual hash comparison
52
+ - Same screenshot = instant match
53
+ - 0% difference threshold
54
+
55
+ 2. **Pixel Diff Match** (Fast)
56
+ - 80%+ perceptual hash similarity
57
+ - Pixel-by-pixel comparison
58
+ - Default 5% difference threshold (95% similarity)
59
+ - Configurable per call
60
+
61
+ 3. **Template Match** (Fallback)
62
+ - Edge detection + template matching
63
+ - Finds visually similar UI elements
64
+ - 75%+ confidence threshold
65
+
66
+ ## Controlling Cache Threshold
67
+
68
+ Adjust similarity threshold per call:
69
+
70
+ ```javascript
71
+ // Default: 95% similarity (5% difference allowed)
72
+ await testdriver.find('submit button');
73
+
74
+ // Stricter: 99% similarity (1% difference allowed)
75
+ await testdriver.find('submit button', { threshold: 0.01 });
76
+
77
+ // More lenient: 90% similarity (10% difference allowed)
78
+ await testdriver.find('submit button', { threshold: 0.10 });
79
+
80
+ // Disable cache: force fresh AI analysis
81
+ await testdriver.find('submit button', { threshold: -1 });
82
+ ```
83
+
84
+ ## Cache Filtering
85
+
86
+ The selector cache automatically filters by:
87
+
88
+ - **Prompt** - Exact text match (case-insensitive)
89
+ - **Team** - Your team ID
90
+ - **OS** - Operating system (if specified)
91
+ - **Resolution** - Screen resolution (if specified)
92
+ - **Time Window** - Last 7 days by default
93
+
94
+ ## Viewing Cache Entries
95
+
96
+ View all cached selectors at [console.testdriver.ai](https://console.testdriver.ai)
97
+
98
+ The console shows:
99
+ - Cached screenshots with green circles on found elements
100
+ - Original prompts
101
+ - Hit count (how many times cache was used)
102
+ - Similarity scores
103
+ - Cache age and last accessed time
104
+
105
+ ## Cache Statistics
106
+
107
+ Each cache entry tracks:
108
+
109
+ - **Hit Count** - Number of times cache was used
110
+ - **Last Hit** - When cache was last accessed
111
+ - **Similarity** - Percentage match to original
112
+ - **Created At** - When entry was created
113
+ - **Element Type** - button, input, link, etc.
114
+ - **Element Bounds** - Bounding box coordinates
115
+
116
+ ## Usage Examples
117
+
118
+ ### Basic Selector Caching
119
+
120
+ ```javascript
121
+ import { test } from 'vitest';
122
+ import { chrome } from 'testdriverai/presets';
123
+
124
+ test('find element', async (context) => {
125
+ const { testdriver } = await chrome(context, {
126
+ url: 'https://example.com'
127
+ });
128
+
129
+ // First call: AI vision analysis, saves to cache
130
+ const button = await testdriver.find('More information link');
131
+ console.log('Cache hit:', button.cacheHit); // false
132
+
133
+ // Second call: uses cache (instant)
134
+ const button2 = await testdriver.find('More information link');
135
+ console.log('Cache hit:', button2.cacheHit); // true
136
+ });
137
+ ```
138
+
139
+ ### Dynamic Threshold Example
140
+
141
+ ```javascript
142
+ test('strict vs lenient matching', async (context) => {
143
+ const { testdriver } = await chrome(context, { url });
144
+
145
+ // Strict: 99% similarity required
146
+ const elem1 = await testdriver.find('button', { threshold: 0.01 });
147
+
148
+ // Lenient: 90% similarity acceptable
149
+ const elem2 = await testdriver.find('button', { threshold: 0.10 });
150
+
151
+ // Bypass cache entirely
152
+ const elem3 = await testdriver.find('button', { threshold: -1 });
153
+ });
154
+ ```
155
+
156
+ ### Checking Cache Hits
157
+
158
+ ```javascript
159
+ test('monitor cache performance', async (context) => {
160
+ const { testdriver } = await chrome(context, { url });
161
+
162
+ const element = await testdriver.find('submit button');
163
+
164
+ if (element.cacheHit) {
165
+ console.log('✅ Cache hit - instant response');
166
+ } else {
167
+ console.log('⏱️ Cache miss - AI analysis performed');
168
+ }
169
+ });
170
+ ```
171
+
172
+ ## Best Practices
173
+
174
+ ### 1. Use Appropriate Thresholds
175
+
176
+ ```javascript
177
+ // Stable UI: strict threshold
178
+ await testdriver.find('logo', { threshold: 0.01 });
179
+
180
+ // Dynamic UI: lenient threshold
181
+ await testdriver.find('news feed item', { threshold: 0.10 });
182
+
183
+ // Always fresh: disable cache
184
+ await testdriver.find('timestamp', { threshold: -1 });
185
+ ```
186
+
187
+ ### 2. Monitor Cache Performance
188
+
189
+ Check [console.testdriver.ai](https://console.testdriver.ai) regularly to:
190
+ - See cache hit rates
191
+ - Identify frequently used selectors
192
+ - Remove stale cache entries
193
+ - Optimize threshold settings
194
+
195
+ ### 3. Clear Cache When UI Changes
196
+
197
+ If your UI changes significantly, delete cache entries through the console dashboard.
198
+
199
+ ### 4. Use Consistent Prompts
200
+
201
+ ```javascript
202
+ // ✅ Good - consistent prompt
203
+ await testdriver.find('submit button');
204
+ await testdriver.find('submit button'); // Cache hit
205
+
206
+ // ❌ Bad - different prompts
207
+ await testdriver.find('submit button');
208
+ await testdriver.find('the submit button'); // Cache miss
209
+ ```
210
+
211
+ ## Cache Storage Details
212
+
213
+ | Property | Value |
214
+ |----------|-------|
215
+ | Location | Server (MongoDB + S3) |
216
+ | Persistence | 7 days default |
217
+ | Scope | Per-team |
218
+ | Matching | Screenshot similarity + prompt |
219
+ | Expiration | 7-day rolling window |
220
+
221
+ ## Troubleshooting
222
+
223
+ ### Cache Not Working
224
+
225
+ Check:
226
+ 1. Threshold isn't too strict (try 0.10 for 90% similarity)
227
+ 2. Screenshot hasn't changed significantly
228
+ 3. OS/resolution matches cached entry
229
+ 4. Cache entry isn't older than 7 days
230
+ 5. Prompt matches exactly (case-insensitive)
231
+
232
+ ### Low Cache Hit Rate
233
+
234
+ If you're seeing low cache hit rates:
235
+
236
+ 1. **Increase threshold** - Try 0.10 (90% similarity) for dynamic UIs
237
+ 2. **Stabilize UI** - Minimize animations, random data, timestamps
238
+ 3. **Use consistent prompts** - Same wording every time
239
+ 4. **Check console** - View similarity scores in dashboard
240
+
241
+ ### Stale Cache Data
242
+
243
+ Delete selector cache entries at [console.testdriver.ai](https://console.testdriver.ai)
244
+
245
+ - Find the cached entry by prompt or screenshot
246
+ - Click delete to remove stale entries
247
+ - Run test again to create fresh cache
248
+
249
+ ### Cache Misses on Identical UI
250
+
251
+ If cache misses occur on seemingly identical screens:
252
+
253
+ 1. **Check resolution** - Cache is resolution-specific
254
+ 2. **Check OS** - Cache is platform-specific
255
+ 3. **Check pixel differences** - Even 1px changes can cause misses with strict thresholds
256
+ 4. **Increase threshold** - Allow more similarity variance
257
+
258
+ ## Advanced Configuration
259
+
260
+ ### Environment Variables
261
+
262
+ ```bash
263
+ # Disable selector cache entirely
264
+ TD_NO_SELECTOR_CACHE=1
265
+
266
+ # Set default threshold globally
267
+ TD_DEFAULT_THRESHOLD=0.10
268
+ ```
269
+
270
+ ### Per-Test Configuration
271
+
272
+ ```javascript
273
+ test('custom cache settings', async (context) => {
274
+ const { testdriver } = await chrome(context, {
275
+ url,
276
+ cacheDefaults: {
277
+ threshold: 0.10, // 90% similarity
278
+ enabled: true
279
+ }
280
+ });
281
+
282
+ // Uses custom defaults
283
+ await testdriver.find('button');
284
+ });
285
+ ```
286
+
287
+ ## See Also
288
+
289
+ - [AI Prompt Caching](/v7/guides/caching-ai) - Cache AI-generated YAML
290
+ - [Console Dashboard](https://console.testdriver.ai) - View and manage selector cache
291
+ - [`.find()` Method](/v7/api/find) - Element location
292
+ - [Vitest Integration](/v7/guides/vitest) - Testing with TestDriver
@@ -0,0 +1,366 @@
1
+ ---
2
+ title: "Caching"
3
+ sidebarTitle: "Caching"
4
+ description: "How TestDriver caches AI responses and element locations for faster tests"
5
+ icon: "bolt"
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ TestDriver uses two types of caching to dramatically speed up your tests and reduce AI costs:
11
+
12
+ 1. **Prompt Cache** - Caches AI-generated commands (`.ai()` responses)
13
+ 2. **Selector Cache** - Caches element locations (`.find()` results)
14
+
15
+ Both caches are enabled by default and work automatically.
16
+
17
+ ## Prompt Cache
18
+
19
+ The Prompt Cache stores AI-generated YAML commands locally, so repeated `.ai()` calls with the same prompt skip the AI entirely.
20
+
21
+ ### How It Works
22
+
23
+ <Steps>
24
+ <Step title="First Call">
25
+ ```javascript
26
+ await testdriver.ai('click the submit button');
27
+ ```
28
+
29
+ - Sends prompt + screenshot to AI
30
+ - Receives YAML commands
31
+ - Saves to `.testdriver/.cache/{prompt-hash}.yaml`
32
+ </Step>
33
+
34
+ <Step title="Subsequent Calls">
35
+ ```javascript
36
+ await testdriver.ai('click the submit button');
37
+ ```
38
+
39
+ - Checks cache first
40
+ - Finds matching cached YAML
41
+ - Uses cached commands (no AI call)
42
+ - Shows `(using cached response)` in output
43
+ </Step>
44
+ </Steps>
45
+
46
+ ### Cache Location
47
+
48
+ Cached prompts are stored locally:
49
+
50
+ ```
51
+ .testdriver/
52
+ .cache/
53
+ click-the-submit-button-a1b2c3d4.yaml
54
+ find-login-form-e5f6a7b8.yaml
55
+ verify-dashboard-c9d0e1f2.yaml
56
+ ```
57
+
58
+ Files are named using:
59
+ - Sanitized prompt (first 50 chars, alphanumeric)
60
+ - MD5 hash of full prompt for uniqueness
61
+
62
+ ### Disabling Prompt Cache
63
+
64
+ Bypass the cache for a specific call:
65
+
66
+ ```javascript
67
+ // Force fresh AI call, bypass cache
68
+ await testdriver.ai('click the submit button', false);
69
+
70
+ // These use cache (default)
71
+ await testdriver.ai('click the submit button');
72
+ await testdriver.ai('click the submit button', true);
73
+ ```
74
+
75
+ ### Clearing Prompt Cache
76
+
77
+ Clear all cached prompts:
78
+
79
+ ```bash
80
+ rm -rf .testdriver/.cache/*.yaml
81
+ ```
82
+
83
+ Or programmatically:
84
+
85
+ ```javascript
86
+ const promptCache = require('testdriverai/agent/lib/cache.js');
87
+ promptCache.clearCache();
88
+ ```
89
+
90
+ ### Benefits
91
+
92
+ - ⚡ **Instant execution** - No AI call needed
93
+ - 💰 **Cost savings** - Reduces API usage
94
+ - 🔌 **Offline testing** - Works without network
95
+ - 🎯 **Deterministic** - Same prompt = same commands
96
+
97
+ ## Selector Cache
98
+
99
+ The Selector Cache stores element locations on the server, so `.find()` calls can skip the AI vision analysis.
100
+
101
+ ### How It Works
102
+
103
+ ```mermaid
104
+ sequenceDiagram
105
+ participant Test as Your Test
106
+ participant SDK as TestDriver SDK
107
+ participant API as TestDriver API
108
+ participant AI as Claude Vision
109
+ participant Cache as Selector Cache DB
110
+
111
+ Test->>SDK: testdriver.find('submit button')
112
+ SDK->>API: POST /locate (screenshot + prompt)
113
+
114
+ API->>Cache: Check for matching cache entry
115
+
116
+ alt Cache Hit (95%+ similar screenshot)
117
+ Cache-->>API: Return cached coordinates
118
+ API-->>SDK: {x, y, cacheHit: true}
119
+ SDK-->>Test: Element found (instant)
120
+ else Cache Miss
121
+ API->>AI: Analyze screenshot
122
+ AI-->>API: Element coordinates
123
+ API->>Cache: Save new cache entry
124
+ API-->>SDK: {x, y, cacheHit: false}
125
+ SDK-->>Test: Element found
126
+ end
127
+ ```
128
+
129
+ ### Cache Matching Strategy
130
+
131
+ The selector cache uses a three-tier matching system:
132
+
133
+ 1. **Exact Hash Match** (Fastest)
134
+ - Perceptual hash comparison
135
+ - Same screenshot = instant match
136
+ - 0% difference threshold
137
+
138
+ 2. **Pixel Diff Match** (Fast)
139
+ - 80%+ perceptual hash similarity
140
+ - Pixel-by-pixel comparison
141
+ - Default 5% difference threshold (95% similarity)
142
+ - Configurable per call
143
+
144
+ 3. **Template Match** (Fallback)
145
+ - Edge detection + template matching
146
+ - Finds visually similar UI elements
147
+ - 75%+ confidence threshold
148
+
149
+ ### Viewing Cache Entries
150
+
151
+ View all cached selectors at [console.testdriver.ai](https://console.testdriver.ai)
152
+
153
+ The console shows:
154
+ - Cached screenshots with green circles on found elements
155
+ - Original prompts
156
+ - Hit count (how many times cache was used)
157
+ - Similarity scores
158
+ - Cache age and last accessed time
159
+
160
+ ### Controlling Cache Threshold
161
+
162
+ Adjust similarity threshold per call:
163
+
164
+ ```javascript
165
+ // Default: 95% similarity (5% difference allowed)
166
+ await testdriver.find('submit button');
167
+
168
+ // Stricter: 99% similarity (1% difference allowed)
169
+ await testdriver.find('submit button', { threshold: 0.01 });
170
+
171
+ // More lenient: 90% similarity (10% difference allowed)
172
+ await testdriver.find('submit button', { threshold: 0.10 });
173
+
174
+ // Disable cache: force fresh AI analysis
175
+ await testdriver.find('submit button', { threshold: -1 });
176
+ ```
177
+
178
+ ### Cache Filtering
179
+
180
+ The selector cache automatically filters by:
181
+
182
+ - **Prompt** - Exact text match (case-insensitive)
183
+ - **Team** - Your team ID
184
+ - **OS** - Operating system (if specified)
185
+ - **Resolution** - Screen resolution (if specified)
186
+ - **Time Window** - Last 7 days by default
187
+
188
+ ### Cache Statistics
189
+
190
+ Each cache entry tracks:
191
+
192
+ - **Hit Count** - Number of times cache was used
193
+ - **Last Hit** - When cache was last accessed
194
+ - **Similarity** - Percentage match to original
195
+ - **Created At** - When entry was created
196
+ - **Element Type** - button, input, link, etc.
197
+ - **Element Bounds** - Bounding box coordinates
198
+
199
+ ### Benefits
200
+
201
+ - ⚡ **Up to 10x faster** - Skip AI vision analysis
202
+ - 💰 **Lower AI costs** - Fewer vision API calls
203
+ - 🎯 **Consistent results** - Same UI = same coordinates
204
+ - 📊 **Metrics tracking** - See cache hit rates in console
205
+
206
+ ## Cache Behavior Examples
207
+
208
+ ### Prompt Cache Example
209
+
210
+ ```javascript
211
+ import { test } from 'vitest';
212
+ import { chrome } from 'testdriverai/presets';
213
+
214
+ test('login flow', async (context) => {
215
+ const { testdriver } = await chrome(context, {
216
+ url: 'https://myapp.com/login'
217
+ });
218
+
219
+ // First call: AI generates commands, saves to cache
220
+ await testdriver.ai('click the login button');
221
+
222
+ // Run test again - uses cache (instant)
223
+ // Look for: "(using cached response)" in output
224
+ });
225
+ ```
226
+
227
+ ### Selector Cache Example
228
+
229
+ ```javascript
230
+ import { test } from 'vitest';
231
+ import { chrome } from 'testdriverai/presets';
232
+
233
+ test('find element', async (context) => {
234
+ const { testdriver } = await chrome(context, {
235
+ url: 'https://example.com'
236
+ });
237
+
238
+ // First call: AI vision analysis, saves to cache
239
+ const button = await testdriver.find('More information link');
240
+ console.log('Cache hit:', button.cacheHit); // false
241
+
242
+ // Second call: uses cache (instant)
243
+ const button2 = await testdriver.find('More information link');
244
+ console.log('Cache hit:', button2.cacheHit); // true
245
+ });
246
+ ```
247
+
248
+ ### Dynamic Threshold Example
249
+
250
+ ```javascript
251
+ test('strict vs lenient matching', async (context) => {
252
+ const { testdriver } = await chrome(context, { url });
253
+
254
+ // Strict: 99% similarity required
255
+ const elem1 = await testdriver.find('button', { threshold: 0.01 });
256
+
257
+ // Lenient: 90% similarity acceptable
258
+ const elem2 = await testdriver.find('button', { threshold: 0.10 });
259
+
260
+ // Bypass cache entirely
261
+ const elem3 = await testdriver.find('button', { threshold: -1 });
262
+ });
263
+ ```
264
+
265
+ ## Best Practices
266
+
267
+ ### 1. Use Consistent Prompts
268
+
269
+ ```javascript
270
+ // ✅ Good - consistent prompt
271
+ await testdriver.find('submit button');
272
+ await testdriver.find('submit button'); // Cache hit
273
+
274
+ // ❌ Bad - different prompts
275
+ await testdriver.find('submit button');
276
+ await testdriver.find('the submit button'); // Cache miss
277
+ ```
278
+
279
+ ### 2. Clear Cache When UI Changes
280
+
281
+ If your UI changes significantly, clear the cache:
282
+
283
+ ```bash
284
+ # Clear prompt cache
285
+ rm -rf .testdriver/.cache/*.yaml
286
+
287
+ # Clear selector cache
288
+ # Use console.testdriver.ai to delete entries
289
+ ```
290
+
291
+ ### 3. Use Appropriate Thresholds
292
+
293
+ ```javascript
294
+ // Stable UI: strict threshold
295
+ await testdriver.find('logo', { threshold: 0.01 });
296
+
297
+ // Dynamic UI: lenient threshold
298
+ await testdriver.find('news feed item', { threshold: 0.10 });
299
+
300
+ // Always fresh: disable cache
301
+ await testdriver.find('timestamp', { threshold: -1 });
302
+ ```
303
+
304
+ ### 4. Monitor Cache Performance
305
+
306
+ Check [console.testdriver.ai](https://console.testdriver.ai) regularly to:
307
+ - See cache hit rates
308
+ - Identify frequently used selectors
309
+ - Remove stale cache entries
310
+ - Optimize threshold settings
311
+
312
+ ## Cache Storage
313
+
314
+ | Cache Type | Location | Persistence |
315
+ |------------|----------|-------------|
316
+ | Prompt Cache | Local (`.testdriver/.cache/`) | Until manually cleared |
317
+ | Selector Cache | Server (MongoDB + S3) | 7 days default |
318
+
319
+ ## Important Notes
320
+
321
+ ### Prompt Cache
322
+
323
+ - Cache keys are **prompt text only** (no screenshot comparison)
324
+ - Case-insensitive, trimmed matching
325
+ - Safe to commit to version control (but not recommended)
326
+ - Never expires automatically
327
+
328
+ ### Selector Cache
329
+
330
+ - Cache matches by **screenshot similarity** + prompt
331
+ - Platform-specific (OS, resolution)
332
+ - Team-scoped (your cache entries only)
333
+ - 7-day rolling window by default
334
+
335
+ ## Troubleshooting
336
+
337
+ ### Prompt Cache Not Working
338
+
339
+ Check:
340
+ 1. Prompts match exactly (case-insensitive)
341
+ 2. `.testdriver/.cache/` directory exists and is writable
342
+ 3. `TD_NO_PROMPT_CACHE` environment variable is not set
343
+
344
+ ### Selector Cache Not Working
345
+
346
+ Check:
347
+ 1. Threshold isn't too strict (try 0.10 for 90% similarity)
348
+ 2. Screenshot hasn't changed significantly
349
+ 3. OS/resolution matches cached entry
350
+ 4. Cache entry isn't older than 7 days
351
+
352
+ ### Stale Cache Data
353
+
354
+ Clear prompt cache:
355
+ ```bash
356
+ rm -rf .testdriver/.cache/*.yaml
357
+ ```
358
+
359
+ Delete selector cache entries at [console.testdriver.ai](https://console.testdriver.ai)
360
+
361
+ ## See Also
362
+
363
+ - [Console Dashboard](https://console.testdriver.ai) - View and manage selector cache
364
+ - [`.ai()` Method](/v7/api/ai) - AI command generation
365
+ - [`.find()` Method](/v7/api/find) - Element location
366
+ - [Vitest Integration](/v7/guides/vitest) - Testing with TestDriver