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.
- package/AGENTS.md +550 -0
- package/CODEOWNERS +0 -1
- package/README.md +126 -0
- package/agent/index.js +43 -18
- package/agent/lib/commands.js +794 -135
- package/agent/lib/redraw.js +124 -39
- package/agent/lib/sandbox.js +10 -1
- package/agent/lib/sdk.js +21 -0
- package/docs/MIGRATION.md +425 -0
- package/docs/PRESETS.md +210 -0
- package/docs/docs.json +91 -37
- package/docs/guide/best-practices-polling.mdx +154 -0
- package/docs/v7/api/dashcam.mdx +497 -0
- package/docs/v7/api/doubleClick.mdx +102 -0
- package/docs/v7/api/mouseDown.mdx +161 -0
- package/docs/v7/api/mouseUp.mdx +164 -0
- package/docs/v7/api/rightClick.mdx +123 -0
- package/docs/v7/getting-started/configuration.mdx +380 -0
- package/docs/v7/getting-started/quickstart.mdx +273 -140
- package/docs/v7/guides/best-practices.mdx +486 -0
- package/docs/v7/guides/caching-ai.mdx +215 -0
- package/docs/v7/guides/caching-selectors.mdx +292 -0
- package/docs/v7/guides/caching.mdx +366 -0
- package/docs/v7/guides/ci-cd/azure.mdx +587 -0
- package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
- package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
- package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
- package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
- package/docs/v7/guides/ci-cd/travis.mdx +438 -0
- package/docs/v7/guides/debugging.mdx +349 -0
- package/docs/v7/guides/faq.mdx +393 -0
- package/docs/v7/guides/performance.mdx +517 -0
- package/docs/v7/guides/troubleshooting.mdx +526 -0
- package/docs/v7/guides/vitest-plugin.mdx +477 -0
- package/docs/v7/guides/vitest.mdx +535 -0
- package/docs/v7/platforms/linux.mdx +308 -0
- package/docs/v7/platforms/macos.mdx +433 -0
- package/docs/v7/platforms/windows.mdx +430 -0
- package/docs/v7/presets/chrome-extension.mdx +223 -0
- package/docs/v7/presets/chrome.mdx +287 -0
- package/docs/v7/presets/electron.mdx +435 -0
- package/docs/v7/presets/vscode.mdx +398 -0
- package/docs/v7/presets/webapp.mdx +396 -0
- package/docs/v7/progressive-apis/CORE.md +459 -0
- package/docs/v7/progressive-apis/HOOKS.md +360 -0
- package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
- package/docs/v7/progressive-apis/PROVISION.md +266 -0
- package/interfaces/vitest-plugin.mjs +186 -100
- package/package.json +12 -1
- package/sdk.d.ts +335 -42
- package/sdk.js +756 -95
- package/src/core/Dashcam.js +469 -0
- package/src/core/index.d.ts +150 -0
- package/src/core/index.js +12 -0
- package/src/presets/index.mjs +331 -0
- package/src/vitest/extended.mjs +108 -0
- package/src/vitest/hooks.d.ts +119 -0
- package/src/vitest/hooks.mjs +298 -0
- package/src/vitest/index.mjs +64 -0
- package/src/vitest/lifecycle.mjs +277 -0
- package/src/vitest/utils.mjs +150 -0
- package/test/dashcam.test.js +137 -0
- package/testdriver/acceptance-sdk/assert.test.mjs +13 -31
- package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
- package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
- package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +7 -19
- package/testdriver/acceptance-sdk/element-not-found.test.mjs +6 -19
- package/testdriver/acceptance-sdk/exec-js.test.mjs +6 -18
- package/testdriver/acceptance-sdk/exec-output.test.mjs +8 -20
- package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +13 -25
- package/testdriver/acceptance-sdk/focus-window.test.mjs +8 -20
- package/testdriver/acceptance-sdk/formatted-logging.test.mjs +5 -20
- package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
- package/testdriver/acceptance-sdk/hover-image.test.mjs +10 -19
- package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +7 -19
- package/testdriver/acceptance-sdk/hover-text.test.mjs +5 -19
- package/testdriver/acceptance-sdk/match-image.test.mjs +7 -19
- package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
- package/testdriver/acceptance-sdk/press-keys.test.mjs +5 -19
- package/testdriver/acceptance-sdk/prompt.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +6 -20
- package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +6 -18
- package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +9 -23
- package/testdriver/acceptance-sdk/scroll.test.mjs +12 -21
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +124 -352
- package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
- package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
- package/testdriver/acceptance-sdk/type.test.mjs +19 -58
- package/vitest.config.mjs +1 -0
- package/.vscode/mcp.json +0 -9
- package/MIGRATION.md +0 -389
- package/PLUGIN_MIGRATION.md +0 -222
- package/PROMPT_CACHE.md +0 -200
- package/SDK_LOGGING.md +0 -222
- package/SDK_MIGRATION.md +0 -474
- package/SDK_README.md +0 -1122
- package/debug-screenshot-1763401388589.png +0 -0
- package/examples/run-tests-with-recording.sh +0 -70
- package/examples/screenshot-example.js +0 -63
- package/examples/sdk-awesome-logs-demo.js +0 -177
- package/examples/sdk-cache-thresholds.js +0 -96
- package/examples/sdk-element-properties.js +0 -155
- package/examples/sdk-simple-example.js +0 -65
- package/examples/test-recording-example.test.js +0 -166
- package/mcp-server/AI_GUIDELINES.md +0 -57
- package/test-find-api.js +0 -73
- package/test-prompt-cache.js +0 -96
- package/test-sandbox-render.js +0 -28
- package/test-sdk-methods.js +0 -15
- package/test-sdk-refactor.js +0 -53
- package/test-stack-trace.mjs +0 -57
- package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +0 -239
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Debugging Tests"
|
|
3
|
+
description: "Debug failing tests and understand test execution"
|
|
4
|
+
icon: "bug"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
TestDriver provides multiple ways to debug tests: Dashcam recordings, verbose logging, screenshots, and direct sandbox access.
|
|
10
|
+
|
|
11
|
+
## Dashcam Recordings
|
|
12
|
+
|
|
13
|
+
Every test creates a video recording automatically:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { test } from 'vitest';
|
|
17
|
+
import { chrome } from 'testdriverai/presets';
|
|
18
|
+
|
|
19
|
+
test('login flow', async (context) => {
|
|
20
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
21
|
+
url: 'https://myapp.com'
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Test code...
|
|
25
|
+
|
|
26
|
+
// Dashcam URL automatically logged
|
|
27
|
+
console.log('Replay:', dashcam.url);
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Dashcam shows:**
|
|
32
|
+
- Video recording of screen
|
|
33
|
+
- All commands executed
|
|
34
|
+
- Logged output
|
|
35
|
+
- Timestamps
|
|
36
|
+
- Element locations
|
|
37
|
+
|
|
38
|
+
## Verbose Logging
|
|
39
|
+
|
|
40
|
+
Enable detailed logging:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
const client = await TestDriver.create({
|
|
44
|
+
apiKey: process.env.TD_API_KEY,
|
|
45
|
+
verbosity: 2, // 0=silent, 1=normal, 2=debug
|
|
46
|
+
logging: true
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Debug output includes:**
|
|
51
|
+
- API requests/responses
|
|
52
|
+
- Element coordinates found
|
|
53
|
+
- Cache hits/misses
|
|
54
|
+
- Command execution time
|
|
55
|
+
- Screenshot hashes
|
|
56
|
+
|
|
57
|
+
## Check Element Found
|
|
58
|
+
|
|
59
|
+
Always verify elements were located:
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
const button = await testdriver.find('submit button');
|
|
63
|
+
|
|
64
|
+
if (!button.found()) {
|
|
65
|
+
console.log('Button not found!');
|
|
66
|
+
console.log('Coordinates:', button.coordinates);
|
|
67
|
+
console.log('Confidence:', button.confidence);
|
|
68
|
+
|
|
69
|
+
// Try alternative selector
|
|
70
|
+
const button2 = await testdriver.find('blue button at bottom');
|
|
71
|
+
console.log('Alternative found:', button2.found());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await button.click();
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Take Screenshots
|
|
78
|
+
|
|
79
|
+
Capture screenshots at key points:
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
// Using exec to save screenshot
|
|
83
|
+
if (process.platform !== 'win32') {
|
|
84
|
+
await testdriver.exec('sh', 'scrot /tmp/debug.png', 5000, true);
|
|
85
|
+
} else {
|
|
86
|
+
await testdriver.exec('pwsh',
|
|
87
|
+
'Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait("%{PRTSC}"); Start-Sleep -Seconds 1',
|
|
88
|
+
5000, true
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Element screenshots (if available)
|
|
93
|
+
const element = await testdriver.find('error message');
|
|
94
|
+
if (element.screenshot) {
|
|
95
|
+
console.log('Element screenshot:', element.screenshot);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Inspect Element Properties
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const element = await testdriver.find('submit button');
|
|
103
|
+
|
|
104
|
+
console.log('Found:', element.found());
|
|
105
|
+
console.log('Coordinates:', element.coordinates);
|
|
106
|
+
console.log('Center:', element.centerX, element.centerY);
|
|
107
|
+
console.log('Confidence:', element.confidence);
|
|
108
|
+
console.log('Text:', element.text);
|
|
109
|
+
console.log('Bounding box:', element.boundingBox);
|
|
110
|
+
console.log('Cache hit:', element.cacheHit);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Step-by-Step Debugging
|
|
114
|
+
|
|
115
|
+
Add delays to watch execution:
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
test('debug step by step', async (context) => {
|
|
119
|
+
const { testdriver } = await chrome(context, { url });
|
|
120
|
+
|
|
121
|
+
console.log('Step 1: Finding username field');
|
|
122
|
+
const username = await testdriver.find('username field');
|
|
123
|
+
await new Promise(r => setTimeout(r, 2000)); // Pause 2s
|
|
124
|
+
|
|
125
|
+
console.log('Step 2: Clicking username');
|
|
126
|
+
await username.click();
|
|
127
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
128
|
+
|
|
129
|
+
console.log('Step 3: Typing username');
|
|
130
|
+
await testdriver.type('user@example.com');
|
|
131
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Using Assertions for Debugging
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
// Verify state at checkpoints
|
|
139
|
+
const result1 = await testdriver.assert('login form is visible');
|
|
140
|
+
console.log('Form visible:', result1);
|
|
141
|
+
|
|
142
|
+
await testdriver.find('username').then(el => el.click());
|
|
143
|
+
await testdriver.type('user@example.com');
|
|
144
|
+
|
|
145
|
+
const result2 = await testdriver.assert('username field contains user@example.com');
|
|
146
|
+
console.log('Username entered:', result2);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Common Issues
|
|
150
|
+
|
|
151
|
+
### Element Not Found
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
// Issue: Element not found
|
|
155
|
+
const button = await testdriver.find('submit button');
|
|
156
|
+
console.log('Found:', button.found()); // false
|
|
157
|
+
|
|
158
|
+
// Debug: Try different descriptions
|
|
159
|
+
const alternatives = [
|
|
160
|
+
'submit button',
|
|
161
|
+
'blue button at bottom',
|
|
162
|
+
'button with text Submit',
|
|
163
|
+
'primary button in form'
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
for (const desc of alternatives) {
|
|
167
|
+
const el = await testdriver.find(desc);
|
|
168
|
+
console.log(`"${desc}":`, el.found(), el.confidence);
|
|
169
|
+
if (el.found()) break;
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Wrong Element Clicked
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
// Issue: Clicked wrong element
|
|
177
|
+
|
|
178
|
+
// Debug: Check coordinates
|
|
179
|
+
const button = await testdriver.find('submit button');
|
|
180
|
+
console.log('Button at:', button.centerX, button.centerY);
|
|
181
|
+
console.log('Confidence:', button.confidence);
|
|
182
|
+
|
|
183
|
+
// Use more specific description
|
|
184
|
+
const specificButton = await testdriver.find(
|
|
185
|
+
'blue submit button at the bottom right of the login form'
|
|
186
|
+
);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Command Timeout
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
// Issue: Command times out
|
|
193
|
+
|
|
194
|
+
// Debug: Increase timeout and add logging
|
|
195
|
+
try {
|
|
196
|
+
await testdriver.exec('sh', 'slow-command', 120000, false);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error('Command failed:', error.message);
|
|
199
|
+
console.error('Increase timeout or check command');
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Cache Issues
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
// Issue: Using stale cached element
|
|
207
|
+
|
|
208
|
+
// Debug: Bypass cache
|
|
209
|
+
const element = await testdriver.find('button', { threshold: -1 });
|
|
210
|
+
console.log('Fresh lookup (no cache):', element.found());
|
|
211
|
+
|
|
212
|
+
// Or clear prompt cache
|
|
213
|
+
import { exec } from 'child_process';
|
|
214
|
+
exec('rm -rf .testdriver/.cache/*.yaml');
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Interactive Debugging
|
|
218
|
+
|
|
219
|
+
### Access Sandbox Directly
|
|
220
|
+
|
|
221
|
+
Get sandbox details for manual inspection:
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
const instance = testdriver.getInstance();
|
|
225
|
+
console.log('Sandbox ID:', instance.instanceId);
|
|
226
|
+
console.log('IP:', instance.ip);
|
|
227
|
+
console.log('VNC Port:', instance.vncPort);
|
|
228
|
+
|
|
229
|
+
// Connect via VNC to watch live
|
|
230
|
+
console.log('VNC URL:', `vnc://${instance.ip}:${instance.vncPort}`);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Keep Sandbox Alive
|
|
234
|
+
|
|
235
|
+
Don't disconnect for manual debugging:
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
test('debug manually', async (context) => {
|
|
239
|
+
const { testdriver } = await chrome(context, { url });
|
|
240
|
+
|
|
241
|
+
// Run test
|
|
242
|
+
await testdriver.find('button').then(el => el.click());
|
|
243
|
+
|
|
244
|
+
// Keep alive for inspection
|
|
245
|
+
console.log('Sandbox still running. Press Ctrl+C when done.');
|
|
246
|
+
await new Promise(() => {}); // Never resolves
|
|
247
|
+
|
|
248
|
+
// Don't call disconnect() to keep sandbox alive
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Event Listeners
|
|
253
|
+
|
|
254
|
+
Listen to internal events:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
const emitter = testdriver.getEmitter();
|
|
258
|
+
|
|
259
|
+
emitter.on('command:start', (data) => {
|
|
260
|
+
console.log('đĩ Command starting:', data);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
emitter.on('command:success', (data) => {
|
|
264
|
+
console.log('â
Command succeeded:', data);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
emitter.on('command:error', (error) => {
|
|
268
|
+
console.error('â Command failed:', error);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
emitter.on('log:info', (message) => {
|
|
272
|
+
console.log('âšī¸ ', message);
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Debugging Checklist
|
|
277
|
+
|
|
278
|
+
When a test fails:
|
|
279
|
+
|
|
280
|
+
1. â
**Check Dashcam recording** - Watch what actually happened
|
|
281
|
+
2. â
**Enable verbose logging** - See detailed execution
|
|
282
|
+
3. â
**Verify element.found()** - Ensure elements were located
|
|
283
|
+
4. â
**Check coordinates** - Verify element positions
|
|
284
|
+
5. â
**Try alternative descriptions** - Use different prompts
|
|
285
|
+
6. â
**Disable cache** - Rule out stale cache
|
|
286
|
+
7. â
**Add delays** - Slow down execution
|
|
287
|
+
8. â
**Use assertions** - Verify state at checkpoints
|
|
288
|
+
9. â
**Check timeouts** - Increase if needed
|
|
289
|
+
10. â
**Inspect sandbox** - Connect directly via VNC
|
|
290
|
+
|
|
291
|
+
## Best Practices
|
|
292
|
+
|
|
293
|
+
<AccordionGroup>
|
|
294
|
+
<Accordion title="Always use Dashcam">
|
|
295
|
+
Every test should record with Dashcam for post-failure analysis:
|
|
296
|
+
```javascript
|
|
297
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
298
|
+
dashcam: true // Default, but be explicit
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
</Accordion>
|
|
302
|
+
|
|
303
|
+
<Accordion title="Log element properties">
|
|
304
|
+
```javascript
|
|
305
|
+
const element = await testdriver.find('button');
|
|
306
|
+
console.log('Element:', {
|
|
307
|
+
found: element.found(),
|
|
308
|
+
coords: element.coordinates,
|
|
309
|
+
confidence: element.confidence
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
</Accordion>
|
|
313
|
+
|
|
314
|
+
<Accordion title="Use descriptive test names">
|
|
315
|
+
```javascript
|
|
316
|
+
test('login with valid credentials shows dashboard', async () => {
|
|
317
|
+
// Clear what's being tested
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
</Accordion>
|
|
321
|
+
|
|
322
|
+
<Accordion title="Add checkpoint assertions">
|
|
323
|
+
```javascript
|
|
324
|
+
await testdriver.assert('login page loaded');
|
|
325
|
+
// ... login steps ...
|
|
326
|
+
await testdriver.assert('dashboard is visible');
|
|
327
|
+
```
|
|
328
|
+
</Accordion>
|
|
329
|
+
</AccordionGroup>
|
|
330
|
+
|
|
331
|
+
## See Also
|
|
332
|
+
|
|
333
|
+
<CardGroup cols={2}>
|
|
334
|
+
<Card title="Dashcam" icon="video" href="/v7/api/dashcam">
|
|
335
|
+
Recording API reference
|
|
336
|
+
</Card>
|
|
337
|
+
|
|
338
|
+
<Card title="Assertions" icon="circle-check" href="/v7/api/assertions">
|
|
339
|
+
Verification methods
|
|
340
|
+
</Card>
|
|
341
|
+
|
|
342
|
+
<Card title="Troubleshooting" icon="circle-question" href="/v7/guides/troubleshooting">
|
|
343
|
+
Common issues
|
|
344
|
+
</Card>
|
|
345
|
+
|
|
346
|
+
<Card title="Best Practices" icon="star" href="/v7/guides/best-practices">
|
|
347
|
+
Testing patterns
|
|
348
|
+
</Card>
|
|
349
|
+
</CardGroup>
|