testdriverai 7.3.32 → 7.3.34
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/.github/copilot-instructions.md +641 -0
- package/.github/skills/testdriver:assert/SKILL.md +31 -0
- package/.github/skills/testdriver:aws-setup/SKILL.md +1 -68
- package/.github/skills/testdriver:client/SKILL.md +33 -0
- package/.github/skills/testdriver:debugging-with-screenshots/SKILL.md +175 -45
- package/.github/skills/testdriver:find/SKILL.md +87 -0
- package/.github/skills/testdriver:parse/SKILL.md +124 -6
- package/.github/skills/testdriver:quickstart/SKILL.md +2 -17
- package/.github/skills/testdriver:reusable-code/SKILL.md +9 -0
- package/.github/skills/testdriver:running-tests/SKILL.md +4 -0
- package/.github/skills/testdriver:screenshot/SKILL.md +84 -3
- package/.github/skills/testdriver:scroll/SKILL.md +36 -0
- package/.github/skills/testdriver:testdriver/SKILL.md +194 -86
- package/CHANGELOG.md +8 -0
- package/docs/_data/examples-manifest.json +72 -64
- package/docs/v7/examples/ai.mdx +1 -1
- package/docs/v7/examples/assert.mdx +1 -1
- package/docs/v7/examples/chrome-extension.mdx +1 -1
- package/docs/v7/examples/drag-and-drop.mdx +1 -1
- package/docs/v7/examples/element-not-found.mdx +1 -1
- package/docs/v7/examples/hover-image.mdx +1 -1
- package/docs/v7/examples/hover-text.mdx +1 -1
- package/docs/v7/examples/installer.mdx +1 -1
- package/docs/v7/examples/launch-vscode-linux.mdx +1 -1
- package/docs/v7/examples/match-image.mdx +1 -1
- package/docs/v7/examples/press-keys.mdx +1 -1
- package/docs/v7/examples/scroll-keyboard.mdx +1 -1
- package/docs/v7/examples/scroll-until-image.mdx +1 -1
- package/docs/v7/examples/scroll-until-text.mdx +1 -1
- package/docs/v7/examples/scroll.mdx +1 -1
- package/docs/v7/examples/type.mdx +1 -1
- package/docs/v7/examples/windows-installer.mdx +1 -1
- package/package.json +1 -2
- package/sdk.js +1 -1
|
@@ -256,7 +256,7 @@ jobs:
|
|
|
256
256
|
run: npm ci
|
|
257
257
|
|
|
258
258
|
- name: Run Windows tests with self-hosted instances
|
|
259
|
-
run: vitest run examples/*.test.mjs
|
|
259
|
+
run: npx vitest run examples/*.test.mjs
|
|
260
260
|
env:
|
|
261
261
|
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
262
262
|
TD_OS: windows
|
|
@@ -393,73 +393,6 @@ You can customize the AMI to include additional software or configurations:
|
|
|
393
393
|
**Security**: Never use the default password in production. Always rotate passwords before creating custom AMIs.
|
|
394
394
|
</Warning>
|
|
395
395
|
|
|
396
|
-
## Custom Lifecycle Hooks
|
|
397
|
-
|
|
398
|
-
You can run custom scripts after instance spawning by creating your own Vitest setup file. This is useful for:
|
|
399
|
-
|
|
400
|
-
- Installing additional software via SSM before tests run
|
|
401
|
-
- Configuring network settings or proxies
|
|
402
|
-
- Running cleanup scripts after tests complete
|
|
403
|
-
- Collecting logs or artifacts from instances
|
|
404
|
-
|
|
405
|
-
### Post-Spawn Hooks
|
|
406
|
-
|
|
407
|
-
To run commands after the instance is ready but before the test executes, create a setup file positioned **after** `setup-aws`:
|
|
408
|
-
|
|
409
|
-
```javascript post-spawn-setup.mjs
|
|
410
|
-
import { execSync } from 'child_process';
|
|
411
|
-
import { beforeEach } from 'vitest';
|
|
412
|
-
|
|
413
|
-
beforeEach(async (context) => {
|
|
414
|
-
// context.ip is set by setup-aws
|
|
415
|
-
if (!context.ip) return;
|
|
416
|
-
|
|
417
|
-
console.log(`Instance ready at ${context.ip}, running post-spawn setup...`);
|
|
418
|
-
|
|
419
|
-
// Run SSM commands on the instance
|
|
420
|
-
execSync(`aws ssm send-command \
|
|
421
|
-
--region "${process.env.AWS_REGION}" \
|
|
422
|
-
--targets "Key=tag:Name,Values=td-*" \
|
|
423
|
-
--document-name "AWS-RunPowerShellScript" \
|
|
424
|
-
--parameters 'commands=["choco install my-software -y"]'`);
|
|
425
|
-
});
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
```javascript vitest.config.mjs
|
|
429
|
-
setupFiles: [
|
|
430
|
-
'testdriverai/vitest/setup',
|
|
431
|
-
'testdriverai/vitest/setup-aws', // Instance spawns here
|
|
432
|
-
'./post-spawn-setup.mjs' // Your hooks run AFTER instance is ready
|
|
433
|
-
]
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
<Note>
|
|
437
|
-
Vitest executes setup files in array order. By positioning your file after `setup-aws`, the `context.ip` is already available in your `beforeEach` hook.
|
|
438
|
-
</Note>
|
|
439
|
-
|
|
440
|
-
### Post-Test Cleanup
|
|
441
|
-
|
|
442
|
-
To run cleanup after each test completes (while the instance is still running):
|
|
443
|
-
|
|
444
|
-
```javascript post-spawn-setup.mjs
|
|
445
|
-
import { execSync } from 'child_process';
|
|
446
|
-
import { beforeEach, afterEach } from 'vitest';
|
|
447
|
-
|
|
448
|
-
beforeEach(async (context) => {
|
|
449
|
-
if (!context.ip) return;
|
|
450
|
-
// ... post-spawn setup
|
|
451
|
-
});
|
|
452
|
-
|
|
453
|
-
afterEach(async (context) => {
|
|
454
|
-
if (!context.ip) return;
|
|
455
|
-
|
|
456
|
-
console.log('Running post-test cleanup...');
|
|
457
|
-
execSync('./scripts/collect-logs.sh', {
|
|
458
|
-
env: { ...process.env, INSTANCE_IP: context.ip }
|
|
459
|
-
});
|
|
460
|
-
});
|
|
461
|
-
```
|
|
462
|
-
|
|
463
396
|
## Security Best Practices
|
|
464
397
|
|
|
465
398
|
### Network Security
|
|
@@ -44,9 +44,37 @@ const testdriver = new TestDriver(apiKey, options)
|
|
|
44
44
|
Enable or disable console logging
|
|
45
45
|
</ParamField>
|
|
46
46
|
|
|
47
|
+
<ParamField path="autoScreenshots" type="boolean" default="true">
|
|
48
|
+
Automatically capture screenshots before and after each command. Screenshots are saved to `.testdriver/screenshots/<test>/` with descriptive filenames that include the line number and action name. Format: `<seq>-<action>-<phase>-L<line>-<description>.png`
|
|
49
|
+
</ParamField>
|
|
50
|
+
|
|
47
51
|
<ParamField path="environment" type="object">
|
|
48
52
|
Additional environment variables to pass to the sandbox
|
|
49
53
|
</ParamField>
|
|
54
|
+
|
|
55
|
+
<ParamField path="ai" type="object">
|
|
56
|
+
Global AI sampling configuration. Controls how the AI model generates responses for `find()` verification and `assert()` calls. Can be overridden per call.
|
|
57
|
+
|
|
58
|
+
<Expandable title="properties">
|
|
59
|
+
<ParamField path="temperature" type="number">
|
|
60
|
+
Controls randomness in AI responses. `0` = deterministic (best for verification), higher values = more creative. Default: `0` for find verification, model default for assert.
|
|
61
|
+
</ParamField>
|
|
62
|
+
|
|
63
|
+
<ParamField path="top" type="object">
|
|
64
|
+
Nucleus and top-k sampling parameters
|
|
65
|
+
|
|
66
|
+
<Expandable title="properties">
|
|
67
|
+
<ParamField path="p" type="number">
|
|
68
|
+
Top-P (nucleus sampling). Limits token choices to the smallest set whose cumulative probability exceeds P. Lower values = more focused responses. Range: 0-1.
|
|
69
|
+
</ParamField>
|
|
70
|
+
|
|
71
|
+
<ParamField path="k" type="number">
|
|
72
|
+
Top-K sampling. Limits token choices to the top K most likely tokens. `1` = always pick the most likely token. `0` = disabled (consider all tokens).
|
|
73
|
+
</ParamField>
|
|
74
|
+
</Expandable>
|
|
75
|
+
</ParamField>
|
|
76
|
+
</Expandable>
|
|
77
|
+
</ParamField>
|
|
50
78
|
</Expandable>
|
|
51
79
|
</ParamField>
|
|
52
80
|
|
|
@@ -63,6 +91,11 @@ const testdriver = new TestDriver({
|
|
|
63
91
|
analytics: true
|
|
64
92
|
});
|
|
65
93
|
|
|
94
|
+
// With AI config for stricter verification
|
|
95
|
+
const testdriver = new TestDriver({
|
|
96
|
+
ai: { temperature: 0, top: { p: 0.9, k: 40 } }
|
|
97
|
+
});
|
|
98
|
+
|
|
66
99
|
// Or pass API key explicitly
|
|
67
100
|
const testdriver = new TestDriver('your-api-key', {
|
|
68
101
|
os: 'windows'
|
|
@@ -8,20 +8,60 @@ description: View and analyze saved screenshots using MCP commands for test debu
|
|
|
8
8
|
|
|
9
9
|
TestDriver MCP provides powerful commands to view and analyze screenshots saved during test execution. This enables rapid debugging, test development, and comparison workflows without manually opening image files.
|
|
10
10
|
|
|
11
|
+
<Note>
|
|
12
|
+
**Automatic Screenshots (Default: Enabled)**: TestDriver automatically captures screenshots before and after every command. Screenshots are named with the line number and action, making it easy to trace exactly which line of code produced each screenshot. For example: `001-click-before-L42-submit-button.png`
|
|
13
|
+
</Note>
|
|
14
|
+
|
|
11
15
|
## MCP Commands
|
|
12
16
|
|
|
13
17
|
### list_local_screenshots
|
|
14
18
|
|
|
15
|
-
List
|
|
19
|
+
List and filter screenshots saved in the `.testdriver/screenshots/` directory:
|
|
16
20
|
|
|
17
21
|
```
|
|
18
22
|
list_local_screenshots()
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
**
|
|
25
|
+
**Filter Parameters:**
|
|
22
26
|
|
|
23
27
|
<ParamField path="directory" type="string" optional>
|
|
24
|
-
Filter screenshots by subdirectory (e.g.,
|
|
28
|
+
Filter screenshots by test file or subdirectory (e.g., "login.test", "mcp-screenshots"). If omitted, lists all screenshots.
|
|
29
|
+
</ParamField>
|
|
30
|
+
|
|
31
|
+
<ParamField path="line" type="number" optional>
|
|
32
|
+
Filter by exact line number from test file (e.g., 42 matches L42 in filename).
|
|
33
|
+
</ParamField>
|
|
34
|
+
|
|
35
|
+
<ParamField path="lineRange" type="object" optional>
|
|
36
|
+
Filter by line number range. Example: `{ start: 10, end: 20 }` matches screenshots from lines 10-20.
|
|
37
|
+
</ParamField>
|
|
38
|
+
|
|
39
|
+
<ParamField path="action" type="string" optional>
|
|
40
|
+
Filter by action type: `click`, `find`, `type`, `assert`, `provision`, `scroll`, `hover`, etc.
|
|
41
|
+
</ParamField>
|
|
42
|
+
|
|
43
|
+
<ParamField path="phase" type="string" optional>
|
|
44
|
+
Filter by phase: `"before"` (state before action) or `"after"` (state after action).
|
|
45
|
+
</ParamField>
|
|
46
|
+
|
|
47
|
+
<ParamField path="pattern" type="string" optional>
|
|
48
|
+
Regex pattern to match against filename. Example: `"login|signin"` or `"button.*click"`.
|
|
49
|
+
</ParamField>
|
|
50
|
+
|
|
51
|
+
<ParamField path="sequence" type="number" optional>
|
|
52
|
+
Filter by exact sequence number.
|
|
53
|
+
</ParamField>
|
|
54
|
+
|
|
55
|
+
<ParamField path="sequenceRange" type="object" optional>
|
|
56
|
+
Filter by sequence range. Example: `{ start: 1, end: 10 }` matches first 10 screenshots.
|
|
57
|
+
</ParamField>
|
|
58
|
+
|
|
59
|
+
<ParamField path="limit" type="number" optional>
|
|
60
|
+
Maximum number of results to return (default: 50).
|
|
61
|
+
</ParamField>
|
|
62
|
+
|
|
63
|
+
<ParamField path="sortBy" type="string" optional>
|
|
64
|
+
Sort results by: `"modified"` (newest first, default), `"sequence"` (execution order), or `"line"` (line number).
|
|
25
65
|
</ParamField>
|
|
26
66
|
|
|
27
67
|
**Returns:**
|
|
@@ -29,24 +69,31 @@ list_local_screenshots()
|
|
|
29
69
|
Array of screenshot metadata including:
|
|
30
70
|
- `path` - Full absolute path to the screenshot file
|
|
31
71
|
- `relativePath` - Path relative to `.testdriver/screenshots/`
|
|
32
|
-
- `
|
|
33
|
-
- `
|
|
34
|
-
- `size` - File size in bytes
|
|
72
|
+
- `name` - Screenshot filename
|
|
73
|
+
- `sizeBytes` - File size in bytes
|
|
35
74
|
- `modified` - Last modification timestamp
|
|
36
|
-
- `
|
|
75
|
+
- `sequence` - Sequential number (from auto-screenshots)
|
|
76
|
+
- `action` - Action type (click, find, etc.)
|
|
77
|
+
- `phase` - Before/after phase
|
|
78
|
+
- `lineNumber` - Line number from test file
|
|
79
|
+
- `description` - Element or action description
|
|
37
80
|
|
|
38
|
-
**Example
|
|
81
|
+
**Example Responses:**
|
|
39
82
|
|
|
40
83
|
```json
|
|
84
|
+
// Basic listing
|
|
41
85
|
[
|
|
42
86
|
{
|
|
43
|
-
"path": "/Users/user/project/.testdriver/screenshots/login.test/
|
|
44
|
-
"relativePath": "login.test/
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"size": 145632,
|
|
87
|
+
"path": "/Users/user/project/.testdriver/screenshots/login.test/001-click-before-L42-submit-button.png",
|
|
88
|
+
"relativePath": "login.test/001-click-before-L42-submit-button.png",
|
|
89
|
+
"name": "001-click-before-L42-submit-button.png",
|
|
90
|
+
"sizeBytes": 145632,
|
|
48
91
|
"modified": "2026-01-23T10:00:00.000Z",
|
|
49
|
-
"
|
|
92
|
+
"sequence": 1,
|
|
93
|
+
"action": "click",
|
|
94
|
+
"phase": "before",
|
|
95
|
+
"lineNumber": 42,
|
|
96
|
+
"description": "submit-button"
|
|
50
97
|
}
|
|
51
98
|
]
|
|
52
99
|
```
|
|
@@ -75,34 +122,85 @@ view_local_screenshot({ path: "/full/path/to/screenshot.png" })
|
|
|
75
122
|
|
|
76
123
|
### Test Debugging After Failures
|
|
77
124
|
|
|
78
|
-
When a test fails,
|
|
125
|
+
When a test fails, use powerful filtering to quickly find relevant screenshots:
|
|
79
126
|
|
|
80
|
-
1.
|
|
127
|
+
**1. Find screenshots at the failing line:**
|
|
81
128
|
|
|
82
129
|
```
|
|
83
|
-
|
|
130
|
+
// If test failed at line 42
|
|
131
|
+
list_local_screenshots({ line: 42 })
|
|
132
|
+
|
|
133
|
+
// View before and after states at that line
|
|
134
|
+
view_local_screenshot({ path: ".testdriver/screenshots/login.test/005-click-before-L42-submit-button.png" })
|
|
135
|
+
view_local_screenshot({ path: ".testdriver/screenshots/login.test/006-click-after-L42-submit-button.png" })
|
|
84
136
|
```
|
|
85
137
|
|
|
86
|
-
2.
|
|
138
|
+
**2. See what happened leading up to the failure:**
|
|
87
139
|
|
|
88
140
|
```
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
view_local_screenshot({ path: ".testdriver/screenshots/login.test/screenshot-1737633620000.png" })
|
|
141
|
+
// Get screenshots from lines 35-45 to see context
|
|
142
|
+
list_local_screenshots({ directory: "login.test", lineRange: { start: 35, end: 45 } })
|
|
92
143
|
```
|
|
93
144
|
|
|
94
|
-
3.
|
|
145
|
+
**3. Find all assertion screenshots:**
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
// See what the screen looked like during assertions
|
|
149
|
+
list_local_screenshots({ action: "assert" })
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**4. View the final state before failure:**
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
// Get the last 5 screenshots in execution order
|
|
156
|
+
list_local_screenshots({ directory: "login.test", sortBy: "sequence", limit: 5 })
|
|
157
|
+
```
|
|
95
158
|
|
|
96
|
-
|
|
159
|
+
### Finding Specific Actions
|
|
160
|
+
|
|
161
|
+
When debugging element interactions:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
// Find all click actions
|
|
165
|
+
list_local_screenshots({ action: "click" })
|
|
166
|
+
|
|
167
|
+
// Find what the screen looked like BEFORE each click
|
|
168
|
+
list_local_screenshots({ action: "click", phase: "before" })
|
|
169
|
+
|
|
170
|
+
// Find screenshots related to a specific element using regex
|
|
171
|
+
list_local_screenshots({ pattern: "submit|button" })
|
|
172
|
+
|
|
173
|
+
// Find all type actions (for form filling issues)
|
|
174
|
+
list_local_screenshots({ action: "type" })
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Understanding Test Flow
|
|
178
|
+
|
|
179
|
+
View screenshots in execution order to trace test behavior:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
// Get screenshots in execution order
|
|
183
|
+
list_local_screenshots({ directory: "checkout.test", sortBy: "sequence" })
|
|
184
|
+
|
|
185
|
+
// Get just the first 10 actions
|
|
186
|
+
list_local_screenshots({ sequenceRange: { start: 1, end: 10 }, sortBy: "sequence" })
|
|
187
|
+
|
|
188
|
+
// Get just the last 10 actions
|
|
189
|
+
list_local_screenshots({ directory: "checkout.test", sortBy: "sequence", limit: 10 })
|
|
190
|
+
```
|
|
97
191
|
|
|
98
192
|
### Interactive Test Development
|
|
99
193
|
|
|
100
194
|
While building tests using MCP tools, view screenshots to verify your test logic:
|
|
101
195
|
|
|
102
|
-
1. **After a test run**,
|
|
196
|
+
1. **After a test run**, filter screenshots to see specific actions:
|
|
103
197
|
|
|
104
198
|
```
|
|
105
|
-
|
|
199
|
+
// See all assertions
|
|
200
|
+
list_local_screenshots({ action: "assert" })
|
|
201
|
+
|
|
202
|
+
// See what happened at a specific line you're debugging
|
|
203
|
+
list_local_screenshots({ line: 25 })
|
|
106
204
|
```
|
|
107
205
|
|
|
108
206
|
2. **Review key points** in the test execution:
|
|
@@ -117,21 +215,31 @@ view_local_screenshot({ path: ".testdriver/screenshots/my-test.test/after-login.
|
|
|
117
215
|
|
|
118
216
|
### Comparison and Analysis
|
|
119
217
|
|
|
120
|
-
Compare screenshots
|
|
218
|
+
Compare screenshots to identify issues:
|
|
121
219
|
|
|
122
|
-
|
|
220
|
+
**Using phase filtering for before/after comparison:**
|
|
123
221
|
|
|
124
|
-
|
|
222
|
+
```
|
|
223
|
+
// See state before all clicks
|
|
224
|
+
list_local_screenshots({ action: "click", phase: "before" })
|
|
125
225
|
|
|
226
|
+
// See state after all clicks
|
|
227
|
+
list_local_screenshots({ action: "click", phase: "after" })
|
|
126
228
|
```
|
|
127
|
-
view_local_screenshot({ path: ".testdriver/screenshots/test.test/before-click.png" })
|
|
128
|
-
// Analyze first run
|
|
129
229
|
|
|
130
|
-
|
|
131
|
-
|
|
230
|
+
**Using line-based debugging:**
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
// Something went wrong around line 50
|
|
234
|
+
list_local_screenshots({ lineRange: { start: 45, end: 55 } })
|
|
132
235
|
```
|
|
133
236
|
|
|
134
|
-
|
|
237
|
+
**Using regex patterns:**
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
// Find screenshots related to login functionality
|
|
241
|
+
list_local_screenshots({ pattern: "login|signin|email|password" })
|
|
242
|
+
```
|
|
135
243
|
|
|
136
244
|
## Best Practices
|
|
137
245
|
|
|
@@ -188,20 +296,37 @@ Understanding the directory structure helps with efficient screenshot viewing:
|
|
|
188
296
|
.testdriver/
|
|
189
297
|
screenshots/
|
|
190
298
|
login.test/ # Test file name (without .mjs extension)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
299
|
+
001-find-before-L15-email-input.png # Auto: before find() at line 15
|
|
300
|
+
002-find-after-L15-email-input.png # Auto: after find() at line 15
|
|
301
|
+
003-click-before-L16-email-input.png # Auto: before click() at line 16
|
|
302
|
+
004-click-after-L16-email-input.png # Auto: after click() at line 16
|
|
303
|
+
login-complete.png # Manual: screenshot("login-complete")
|
|
194
304
|
checkout.test/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
screenshot-1737633800000.png
|
|
305
|
+
001-find-before-L12-add-to-cart.png
|
|
306
|
+
002-find-after-L12-add-to-cart.png
|
|
307
|
+
...
|
|
199
308
|
```
|
|
200
309
|
|
|
310
|
+
### Automatic Screenshot Naming Format
|
|
311
|
+
|
|
312
|
+
`<seq>-<action>-<phase>-L<line>-<description>.png`
|
|
313
|
+
|
|
314
|
+
| Component | Description | Example |
|
|
315
|
+
|-----------|-------------|---------|
|
|
316
|
+
| `seq` | Sequential number | `001`, `002` |
|
|
317
|
+
| `action` | Command name | `click`, `type`, `find` |
|
|
318
|
+
| `phase` | Before, after, or error | `before`, `after`, `error` |
|
|
319
|
+
| `L<line>` | Line number from test file | `L42` |
|
|
320
|
+
| `description` | Element/action description | `submit-button` |
|
|
321
|
+
|
|
322
|
+
### Key Points
|
|
323
|
+
|
|
201
324
|
- Each test file gets its own subdirectory
|
|
202
|
-
-
|
|
325
|
+
- Automatic screenshots include line numbers for easy tracing
|
|
326
|
+
- Manual `screenshot()` calls use custom names you provide
|
|
203
327
|
- Folders are cleared at the start of each test run
|
|
204
328
|
- All screenshots are PNG format
|
|
329
|
+
- Disable automatic screenshots with `autoScreenshots: false` if needed
|
|
205
330
|
|
|
206
331
|
## Integration with Test Development
|
|
207
332
|
|
|
@@ -248,11 +373,16 @@ When tests fail or behave unexpectedly:
|
|
|
248
373
|
</Accordion>
|
|
249
374
|
|
|
250
375
|
<Accordion title="Too many screenshots">
|
|
251
|
-
If you have hundreds of screenshots making it hard to find what you need:
|
|
376
|
+
If you have hundreds of screenshots making it hard to find what you need, use filtering:
|
|
252
377
|
|
|
253
|
-
-
|
|
254
|
-
-
|
|
255
|
-
-
|
|
378
|
+
- Filter by test file: `list_local_screenshots({ directory: "my-test.test" })`
|
|
379
|
+
- Filter by line number: `list_local_screenshots({ line: 42 })` or `list_local_screenshots({ lineRange: { start: 40, end: 50 } })`
|
|
380
|
+
- Filter by action: `list_local_screenshots({ action: "click" })`
|
|
381
|
+
- Filter by phase: `list_local_screenshots({ phase: "before" })`
|
|
382
|
+
- Use regex: `list_local_screenshots({ pattern: "submit|login" })`
|
|
383
|
+
- Limit results: `list_local_screenshots({ limit: 10 })`
|
|
384
|
+
- Sort by line: `list_local_screenshots({ sortBy: "line" })`
|
|
385
|
+
- Clean up old folders: `rm -rf .testdriver/screenshots/*`
|
|
256
386
|
</Accordion>
|
|
257
387
|
|
|
258
388
|
<Accordion title="Screenshots from old test runs">
|
|
@@ -52,6 +52,30 @@ const element = await testdriver.find(description, options)
|
|
|
52
52
|
<ParamField path="zoom" type="boolean" default={false}>
|
|
53
53
|
Enable two-phase zoom mode for better precision in crowded UIs with many similar elements.
|
|
54
54
|
</ParamField>
|
|
55
|
+
|
|
56
|
+
<ParamField path="ai" type="object">
|
|
57
|
+
AI sampling configuration for this find call (overrides global `ai` config from constructor).
|
|
58
|
+
|
|
59
|
+
<Expandable title="properties">
|
|
60
|
+
<ParamField path="temperature" type="number">
|
|
61
|
+
Controls randomness. `0` = deterministic. Default: `0` for find verification.
|
|
62
|
+
</ParamField>
|
|
63
|
+
|
|
64
|
+
<ParamField path="top" type="object">
|
|
65
|
+
Sampling parameters
|
|
66
|
+
|
|
67
|
+
<Expandable title="properties">
|
|
68
|
+
<ParamField path="p" type="number">
|
|
69
|
+
Top-P (nucleus sampling). Range: 0-1.
|
|
70
|
+
</ParamField>
|
|
71
|
+
|
|
72
|
+
<ParamField path="k" type="number">
|
|
73
|
+
Top-K sampling. `1` = most deterministic.
|
|
74
|
+
</ParamField>
|
|
75
|
+
</Expandable>
|
|
76
|
+
</ParamField>
|
|
77
|
+
</Expandable>
|
|
78
|
+
</ParamField>
|
|
55
79
|
</Expandable>
|
|
56
80
|
</ParamField>
|
|
57
81
|
|
|
@@ -220,6 +244,69 @@ This is useful for:
|
|
|
220
244
|
```
|
|
221
245
|
</Check>
|
|
222
246
|
|
|
247
|
+
## Confidence Threshold
|
|
248
|
+
|
|
249
|
+
Require a minimum AI confidence score for element matches. If the confidence is below the threshold, `find()` treats the result as not found:
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
// Require at least 90% confidence
|
|
253
|
+
const element = await testdriver.find('submit button', { confidence: 0.9 });
|
|
254
|
+
|
|
255
|
+
if (!element.found()) {
|
|
256
|
+
// AI found something but wasn't confident enough
|
|
257
|
+
throw new Error('Could not confidently locate submit button');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
await element.click();
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
This is useful for:
|
|
264
|
+
- Critical test steps where an incorrect click could cause cascading failures
|
|
265
|
+
- Distinguishing between similar elements (e.g., multiple buttons)
|
|
266
|
+
- Failing fast when the UI has changed unexpectedly
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
// Combine with timeout for robust polling with confidence gate
|
|
270
|
+
const element = await testdriver.find('success notification', {
|
|
271
|
+
confidence: 0.85,
|
|
272
|
+
timeout: 15000,
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
<Tip>
|
|
277
|
+
The `confidence` value is a float between 0 and 1 (e.g., `0.9` = 90%). The AI returns its confidence with each find result, which you can also read from `element.confidence` after a successful find.
|
|
278
|
+
</Tip>
|
|
279
|
+
## Element Type
|
|
280
|
+
|
|
281
|
+
Use the `type` option to hint what kind of element you're looking for. This wraps your description into a more specific prompt for the AI, improving match accuracy — especially when users provide short or ambiguous descriptions.
|
|
282
|
+
|
|
283
|
+
```javascript
|
|
284
|
+
// Find text on the page
|
|
285
|
+
const label = await testdriver.find('Sign In', { type: 'text' });
|
|
286
|
+
// AI prompt becomes: The text "Sign In"
|
|
287
|
+
|
|
288
|
+
// Find an image
|
|
289
|
+
const logo = await testdriver.find('company logo', { type: 'image' });
|
|
290
|
+
// AI prompt becomes: The image "company logo"
|
|
291
|
+
|
|
292
|
+
// Find a UI element (button, input, checkbox, etc.)
|
|
293
|
+
const btn = await testdriver.find('Submit', { type: 'ui' });
|
|
294
|
+
// AI prompt becomes: The UI element "Submit"
|
|
295
|
+
|
|
296
|
+
// No wrapping — same as omitting the option
|
|
297
|
+
const el = await testdriver.find('the blue submit button', { type: 'any' });
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
| Type | Prompt sent to AI |
|
|
301
|
+
|------|----|
|
|
302
|
+
| `"text"` | `The text "..."` |
|
|
303
|
+
| `"image"` | `The image "..."` |
|
|
304
|
+
| `"ui"` | `The UI element "..."` |
|
|
305
|
+
| `"any"` | Original description (no wrapping) |
|
|
306
|
+
|
|
307
|
+
<Tip>
|
|
308
|
+
This is particularly useful for short descriptions like `"Submit"` or `"Login"` where the AI may not know whether to look for a button, a link, or visible text. Specifying `type` removes the ambiguity.
|
|
309
|
+
</Tip>
|
|
223
310
|
## Polling for Dynamic Elements
|
|
224
311
|
|
|
225
312
|
For elements that may not be immediately visible, use the `timeout` option to automatically poll:
|