testdriverai 7.2.86 → 7.2.88
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/agent/lib/redraw.js +33 -26
- package/ai/agents/testdriver.md +10 -8
- package/package.json +1 -1
package/agent/lib/redraw.js
CHANGED
|
@@ -21,7 +21,8 @@ const createRedraw = (
|
|
|
21
21
|
// Merge default options with provided defaults
|
|
22
22
|
const baseOptions = { ...DEFAULT_REDRAW_OPTIONS, ...defaultOptions };
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
// Network check interval (ms) - used for speed calculation display
|
|
25
|
+
const networkCheckInterval = 250;
|
|
25
26
|
|
|
26
27
|
let lastTxBytes = null;
|
|
27
28
|
let lastRxBytes = null;
|
|
@@ -125,15 +126,32 @@ const createRedraw = (
|
|
|
125
126
|
}
|
|
126
127
|
};
|
|
127
128
|
|
|
129
|
+
// Track if a network request is in flight to prevent overlapping requests
|
|
130
|
+
let networkRequestInFlight = false;
|
|
131
|
+
|
|
128
132
|
async function updateNetwork() {
|
|
133
|
+
// Prevent overlapping requests - if one is already in flight, skip this cycle
|
|
134
|
+
if (networkRequestInFlight) {
|
|
135
|
+
emitter.emit(events.log.debug, '[redraw] updateNetwork() - skipping, request already in flight');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
129
139
|
if (sandbox && sandbox.instanceSocketConnected) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
network
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
networkRequestInFlight = true;
|
|
141
|
+
try {
|
|
142
|
+
let network = await sandbox.send({
|
|
143
|
+
type: "system.network",
|
|
144
|
+
}, 10000); // Use a shorter 10 second timeout for network stats
|
|
145
|
+
parseNetworkStats(
|
|
146
|
+
network.out.totalBytesReceived,
|
|
147
|
+
network.out.totalBytesSent,
|
|
148
|
+
);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
// Log the error but don't throw - network monitoring is non-critical
|
|
151
|
+
emitter.emit(events.log.debug, `[redraw] updateNetwork() failed: ${error.message}`);
|
|
152
|
+
} finally {
|
|
153
|
+
networkRequestInFlight = false;
|
|
154
|
+
}
|
|
137
155
|
}
|
|
138
156
|
}
|
|
139
157
|
|
|
@@ -181,14 +199,7 @@ const createRedraw = (
|
|
|
181
199
|
}
|
|
182
200
|
}
|
|
183
201
|
|
|
184
|
-
//
|
|
185
|
-
function startNetworkMonitoring() {
|
|
186
|
-
if (!networkInterval) {
|
|
187
|
-
networkInterval = setInterval(updateNetwork, networkUpdateInterval);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Stop network monitoring
|
|
202
|
+
// Stop network monitoring (cleanup any residual interval)
|
|
192
203
|
function stopNetworkMonitoring() {
|
|
193
204
|
if (networkInterval) {
|
|
194
205
|
clearInterval(networkInterval);
|
|
@@ -220,11 +231,6 @@ const createRedraw = (
|
|
|
220
231
|
|
|
221
232
|
resetState();
|
|
222
233
|
|
|
223
|
-
// Only start network monitoring if enabled
|
|
224
|
-
if (currentOptions.networkMonitor) {
|
|
225
|
-
startNetworkMonitoring();
|
|
226
|
-
}
|
|
227
|
-
|
|
228
234
|
// Capture initial image for screen stability monitoring
|
|
229
235
|
if (currentOptions.screenRedraw) {
|
|
230
236
|
initialScreenImage = await system.captureScreenPNG(0.25, true);
|
|
@@ -244,6 +250,11 @@ const createRedraw = (
|
|
|
244
250
|
return;
|
|
245
251
|
}
|
|
246
252
|
|
|
253
|
+
// Update network stats on each check (with guard against overlapping requests)
|
|
254
|
+
if (networkMonitor) {
|
|
255
|
+
await updateNetwork();
|
|
256
|
+
}
|
|
257
|
+
|
|
247
258
|
let nowImage = screenRedraw ? await system.captureScreenPNG(0.25, true) : null;
|
|
248
259
|
let timeElapsed = Date.now() - startTime;
|
|
249
260
|
let diffFromInitial = 0;
|
|
@@ -305,7 +316,7 @@ const createRedraw = (
|
|
|
305
316
|
: effectiveNetworkSettled
|
|
306
317
|
? theme.green(`y`)
|
|
307
318
|
: theme.dim(
|
|
308
|
-
`${Math.trunc((diffRxBytes + diffTxBytes) /
|
|
319
|
+
`${Math.trunc((diffRxBytes + diffTxBytes) / (networkCheckInterval / 1000))}b/s`,
|
|
309
320
|
);
|
|
310
321
|
let timeoutText = isTimeout
|
|
311
322
|
? theme.green(`y`)
|
|
@@ -370,10 +381,6 @@ const createRedraw = (
|
|
|
370
381
|
|
|
371
382
|
return new Promise((resolve) => {
|
|
372
383
|
const startTime = Date.now();
|
|
373
|
-
// Start network monitoring if not already started and enabled
|
|
374
|
-
if (waitOptions.networkMonitor) {
|
|
375
|
-
startNetworkMonitoring();
|
|
376
|
-
}
|
|
377
384
|
checkCondition(resolve, startTime, timeoutMs, waitOptions);
|
|
378
385
|
});
|
|
379
386
|
}
|
package/ai/agents/testdriver.md
CHANGED
|
@@ -44,7 +44,8 @@ Use this agent when the user asks to:
|
|
|
44
44
|
4. **⚠️ WRITE CODE IMMEDIATELY**: After EVERY successful action, append the generated code to the test file RIGHT AWAY. Do NOT wait until the end.
|
|
45
45
|
5. **Verify Actions**: Use `check` after actions to verify they succeeded (for YOUR understanding only).
|
|
46
46
|
6. **Add Assertions**: Use `assert` for test conditions that should be in the final test file.
|
|
47
|
-
7. **⚠️ RUN THE TEST YOURSELF**: Use `
|
|
47
|
+
7. **⚠️ RUN THE TEST YOURSELF**: Use `vitest run <testFile> --reporter=dot` to run the test - do NOT tell the user to run it. Iterate until it passes. **NEVER use `npx vitest`** - always use `vitest` directly.
|
|
48
|
+
8. **⚠️ SHARE THE TEST REPORT**: After EVERY test run, find the `TESTDRIVER_RUN_URL` in the output (e.g., `TESTDRIVER_RUN_URL=https://console.testdriver.ai/runs/...`) and share it with the user so they can view the recording and results.
|
|
48
49
|
|
|
49
50
|
## Prerequisites
|
|
50
51
|
|
|
@@ -80,7 +81,7 @@ The `init` command creates:
|
|
|
80
81
|
|
|
81
82
|
**After running init:**
|
|
82
83
|
1. User adds their API key to `.env`: `TD_API_KEY=...`
|
|
83
|
-
2. Test the setup: `
|
|
84
|
+
2. Test the setup: `vitest run`
|
|
84
85
|
3. Start building custom tests using the examples as templates
|
|
85
86
|
|
|
86
87
|
### API Key Setup
|
|
@@ -254,7 +255,7 @@ TestDriver **automatically captures screenshots before and after every command**
|
|
|
254
255
|
|
|
255
256
|
**Every MCP tool response includes "ACTION REQUIRED: Append this code..." - you MUST write that code to the test file IMMEDIATELY before proceeding to the next action.**
|
|
256
257
|
|
|
257
|
-
**When ready to validate, RUN THE TEST YOURSELF using `
|
|
258
|
+
**When ready to validate, RUN THE TEST YOURSELF using `vitest run`. Do NOT tell the user to run it. NEVER use `npx vitest`.**
|
|
258
259
|
|
|
259
260
|
### Step 1: Start a Session
|
|
260
261
|
|
|
@@ -311,17 +312,17 @@ assert({ assertion: "the dashboard is visible" })
|
|
|
311
312
|
|
|
312
313
|
### Step 5: Run the Test Yourself
|
|
313
314
|
|
|
314
|
-
**⚠️ YOU must run the test - do NOT tell the user to run it:**
|
|
315
|
+
**⚠️ YOU must run the test - do NOT tell the user to run it. NEVER use `npx vitest` - always use `vitest` directly:**
|
|
315
316
|
|
|
316
317
|
```bash
|
|
317
|
-
|
|
318
|
+
vitest run tests/login.test.mjs --reporter=dot
|
|
318
319
|
```
|
|
319
320
|
|
|
320
321
|
**Always use `--reporter=dot`** for cleaner, more concise output that's easier to parse.
|
|
321
322
|
|
|
322
323
|
Analyze the output, fix any issues, and iterate until the test passes.
|
|
323
324
|
|
|
324
|
-
**⚠️ ALWAYS share the test report link with the user.** After each test run, look for
|
|
325
|
+
**⚠️ ALWAYS share the test report link with the user.** After each test run, look for `TESTDRIVER_RUN_URL` in the test output (e.g., `TESTDRIVER_RUN_URL=https://console.testdriver.ai/runs/...`) and share it with the user so they can view the recording and results. This is CRITICAL - users need to see the visual recording to understand test behavior.
|
|
325
326
|
|
|
326
327
|
### MCP Tools Reference
|
|
327
328
|
|
|
@@ -456,7 +457,7 @@ list_local_screenshots({ directory: "checkout.test", phase: "before", limit: 10
|
|
|
456
457
|
### Tips for MCP Workflow
|
|
457
458
|
|
|
458
459
|
1. **⚠️ Write code IMMEDIATELY** - After EVERY action, append generated code to test file RIGHT AWAY
|
|
459
|
-
2. **⚠️ Run tests YOURSELF** - Use `
|
|
460
|
+
2. **⚠️ Run tests YOURSELF** - Use `vitest run` (NEVER `npx vitest`) - do NOT tell user to run tests
|
|
460
461
|
3. **⚠️ Add screenshots liberally** - Include `await testdriver.screenshot()` after every significant action for debugging
|
|
461
462
|
4. **⚠️ Use screenshot viewing for debugging** - When tests fail, use `list_local_screenshots` and `view_local_screenshot` to understand what went wrong
|
|
462
463
|
5. **Work incrementally** - Don't try to build the entire test at once
|
|
@@ -616,7 +617,8 @@ await testdriver.screenshot(1, false, true);
|
|
|
616
617
|
## Tips for Agents
|
|
617
618
|
|
|
618
619
|
1. **⚠️ WRITE CODE IMMEDIATELY** - After EVERY successful MCP action, append the generated code to the test file RIGHT AWAY. Do NOT wait until the session ends.
|
|
619
|
-
2. **⚠️ RUN TESTS YOURSELF** - Do NOT tell the user to run tests. YOU must run the tests using `
|
|
620
|
+
2. **⚠️ RUN TESTS YOURSELF** - Do NOT tell the user to run tests. YOU must run the tests using `vitest run <testFile> --reporter=dot` (NEVER use `npx vitest` - it breaks the reporter). Always use `--reporter=dot` for cleaner output. Analyze the output and iterate until the test passes.
|
|
621
|
+
3. **⚠️ SHARE THE TEST REPORT URL** - After EVERY test run, find `TESTDRIVER_RUN_URL=https://console.testdriver.ai/runs/...` in the output and share it with the user. This is CRITICAL - users need to view the recording to understand what happened.
|
|
620
622
|
3. **Screenshots are automatic** - TestDriver captures screenshots before/after every command by default. Each screenshot filename includes the line number (e.g., `001-click-before-L42-submit-button.png`) making it easy to trace issues.
|
|
621
623
|
4. **⚠️ USE SCREENSHOT VIEWING FOR DEBUGGING** - When tests fail, use `list_local_screenshots` and `view_local_screenshot` MCP commands to see exactly what the UI looked like. The filenames tell you which line of code triggered each screenshot.
|
|
622
624
|
5. **⚠️ NEVER USE `.wait()`** - Do NOT use any `.wait()` method. Instead, use `find()` with a `timeout` option to poll for elements, or use `assert()` / `check()` to verify state. Explicit waits are flaky and slow.
|