@testdriverai/agent 7.11.239-test → 7.11.241-canary
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/ai/skills/testdriver-agent/SKILL.md +174 -91
- package/ai/skills/testdriver-assert/SKILL.md +73 -269
- package/ai/skills/testdriver-aws-setup/SKILL.md +194 -312
- package/ai/skills/testdriver-bring-your-own-machine/SKILL.md +137 -204
- package/ai/skills/testdriver-cache/SKILL.md +142 -149
- package/ai/skills/testdriver-caching/SKILL.md +97 -87
- package/ai/skills/testdriver-captcha/SKILL.md +126 -111
- package/ai/skills/testdriver-ci-cd/SKILL.md +153 -542
- package/ai/skills/testdriver-click/SKILL.md +74 -229
- package/ai/skills/testdriver-client/SKILL.md +175 -229
- package/ai/skills/testdriver-customizing-devices/SKILL.md +72 -250
- package/ai/skills/testdriver-dashcam/SKILL.md +71 -404
- package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +103 -369
- package/ai/skills/testdriver-double-click/SKILL.md +46 -67
- package/ai/skills/testdriver-errors/SKILL.md +102 -176
- package/ai/skills/testdriver-events/SKILL.md +170 -327
- package/ai/skills/testdriver-exec/SKILL.md +92 -256
- package/ai/skills/testdriver-extract/SKILL.md +69 -170
- package/ai/skills/testdriver-find/SKILL.md +140 -736
- package/ai/skills/testdriver-focus-application/SKILL.md +69 -246
- package/ai/skills/testdriver-generating-tests/SKILL.md +102 -136
- package/ai/skills/testdriver-hosted/SKILL.md +79 -143
- package/ai/skills/testdriver-hover/SKILL.md +62 -235
- package/ai/skills/testdriver-locating-elements/SKILL.md +71 -366
- package/ai/skills/testdriver-making-assertions/SKILL.md +114 -72
- package/ai/skills/testdriver-mcp-setup/SKILL.md +79 -62
- package/ai/skills/testdriver-mouse-down/SKILL.md +46 -124
- package/ai/skills/testdriver-mouse-up/SKILL.md +45 -128
- package/ai/skills/testdriver-options/SKILL.md +73 -46
- package/ai/skills/testdriver-parse/SKILL.md +95 -184
- package/ai/skills/testdriver-performing-actions/SKILL.md +101 -91
- package/ai/skills/testdriver-press-keys/SKILL.md +59 -299
- package/ai/skills/testdriver-provision/SKILL.md +135 -179
- package/ai/skills/testdriver-quickstart/SKILL.md +24 -8
- package/ai/skills/testdriver-quickstart-claude/SKILL.md +84 -0
- package/ai/skills/testdriver-quickstart-github/SKILL.md +62 -32
- package/ai/skills/testdriver-quickstart-manual/SKILL.md +59 -32
- package/ai/skills/testdriver-quickstart-vscode/SKILL.md +96 -0
- package/ai/skills/testdriver-redraw/SKILL.md +100 -164
- package/ai/skills/testdriver-reusable-code/SKILL.md +95 -199
- package/ai/skills/testdriver-right-click/SKILL.md +45 -88
- package/ai/skills/testdriver-screenshot/SKILL.md +47 -201
- package/ai/skills/testdriver-screenshots/SKILL.md +86 -136
- package/ai/skills/testdriver-scroll/SKILL.md +71 -154
- package/ai/skills/testdriver-secrets/SKILL.md +94 -90
- package/ai/skills/testdriver-self-hosted/SKILL.md +82 -140
- package/ai/skills/testdriver-test-results-json/SKILL.md +165 -202
- package/ai/skills/testdriver-type/SKILL.md +56 -304
- package/ai/skills/testdriver-variables/SKILL.md +119 -80
- package/ai/skills/testdriver-wait/SKILL.md +31 -29
- package/ai/skills/testdriver-what-is-testdriver/SKILL.md +80 -32
- package/package.json +1 -1
|
@@ -1,356 +1,199 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testdriver:events
|
|
3
|
-
description: Listen to
|
|
3
|
+
description: Listen to what TestDriver does during a test through its event emitter.
|
|
4
4
|
---
|
|
5
5
|
<!-- Generated from events.mdx. DO NOT EDIT. -->
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
TestDriver uses [EventEmitter2](https://github.com/EventEmitter2/EventEmitter2) for its event system. Events use a namespace pattern with colons. They permit wildcard listeners.
|
|
10
|
-
|
|
11
|
-
Use the emitter through `testdriver.emitter`:
|
|
12
|
-
|
|
13
|
-
```javascript
|
|
14
|
-
testdriver.emitter.on('command:start', (data) => {
|
|
15
|
-
console.log(`Running: ${data.command}`);
|
|
16
|
-
});
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### Configuration
|
|
20
|
-
|
|
21
|
-
The internal emitter is created with:
|
|
22
|
-
|
|
23
|
-
```javascript
|
|
24
|
-
new EventEmitter2({
|
|
25
|
-
wildcard: true,
|
|
26
|
-
delimiter: ':',
|
|
27
|
-
maxListeners: 20,
|
|
28
|
-
verboseMemoryLeak: false,
|
|
29
|
-
ignoreErrors: false,
|
|
30
|
-
});
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### Wildcard Listeners
|
|
34
|
-
|
|
35
|
-
Use `*` to match one level. Use `**` to match many levels:
|
|
36
|
-
|
|
37
|
-
```javascript
|
|
38
|
-
// Match all log events
|
|
39
|
-
testdriver.emitter.on('log:*', (message) => {
|
|
40
|
-
console.log(message);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Match all events in any namespace
|
|
44
|
-
testdriver.emitter.on('**', (...args) => {
|
|
45
|
-
console.log('Event:', this.event, args);
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Event Reference
|
|
50
|
-
|
|
51
|
-
### Command Events
|
|
52
|
-
|
|
53
|
-
Emitted during the execution of SDK commands (`click`, `type`, `find`, etc.).
|
|
54
|
-
|
|
55
|
-
| Event | Payload |
|
|
56
|
-
|---|---|
|
|
57
|
-
| `command:start` | `{ command, depth, data, timestamp, sourcePosition }` |
|
|
58
|
-
| `command:success` | `{ command, depth, data, duration, response, timestamp, sourcePosition }` |
|
|
59
|
-
| `command:error` | `{ command, depth, data, error, duration, timestamp, sourcePosition }` |
|
|
60
|
-
| `command:status` | `{ command, status: "executing", data, depth, timestamp }` |
|
|
61
|
-
| `command:progress` | `{ command, status: "completed", timing, data, depth, timestamp }` |
|
|
62
|
-
|
|
63
|
-
```javascript
|
|
64
|
-
testdriver.emitter.on('command:start', ({ command, data }) => {
|
|
65
|
-
console.log(`Starting ${command}`, data);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
testdriver.emitter.on('command:error', ({ command, error, duration }) => {
|
|
69
|
-
console.error(`${command} failed after ${duration}ms: ${error}`);
|
|
70
|
-
});
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Step Events
|
|
74
|
-
|
|
75
|
-
Emitted for each AI reasoning step within a command.
|
|
76
|
-
|
|
77
|
-
| Event | Payload |
|
|
78
|
-
|---|---|
|
|
79
|
-
| `step:start` | `{ stepIndex, prompt, commandCount, timestamp, sourcePosition }` |
|
|
80
|
-
| `step:success` | `{ stepIndex, prompt, commandCount, duration, timestamp, sourcePosition }` |
|
|
81
|
-
| `step:error` | `{ stepIndex, prompt, error, duration?, timestamp, sourcePosition? }` |
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
testdriver.emitter.on('step:start', ({ stepIndex, prompt }) => {
|
|
85
|
-
console.log(`Step ${stepIndex}: ${prompt}`);
|
|
86
|
-
});
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Test Events
|
|
90
|
-
|
|
91
|
-
Emitted when a test file execution starts.
|
|
92
|
-
|
|
93
|
-
| Event | Payload |
|
|
94
|
-
|---|---|
|
|
95
|
-
| `test:start` | `{ filePath, timestamp }` |
|
|
96
|
-
| `test:success` | *Emitted on test completion* |
|
|
97
|
-
| `test:error` | *Emitted on test failure* |
|
|
98
|
-
|
|
99
|
-
### Log Events
|
|
100
|
-
|
|
101
|
-
Emitted for all log output from the SDK.
|
|
102
|
-
|
|
103
|
-
| Event | Payload |
|
|
104
|
-
|---|---|
|
|
105
|
-
| `log:log` | `(message: string)` — general log message |
|
|
106
|
-
| `log:warn` | `(message: string)` — warning message |
|
|
107
|
-
| `log:debug` | `(message: string)` — debug output (only when `VERBOSE`/`DEBUG`/`TD_DEBUG` env set) |
|
|
108
|
-
| `log:info` | `(message: string)` — informational message |
|
|
109
|
-
| `log:error` | `(message: string)` — error message |
|
|
110
|
-
| `log:narration` | `(message: string, overwrite?: boolean)` — in-place status line |
|
|
111
|
-
| `log:markdown` | `(markdown: string)` — full static markdown content |
|
|
112
|
-
| `log:markdown:start` | `(streamId: string)` — begin streaming markdown |
|
|
113
|
-
| `log:markdown:chunk` | `(streamId: string, chunk: string)` — incremental chunk |
|
|
114
|
-
| `log:markdown:end` | `(streamId: string)` — end streaming markdown |
|
|
7
|
+
TestDriver reports what it's doing through an event emitter. Get it with [`getEmitter()`](/client#getemitter) and listen with `on()`:
|
|
115
8
|
|
|
116
9
|
```javascript
|
|
117
|
-
|
|
118
|
-
testdriver.emitter.on('log:*', function (message) {
|
|
119
|
-
console.log(`[${this.event}]`, message);
|
|
120
|
-
});
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Screen Capture Events
|
|
124
|
-
|
|
125
|
-
Emitted during screenshot capture.
|
|
10
|
+
const emitter = testdriver.getEmitter();
|
|
126
11
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
| `screen-capture:start` | `{ scale, silent, display }` |
|
|
130
|
-
| `screen-capture:end` | `{ scale, silent, display }` |
|
|
131
|
-
| `screen-capture:error` | `{ error, scale, silent, display }` |
|
|
132
|
-
|
|
133
|
-
### Sandbox Events
|
|
134
|
-
|
|
135
|
-
Emitted for sandbox WebSocket lifecycle and communication.
|
|
136
|
-
|
|
137
|
-
| Event | Payload |
|
|
138
|
-
|---|---|
|
|
139
|
-
| `sandbox:connected` | *No payload* — WebSocket connection established |
|
|
140
|
-
| `sandbox:authenticated` | `{ traceId }` — authentication successful |
|
|
141
|
-
| `sandbox:error` | `(err: Error \| string)` — connection or sandbox error |
|
|
142
|
-
| `sandbox:sent` | `(message: object)` — WebSocket message sent |
|
|
143
|
-
| `sandbox:received` | *No payload* — successful message reply received |
|
|
144
|
-
| `sandbox:progress` | `{ step, message }` — sandbox setup progress |
|
|
145
|
-
|
|
146
|
-
```javascript
|
|
147
|
-
testdriver.emitter.on('sandbox:connected', () => {
|
|
148
|
-
console.log('Connected to sandbox');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
testdriver.emitter.on('sandbox:progress', ({ step, message }) => {
|
|
152
|
-
console.log(`Sandbox: [${step}] ${message}`);
|
|
12
|
+
emitter.on('sandbox:progress', ({ step, message }) => {
|
|
13
|
+
console.log(`[${step}] ${message}`);
|
|
153
14
|
});
|
|
154
15
|
```
|
|
155
16
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
Emitted during screen stability detection. See [Redraw](/redraw) for more details.
|
|
159
|
-
|
|
160
|
-
| Event | Payload |
|
|
161
|
-
|---|---|
|
|
162
|
-
| `redraw:status` | `{ redraw: { enabled, settled, hasChangedFromInitial, consecutiveFramesStable, diffFromInitial, diffFromLast, text }, network: { enabled, settled, rxBytes, txBytes, text }, timeout: { isTimeout, elapsed, max, text } }` |
|
|
163
|
-
| `redraw:complete` | `{ screenSettled, hasChangedFromInitial, consecutiveFramesStable, networkSettled, isTimeout, timeElapsed }` |
|
|
164
|
-
|
|
165
|
-
```javascript
|
|
166
|
-
testdriver.emitter.on('redraw:complete', (result) => {
|
|
167
|
-
if (result.isTimeout) {
|
|
168
|
-
console.warn('Redraw timed out after', result.timeElapsed, 'ms');
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
```
|
|
17
|
+
The emitter is an [EventEmitter2](https://github.com/EventEmitter2/EventEmitter2) instance. Event names are segments separated by colons, such as `redraw:complete`.
|
|
172
18
|
|
|
173
|
-
|
|
19
|
+
## Listen in a test
|
|
174
20
|
|
|
175
|
-
|
|
21
|
+
The emitter exists as soon as you create the client, so add listeners before the first command:
|
|
176
22
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
| `file:stop` | `{ operation, filePath, duration, success, sourceMap?, reason?, timestamp }` |
|
|
181
|
-
| `file:load` | `{ filePath, size, timestamp }` |
|
|
182
|
-
| `file:save` | `{ filePath, size, timestamp }` |
|
|
183
|
-
| `file:diff` | `{ filePath, diff: { patches, sourceMaps, summary: { additions, deletions, modifications } }, timestamp }` |
|
|
184
|
-
| `file:error` | `{ operation, filePath, error, duration?, timestamp }` |
|
|
23
|
+
```javascript tests/login.test.mjs
|
|
24
|
+
import { describe, expect, it } from 'vitest';
|
|
25
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
185
26
|
|
|
186
|
-
|
|
27
|
+
describe('Login', () => {
|
|
28
|
+
it('shows an error for an empty form', async (context) => {
|
|
29
|
+
const testdriver = TestDriver(context);
|
|
30
|
+
const emitter = testdriver.getEmitter();
|
|
187
31
|
|
|
188
|
-
|
|
32
|
+
const clicks = [];
|
|
33
|
+
emitter.on('mouse-click', ({ x, y, button }) => {
|
|
34
|
+
clicks.push({ x, y, button });
|
|
35
|
+
});
|
|
189
36
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
| `error:fatal` | `(error: string \| Error)` — terminates the process |
|
|
193
|
-
| `error:general` | `(message: string)` — non-fatal error |
|
|
194
|
-
| `error:sandbox` | `(err: Error \| string)` — sandbox/WebSocket error |
|
|
37
|
+
await testdriver.provision.chrome({ url: 'https://testdriver-sandbox.vercel.app/login' });
|
|
38
|
+
await testdriver.find('Sign in button below the password field').click();
|
|
195
39
|
|
|
196
|
-
|
|
197
|
-
testdriver.
|
|
198
|
-
|
|
40
|
+
console.log(clicks); // e.g. [{ x: 683, y: 412, button: 'left' }]
|
|
41
|
+
expect(await testdriver.assert('an error says the fields are required')).toBe(true);
|
|
42
|
+
});
|
|
199
43
|
});
|
|
200
44
|
```
|
|
201
45
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
Emitted for API request lifecycle.
|
|
46
|
+
## Use wildcards
|
|
205
47
|
|
|
206
|
-
|
|
207
|
-
|---|---|
|
|
208
|
-
| `sdk:request` | `{ path }` — outgoing API request |
|
|
209
|
-
| `sdk:response` | `{ path }` — API response received |
|
|
210
|
-
| `sdk:retry` | `{ path, attempt, error, delayMs }` — request retry |
|
|
211
|
-
|
|
212
|
-
### Other Events
|
|
213
|
-
|
|
214
|
-
| Event | Payload |
|
|
215
|
-
|---|---|
|
|
216
|
-
| `exit` | `(exitCode: number)` — `0` for success, `1` for failure |
|
|
217
|
-
| `status` | `(message: string)` — general status updates |
|
|
218
|
-
| `mouse-click` | `{ x, y, button, click, double }` — mouse click performed |
|
|
219
|
-
| `terminal:stdout` | Terminal stdout output |
|
|
220
|
-
| `terminal:stderr` | Terminal stderr output |
|
|
221
|
-
|
|
222
|
-
## Practical Examples
|
|
223
|
-
|
|
224
|
-
### Custom Test Reporter
|
|
225
|
-
|
|
226
|
-
```javascript
|
|
227
|
-
const results = [];
|
|
228
|
-
|
|
229
|
-
testdriver.emitter.on('command:success', ({ command, duration }) => {
|
|
230
|
-
results.push({ command, duration, status: 'pass' });
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
testdriver.emitter.on('command:error', ({ command, duration, error }) => {
|
|
234
|
-
results.push({ command, duration, status: 'fail', error });
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
// After test completes
|
|
238
|
-
afterAll(() => {
|
|
239
|
-
console.table(results);
|
|
240
|
-
});
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
### Progress Monitoring
|
|
48
|
+
`*` matches one segment. `**` matches any number of segments. Use a `function` listener, not an arrow function, to read the event's name from `this.event`:
|
|
244
49
|
|
|
245
50
|
```javascript
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
testdriver.emitter.on('command:progress', ({ command, timing }) => {
|
|
251
|
-
process.stdout.write(`\r ${command} completed in ${timing}ms`);
|
|
51
|
+
// Every error event: error:fatal, error:sdk, and so on
|
|
52
|
+
emitter.on('error:*', function (error) {
|
|
53
|
+
console.error(`[${this.event}]`, error);
|
|
252
54
|
});
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Debug Logging
|
|
256
55
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
console.debug(`[EVENT] ${this.event}`, ...args);
|
|
56
|
+
// Every event, with its arguments
|
|
57
|
+
emitter.on('**', function (...args) {
|
|
58
|
+
console.debug(this.event, ...args);
|
|
261
59
|
});
|
|
262
60
|
```
|
|
263
61
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
62
|
+
`log:*` matches `log:log` and `log:warn` but not `log:markdown:start`, which has three segments. Use `log:**` to match all of them.
|
|
63
|
+
|
|
64
|
+
## Log events
|
|
65
|
+
|
|
66
|
+
The SDK prints these to the console unless you turn logging off with the `logging` option.
|
|
67
|
+
|
|
68
|
+
| Event | Arguments | When |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| `log:log` | `(message: string)` | General output, such as each action and `find()` |
|
|
71
|
+
| `log:warn` | `(message: string)` | A warning |
|
|
72
|
+
| `log:debug` | `(message: string)` | Debug detail. Always emitted, but printed only when `VERBOSE` or `TD_DEBUG` is set |
|
|
73
|
+
| `log:narration` | `(message: string, overwrite?: boolean)` | Progress detail for an action, such as how long a redraw wait took |
|
|
74
|
+
| `log:markdown` | `(markdown: string)` | A complete Markdown message from `ai()` |
|
|
75
|
+
| `log:markdown:start` | `(streamId: string)` | `ai()` starts streaming a Markdown message |
|
|
76
|
+
| `log:markdown:chunk` | `(streamId: string, chunk: string)` | The next piece of that message |
|
|
77
|
+
| `log:markdown:end` | `(streamId: string)` | The message is complete |
|
|
78
|
+
|
|
79
|
+
There's no `log:info` or `log:error` in the event list. Listen to `log:log` and `error:*` instead.
|
|
80
|
+
|
|
81
|
+
## Error events
|
|
82
|
+
|
|
83
|
+
| Event | Arguments | When |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| `error:fatal` | `(error: string \| Error)` | TestDriver hit an error it can't recover from |
|
|
86
|
+
| `error:general` | `(message: string)` | A non-fatal error |
|
|
87
|
+
| `error:sdk` | `({ message, code, ... })` | A request to the TestDriver API failed |
|
|
88
|
+
| `error:sandbox` | `(message: string)` | The sandbox reported an error, or the realtime connection to it failed |
|
|
89
|
+
|
|
90
|
+
## Sandbox events
|
|
91
|
+
|
|
92
|
+
| Event | Arguments | When |
|
|
93
|
+
| --- | --- | --- |
|
|
94
|
+
| `sandbox:authenticated` | `({ traceId })` | The connection to the sandbox is authenticated |
|
|
95
|
+
| `sandbox:connected` | none | The client is connected to a sandbox |
|
|
96
|
+
| `sandbox:progress` | `({ step, message })` | A setup step while the sandbox starts, or recovery after a dropped connection |
|
|
97
|
+
| `sandbox:sent` | `(message: object)` | A message was sent to the sandbox |
|
|
98
|
+
| `sandbox:received` | none | The sandbox replied to a message |
|
|
99
|
+
| `sandbox:file` | `(message: object)` | The sandbox sent a file message |
|
|
100
|
+
| `show-window` | `(url: string)` | The live preview URL is ready to open |
|
|
101
|
+
|
|
102
|
+
## Action events
|
|
103
|
+
|
|
104
|
+
| Event | Arguments | When |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
| `mouse-click` | `({ x, y, button, double })` | A click, double-click, right-click, `mouseDown()`, or `mouseUp()` was sent. `button` is `'left'` or `'right'`, and `double` is `true` for a double-click |
|
|
107
|
+
| `exec:output` | `({ chunk, requestId })` | A piece of output from a running [`exec()`](/exec) command |
|
|
108
|
+
| `screen-capture:start` | `({ scale, silent, display })` | TestDriver starts capturing the screen |
|
|
109
|
+
| `screen-capture:end` | `({ scale, silent, display })` | The capture finished |
|
|
110
|
+
| `screen-capture:error` | `({ error, scale, silent, display })` | The capture failed |
|
|
111
|
+
|
|
112
|
+
## Redraw events
|
|
113
|
+
|
|
114
|
+
Emitted only when [redraw detection](/redraw) is on.
|
|
115
|
+
|
|
116
|
+
| Event | Arguments | When |
|
|
117
|
+
| --- | --- | --- |
|
|
118
|
+
| `redraw:status` | `(status: object)` | Every 500 ms while TestDriver waits for the screen to settle |
|
|
119
|
+
| `redraw:complete` | `(result: object)` | The wait ended, either settled or timed out |
|
|
120
|
+
|
|
121
|
+
<ResponseField name="redraw:status" type="object">
|
|
122
|
+
<Expandable title="properties">
|
|
123
|
+
<ResponseField name="redraw" type="object">
|
|
124
|
+
Screen state: `enabled`, `settled`, `hasChangedFromInitial`, `consecutiveFramesStable` (booleans), `diffFromInitial` and `diffFromLast` (percent of pixels that differ), and `text` (a short summary for the console).
|
|
125
|
+
</ResponseField>
|
|
126
|
+
<ResponseField name="network" type="object">
|
|
127
|
+
Network state: `enabled`, `settled` (booleans), `rxBytes` and `txBytes` (bytes since the last check), and `text`.
|
|
128
|
+
</ResponseField>
|
|
129
|
+
<ResponseField name="timeout" type="object">
|
|
130
|
+
Timing: `isTimeout` (boolean), `elapsed` and `max` (milliseconds), and `text`.
|
|
131
|
+
</ResponseField>
|
|
132
|
+
</Expandable>
|
|
133
|
+
</ResponseField>
|
|
134
|
+
|
|
135
|
+
<ResponseField name="redraw:complete" type="object">
|
|
136
|
+
<Expandable title="properties">
|
|
137
|
+
<ResponseField name="screenSettled" type="boolean">
|
|
138
|
+
Whether the screen settled. `true` when the screen check is off.
|
|
139
|
+
</ResponseField>
|
|
140
|
+
<ResponseField name="networkSettled" type="boolean">
|
|
141
|
+
Whether network traffic settled. `true` when the network check is off.
|
|
142
|
+
</ResponseField>
|
|
143
|
+
<ResponseField name="hasChangedFromInitial" type="boolean">
|
|
144
|
+
Whether the screen changed after the action.
|
|
145
|
+
</ResponseField>
|
|
146
|
+
<ResponseField name="consecutiveFramesStable" type="boolean">
|
|
147
|
+
Whether the last frames stopped changing.
|
|
148
|
+
</ResponseField>
|
|
149
|
+
<ResponseField name="isTimeout" type="boolean">
|
|
150
|
+
Whether the wait ended because it ran out of time.
|
|
151
|
+
</ResponseField>
|
|
152
|
+
<ResponseField name="timeElapsed" type="number">
|
|
153
|
+
How long the wait took, in milliseconds.
|
|
154
|
+
</ResponseField>
|
|
155
|
+
</Expandable>
|
|
156
|
+
</ResponseField>
|
|
157
|
+
|
|
158
|
+
## API request events
|
|
159
|
+
|
|
160
|
+
| Event | Arguments | When |
|
|
161
|
+
| --- | --- | --- |
|
|
162
|
+
| `sdk:request` | `({ path })` | A request to the TestDriver API starts |
|
|
163
|
+
| `sdk:response` | `({ path })` | The API responded |
|
|
164
|
+
| `sdk:retry` | `({ path, attempt, error, delayMs })` | A failed request will be retried after `delayMs` milliseconds |
|
|
165
|
+
|
|
166
|
+
## ai() command events
|
|
167
|
+
|
|
168
|
+
These fire for the commands the AI runs inside [`ai()`](/errors#aierror). Commands you call yourself, such as `testdriver.click()`, don't emit them.
|
|
169
|
+
|
|
170
|
+
| Event | Arguments |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| `command:start` | `({ command, depth, data, timestamp, sourcePosition })` |
|
|
173
|
+
| `command:status` | `({ command, status: 'executing', data, depth, timestamp })` |
|
|
174
|
+
| `command:progress` | `({ command, status: 'completed', timing, data, depth, timestamp })` |
|
|
175
|
+
| `command:success` | `({ command, depth, data, duration, response, timestamp, sourcePosition })` |
|
|
176
|
+
| `command:error` | `({ command, depth, data, error, duration, timestamp, sourcePosition })` |
|
|
177
|
+
|
|
178
|
+
- `command` is the command name, and `data` is the full command the AI generated.
|
|
179
|
+
- `error` is the error message as a string.
|
|
180
|
+
- `timing` and `duration` are in milliseconds.
|
|
181
|
+
|
|
182
|
+
## Other events
|
|
183
|
+
|
|
184
|
+
| Event | Arguments | When |
|
|
185
|
+
| --- | --- | --- |
|
|
186
|
+
| `runner:log` | `({ level, message, timestamp })` | A log line from the sandbox's runner. Sent only when debug logging is on |
|
|
187
|
+
| `exit` | `(exitCode: number)` | The agent stopped. `0` means success, `1` means failure |
|
|
188
|
+
|
|
189
|
+
The event list also contains names that Vitest tests don't emit:
|
|
190
|
+
|
|
191
|
+
- `step:*`, `test:*`, and `file:*` come from running YAML test files.
|
|
192
|
+
- `command:stop`, `command:location`, `sandbox:error`, `sandbox:disconnected`, `sdk:error`, `sdk:progress`, `status`, `mouse-move`, `terminal:stdout`, `terminal:stderr`, `matches:show`, and `vm:show` aren't currently emitted.
|
|
193
|
+
|
|
194
|
+
## Related
|
|
195
|
+
|
|
196
|
+
- [getEmitter()](/client#getemitter): get the client's emitter
|
|
197
|
+
- [Redraw](/redraw): what the redraw events measure
|
|
198
|
+
- [Errors](/errors): the errors TestDriver throws
|
|
199
|
+
- [Debug a failing test](/debugging-with-screenshots): find out why a test failed
|