@testdriverai/agent 7.11.240-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.
Files changed (52) hide show
  1. package/ai/skills/testdriver-agent/SKILL.md +174 -91
  2. package/ai/skills/testdriver-assert/SKILL.md +73 -269
  3. package/ai/skills/testdriver-aws-setup/SKILL.md +194 -312
  4. package/ai/skills/testdriver-bring-your-own-machine/SKILL.md +137 -204
  5. package/ai/skills/testdriver-cache/SKILL.md +142 -149
  6. package/ai/skills/testdriver-caching/SKILL.md +97 -87
  7. package/ai/skills/testdriver-captcha/SKILL.md +126 -111
  8. package/ai/skills/testdriver-ci-cd/SKILL.md +153 -542
  9. package/ai/skills/testdriver-click/SKILL.md +74 -229
  10. package/ai/skills/testdriver-client/SKILL.md +175 -229
  11. package/ai/skills/testdriver-customizing-devices/SKILL.md +72 -250
  12. package/ai/skills/testdriver-dashcam/SKILL.md +71 -404
  13. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +103 -369
  14. package/ai/skills/testdriver-double-click/SKILL.md +46 -67
  15. package/ai/skills/testdriver-errors/SKILL.md +102 -176
  16. package/ai/skills/testdriver-events/SKILL.md +170 -327
  17. package/ai/skills/testdriver-exec/SKILL.md +92 -256
  18. package/ai/skills/testdriver-extract/SKILL.md +69 -170
  19. package/ai/skills/testdriver-find/SKILL.md +140 -736
  20. package/ai/skills/testdriver-focus-application/SKILL.md +69 -246
  21. package/ai/skills/testdriver-generating-tests/SKILL.md +102 -136
  22. package/ai/skills/testdriver-hosted/SKILL.md +79 -143
  23. package/ai/skills/testdriver-hover/SKILL.md +62 -235
  24. package/ai/skills/testdriver-locating-elements/SKILL.md +71 -366
  25. package/ai/skills/testdriver-making-assertions/SKILL.md +114 -72
  26. package/ai/skills/testdriver-mcp-setup/SKILL.md +79 -62
  27. package/ai/skills/testdriver-mouse-down/SKILL.md +46 -124
  28. package/ai/skills/testdriver-mouse-up/SKILL.md +45 -128
  29. package/ai/skills/testdriver-options/SKILL.md +73 -46
  30. package/ai/skills/testdriver-parse/SKILL.md +95 -184
  31. package/ai/skills/testdriver-performing-actions/SKILL.md +101 -91
  32. package/ai/skills/testdriver-press-keys/SKILL.md +59 -299
  33. package/ai/skills/testdriver-provision/SKILL.md +135 -179
  34. package/ai/skills/testdriver-quickstart/SKILL.md +24 -8
  35. package/ai/skills/testdriver-quickstart-claude/SKILL.md +84 -0
  36. package/ai/skills/testdriver-quickstart-github/SKILL.md +62 -32
  37. package/ai/skills/testdriver-quickstart-manual/SKILL.md +59 -32
  38. package/ai/skills/testdriver-quickstart-vscode/SKILL.md +96 -0
  39. package/ai/skills/testdriver-redraw/SKILL.md +100 -164
  40. package/ai/skills/testdriver-reusable-code/SKILL.md +95 -199
  41. package/ai/skills/testdriver-right-click/SKILL.md +45 -88
  42. package/ai/skills/testdriver-screenshot/SKILL.md +47 -201
  43. package/ai/skills/testdriver-screenshots/SKILL.md +86 -136
  44. package/ai/skills/testdriver-scroll/SKILL.md +71 -154
  45. package/ai/skills/testdriver-secrets/SKILL.md +94 -90
  46. package/ai/skills/testdriver-self-hosted/SKILL.md +82 -140
  47. package/ai/skills/testdriver-test-results-json/SKILL.md +165 -202
  48. package/ai/skills/testdriver-type/SKILL.md +56 -304
  49. package/ai/skills/testdriver-variables/SKILL.md +119 -80
  50. package/ai/skills/testdriver-wait/SKILL.md +31 -29
  51. package/ai/skills/testdriver-what-is-testdriver/SKILL.md +80 -32
  52. package/package.json +1 -1
@@ -1,257 +1,220 @@
1
1
  ---
2
2
  name: testdriver:test-results-json
3
- description: Per-test JSON result files with metadata, versions, and infrastructure details
3
+ description: Read each test's result, replay link, and run details from a JSON file.
4
4
  ---
5
5
  <!-- Generated from test-results-json.mdx. DO NOT EDIT. -->
6
6
 
7
- ## Overview
7
+ TestDriver writes a JSON file for each test after it finishes.
8
8
 
9
- TestDriver writes a JSON result file for each test case after it finishes. These files have full metadata about the test run. This includes the SDK version, the runner version, infrastructure details, interaction statistics, and links to recordings.
9
+ - It has the test's result, error, and links to its report and replay.
10
+ - It also records versions, sandbox details, and how many `find()` calls hit the cache.
11
+ - Use it in CI scripts instead of parsing console output.
10
12
 
11
- TestDriver writes the result files to:
13
+ ## Turn it on
12
14
 
13
- ```
14
- .testdriver/results/<testFile>/<testName>.json
15
- ```
15
+ The TestDriver Vitest reporter writes the files. `npx testdriverai init` adds it to `vitest.config.js` for you:
16
16
 
17
- For example, a test file `tests/login.test.mjs` with a test named `"should log in"` produces:
17
+ ```javascript vitest.config.js
18
+ import { defineConfig } from 'vitest/config';
19
+ import TestDriver from 'testdriverai/vitest';
18
20
 
21
+ export default defineConfig({
22
+ test: {
23
+ testTimeout: 300000,
24
+ hookTimeout: 300000,
25
+ reporters: ['default', TestDriver()],
26
+ setupFiles: ['testdriverai/vitest/setup'],
27
+ },
28
+ });
19
29
  ```
20
- .testdriver/results/tests/login.test.mjs/should_log_in.json
21
- ```
22
-
23
- <Note>
24
- TestDriver makes the test names safe for the file system. It changes special characters to underscores. It cuts the names to 200 characters.
25
- </Note>
26
-
27
- ## Enabling
28
-
29
- You do not need configuration. The TestDriver Vitest reporter plugin writes the JSON files automatically each time the tests run.
30
-
31
- ## JSON Schema
32
-
33
- Each result file is organized into logical groups:
34
-
35
- ### `versions`
36
-
37
- | Field | Type | Description |
38
- |---|---|---|
39
- | `versions.sdk` | `string \| null` | TestDriver SDK version (e.g. `"7.8.0"`) |
40
- | `versions.vitest` | `string \| null` | Vitest version used to run the test |
41
- | `versions.api` | `string \| null` | TestDriver API server version |
42
- | `versions.runnerBefore` | `string \| null` | Runner version at sandbox start |
43
- | `versions.runnerAfter` | `string \| null` | Runner version after auto-update |
44
- | `versions.runnerWasUpdated` | `boolean` | Whether the runner was auto-updated during provisioning |
45
-
46
- ### `test`
47
-
48
- | Field | Type | Description |
49
- |---|---|---|
50
- | `test.file` | `string \| null` | Relative path to the test file |
51
- | `test.name` | `string \| null` | Name of the test case |
52
- | `test.suite` | `string \| null` | Name of the parent `describe` block |
53
- | `test.passed` | `boolean` | Whether the test passed |
54
- | `test.caseId` | `string \| null` | Database ID for this test case |
55
- | `test.runId` | `string \| null` | Database ID for the overall test run |
56
- | `test.error` | `string \| null` | Error message if the test failed |
57
- | `test.errorStack` | `string \| null` | Error stack trace if the test failed |
58
-
59
- ### `urls`
60
30
 
61
- | Field | Type | Description |
62
- |---|---|---|
63
- | `urls.api` | `string \| null` | API root URL used for this test |
64
- | `urls.console` | `string \| null` | TestDriver console base URL |
65
- | `urls.vnc` | `string \| null` | VNC URL for the sandbox |
66
- | `urls.testRun` | `string \| null` | Direct link to this test case in the console |
67
-
68
- ### `replay`
69
-
70
- The `replay` object contains the recording replay URL and derived embed links. The `gifUrl` and `embedUrl` are generated automatically from the replay URL.
71
-
72
- | Field | Type | Description |
73
- |---|---|---|
74
- | `replay.url` | `string \| null` | Recording replay URL |
75
- | `replay.gifUrl` | `string \| null` | Animated GIF thumbnail of the recording |
76
- | `replay.embedUrl` | `string \| null` | Embeddable replay URL (appends `&embed=true`) |
77
- | `replay.markdown` | `string \| null` | Ready-to-use Markdown embed with GIF linking to the replay |
31
+ The reporter records each run in TestDriver, so it needs your API key in `TD_API_KEY`. If it can't record the run, it doesn't write the files.
78
32
 
79
- The `replay.markdown` field produces a clickable GIF badge you can paste directly into PR comments, README files, or issue descriptions:
33
+ ## Where the files go
80
34
 
81
- ```markdown
82
- [![Test Recording](https://api.testdriver.ai/replay/abc123/gif?shareKey=xyz)](https://console.testdriver.ai/replay/abc123?share=xyz)
35
+ ```text
36
+ .testdriver/results/<test file>/<test id>.json
83
37
  ```
84
38
 
85
- ### `date`
39
+ - `<test file>` is the test file's path relative to the project root, such as `tests/login.test.mjs`.
40
+ - `<test id>` is Vitest's ID for the test, with characters other than letters, digits, `_`, `.`, and `-` replaced by `_`. Read the test's name from `test.name` inside the file.
86
41
 
87
- | Field | Type | Description |
88
- |---|---|---|
89
- | `date` | `string` | ISO 8601 timestamp when the test finished |
90
-
91
- ### `team`
92
-
93
- | Field | Type | Description |
94
- |---|---|---|
95
- | `team.id` | `string \| null` | Team ID from the sandbox |
96
- | `team.sessionId` | `string \| null` | SDK session ID |
42
+ The folder isn't cleared between runs. Delete `.testdriver/results` before a run if you only want the latest results.
97
43
 
98
- ### `infrastructure`
99
-
100
- | Field | Type | Description |
101
- |---|---|---|
102
- | `infrastructure.sandboxId` | `string \| null` | Sandbox instance ID |
103
- | `infrastructure.instanceId` | `string \| null` | Instance ID |
104
- | `infrastructure.os` | `string \| null` | Operating system of the sandbox (`"linux"` or `"windows"`) |
105
- | `infrastructure.amiId` | `string \| null` | AWS AMI ID used for provisioning |
106
- | `infrastructure.e2bTemplateId` | `string \| null` | E2B template ID used for provisioning |
107
- | `infrastructure.imageVersion` | `string \| null` | Sandbox image version |
108
-
109
- ### `realtime`
110
-
111
- | Field | Type | Description |
112
- |---|---|---|
113
- | `realtime.channel` | `string \| null` | Ably channel name used for communication |
114
- | `realtime.messageCount` | `number` | Number of messages published to the realtime channel |
115
-
116
- ### `interactions`
117
-
118
- | Field | Type | Description |
119
- |---|---|---|
120
- | `interactions.total` | `number` | Total number of interactions recorded |
121
- | `interactions.cached` | `number` | Number of interactions served from cache |
122
- | `interactions.byType` | `object` | Breakdown of interactions by type (e.g. `find`, `click`, `assert`) |
44
+ ## Example
123
45
 
124
- ## Example Output
125
-
126
- ```json
46
+ ```json .testdriver/results/tests/login.test.mjs/1223128da3_0_0.json
127
47
  {
128
- "sdkVersion": "7.8.0",
129
- "vitestVersion": "4.0.0",
130
- "apiVersion": "1.45.0",
131
- "runnerVersionBefore": "2.1.0",
132
- "runnerVersionAfter": "2.1.1",
133
- "wasUpdated": true,
134
- "apiUrl": "https://api.testdriver.ai",
135
- "consoleUrl": "https://console.testdriver.ai",
136
- "testRunLink": "https://console.testdriver.ai/runs/abc123/def456",
137
- "dashcamUrl": "https://app.dashcam.io/replay/abc123",
138
- "vncUrl": "wss://sandbox-123.testdriver.ai/vnc",
139
- "date": "2025-01-15T14:30:00.000Z",
48
+ "versions": {
49
+ "sdk": "7.11.228",
50
+ "vitest": "4.0.8",
51
+ "api": "7.11.228",
52
+ "runnerBefore": "2.4.1",
53
+ "runnerAfter": "2.4.1",
54
+ "runnerWasUpdated": false
55
+ },
56
+ "test": {
57
+ "file": "tests/login.test.mjs",
58
+ "name": "shows an error for an empty form",
59
+ "suite": "Login",
60
+ "passed": false,
61
+ "caseId": "6712f0c4e1a2b3c4d5e6f701",
62
+ "runId": "6712f0b9e1a2b3c4d5e6f700",
63
+ "error": "AI Assertion failed: an error says the fields are required",
64
+ "errorStack": "Error: AI Assertion failed: ..."
65
+ },
66
+ "urls": {
67
+ "api": "https://api.testdriver.ai",
68
+ "console": "https://console.testdriver.ai",
69
+ "vnc": null,
70
+ "testRun": "https://console.testdriver.ai/runs/6712f0b9e1a2b3c4d5e6f700/6712f0c4e1a2b3c4d5e6f701"
71
+ },
72
+ "replay": {
73
+ "url": "https://console.testdriver.ai/replay/6789abcdef0123456789abcd?share=k3y",
74
+ "gifUrl": "https://api.testdriver.ai/replay/6789abcdef0123456789abcd/gif?shareKey=k3y",
75
+ "embedUrl": "https://console.testdriver.ai/replay/6789abcdef0123456789abcd?share=k3y&embed=true",
76
+ "markdown": "[![Test Recording](https://api.testdriver.ai/replay/6789abcdef0123456789abcd/gif?shareKey=k3y)](https://console.testdriver.ai/replay/6789abcdef0123456789abcd?share=k3y)"
77
+ },
78
+ "date": "2026-10-21T14:30:00.000Z",
140
79
  "team": {
141
80
  "id": "team_abc123",
142
81
  "sessionId": "sess_xyz789"
143
82
  },
144
83
  "infrastructure": {
145
- "sandboxId": "sandbox-123",
146
- "instanceId": "i-abc123",
84
+ "sandboxId": "sbx-123",
85
+ "instanceId": null,
147
86
  "os": "linux",
148
- "amiId": "ami-0abc123",
87
+ "amiId": null,
149
88
  "e2bTemplateId": null,
150
- "imageVersion": "v2.1.0"
89
+ "imageVersion": null
151
90
  },
152
91
  "realtime": {
153
- "channel": "sandbox:sandbox-123",
92
+ "channel": "sandbox:sbx-123",
154
93
  "messageCount": 42
155
94
  },
156
95
  "interactions": {
157
- "total": 15,
158
- "cached": 3,
159
- "byType": {
160
- "find": 8,
161
- "click": 5,
162
- "assert": 2
163
- }
96
+ "total": 3,
97
+ "cached": 1,
98
+ "byType": { "find": 3 }
164
99
  }
165
100
  }
166
101
  ```
167
102
 
168
- ## Using Result Files in CI
103
+ Values that TestDriver doesn't know are `null`.
169
104
 
170
- Result files are useful for extracting test metadata in CI pipelines without parsing log output.
105
+ ## Fields
171
106
 
172
- ### GitHub Actions Example
107
+ ### versions
173
108
 
174
- Use `fromJSON` to parse a result file into a GitHub Actions expression you can reference in subsequent steps:
109
+ | Field | Type | Description |
110
+ | --- | --- | --- |
111
+ | `versions.sdk` | `string \| null` | TestDriver SDK version |
112
+ | `versions.vitest` | `string \| null` | Vitest version |
113
+ | `versions.api` | `string \| null` | TestDriver API version |
114
+ | `versions.runnerBefore` | `string \| null` | Sandbox runner version when the sandbox started |
115
+ | `versions.runnerAfter` | `string \| null` | Runner version after any update during setup |
116
+ | `versions.runnerWasUpdated` | `boolean` | Whether the runner was updated during setup |
175
117
 
176
- ```yaml
177
- - name: Run tests
178
- run: vitest run tests/login.test.mjs
118
+ ### test
179
119
 
180
- - name: Parse result
181
- id: result
182
- run: |
183
- # Read the first JSON result file
184
- FILE=$(find .testdriver/results -name '*.json' | head -n 1)
185
- echo "json=$(cat "$FILE")" >> "$GITHUB_OUTPUT"
186
-
187
- - name: Comment on PR
188
- if: fromJSON(steps.result.outputs.json).test.passed == false
189
- uses: actions/github-script@v7
190
- with:
191
- script: |
192
- const result = ${{ steps.result.outputs.json }};
193
- await github.rest.issues.createComment({
194
- owner: context.repo.owner,
195
- repo: context.repo.repo,
196
- issue_number: context.issue.number,
197
- body: [
198
- `❌ **${result.test.name}** failed`,
199
- ``,
200
- `Error: ${result.test.error}`,
201
- ``,
202
- result.replay.markdown,
203
- ``,
204
- `[View full recording](${result.urls.testRun})`
205
- ].join('\n')
206
- });
207
- ```
120
+ | Field | Type | Description |
121
+ | --- | --- | --- |
122
+ | `test.file` | `string \| null` | Test file path, relative to the directory you ran the tests from |
123
+ | `test.name` | `string \| null` | The test's name |
124
+ | `test.suite` | `string \| null` | The enclosing `describe` names, outermost first, joined with ` > ` |
125
+ | `test.passed` | `boolean` | Whether the test passed |
126
+ | `test.caseId` | `string \| null` | ID of this test's result in TestDriver |
127
+ | `test.runId` | `string \| null` | ID of the whole run in TestDriver |
128
+ | `test.error` | `string \| null` | The error message, if the test failed |
129
+ | `test.errorStack` | `string \| null` | The error's stack trace, if the test failed |
130
+
131
+ ### urls
208
132
 
209
- You can also load all results into a matrix or iterate over them:
133
+ | Field | Type | Description |
134
+ | --- | --- | --- |
135
+ | `urls.api` | `string \| null` | The TestDriver API the test used |
136
+ | `urls.console` | `string \| null` | The TestDriver console |
137
+ | `urls.vnc` | `string \| null` | The sandbox's VNC address |
138
+ | `urls.testRun` | `string \| null` | This test's report in the console |
139
+
140
+ ### replay
141
+
142
+ The test's [Dashcam](/dashcam) recording.
143
+
144
+ | Field | Type | Description |
145
+ | --- | --- | --- |
146
+ | `replay.url` | `string \| null` | The replay link |
147
+ | `replay.gifUrl` | `string \| null` | An animated GIF of the recording |
148
+ | `replay.embedUrl` | `string \| null` | The replay link with `&embed=true`, for embedding |
149
+ | `replay.markdown` | `string \| null` | Markdown for the GIF, linked to the replay, ready to paste into a pull request comment or README |
150
+
151
+ `gifUrl`, `embedUrl`, and `markdown` are filled in only when the replay link includes a `?share=` key.
152
+
153
+ ### date, team, and infrastructure
154
+
155
+ | Field | Type | Description |
156
+ | --- | --- | --- |
157
+ | `date` | `string` | When the test finished, as an ISO 8601 string |
158
+ | `team.id` | `string \| null` | Your team's ID |
159
+ | `team.sessionId` | `string \| null` | The SDK session ID |
160
+ | `infrastructure.sandboxId` | `string \| null` | The sandbox's ID |
161
+ | `infrastructure.instanceId` | `string \| null` | The sandbox's instance ID |
162
+ | `infrastructure.os` | `string \| null` | `"linux"` or `"windows"` |
163
+ | `infrastructure.amiId` | `string \| null` | The machine image the sandbox started from |
164
+ | `infrastructure.e2bTemplateId` | `string \| null` | The sandbox template the sandbox started from |
165
+ | `infrastructure.imageVersion` | `string \| null` | The sandbox image version |
166
+
167
+ ### realtime and interactions
168
+
169
+ | Field | Type | Description |
170
+ | --- | --- | --- |
171
+ | `realtime.channel` | `string \| null` | The realtime channel used to talk to the sandbox |
172
+ | `realtime.messageCount` | `number` | Messages sent on that channel |
173
+ | `interactions.total` | `number` | Number of `find()` and `findAll()` calls |
174
+ | `interactions.cached` | `number` | How many of those were answered from the [cache](/caching) |
175
+ | `interactions.byType` | `object` | Counts per method, such as `{ "find": 3, "findAll": 1 }` |
176
+
177
+ ## Use the results in CI
178
+
179
+ This GitHub Actions step adds a table of results to the job summary:
210
180
 
211
181
  ```yaml
212
182
  - name: Run tests
213
- run: vitest run tests/*.test.mjs
214
-
215
- - name: Collect results
216
- id: results
217
- run: |
218
- # Merge all result files into a JSON array
219
- echo "json=$(find .testdriver/results -name '*.json' -exec cat {} + | jq -s '.')" >> "$GITHUB_OUTPUT"
183
+ run: npx vitest run
220
184
 
221
- - name: Summary
185
+ - name: Summarize results
186
+ if: always()
222
187
  run: |
223
- echo '## Test Results' >> $GITHUB_STEP_SUMMARY
224
- RESULTS='${{ steps.results.outputs.json }}'
225
- echo "$RESULTS" | jq -r '.[] | "| \(.test.name) | \(if .test.passed then "✅" else "❌" end) | \(.urls.testRun) |"' >> $GITHUB_STEP_SUMMARY
188
+ echo '| Test | Result | Report |' >> "$GITHUB_STEP_SUMMARY"
189
+ echo '| --- | --- | --- |' >> "$GITHUB_STEP_SUMMARY"
190
+ find .testdriver/results -name '*.json' -exec cat {} + \
191
+ | jq -rs '.[] | "| \(.test.name) | \(if .test.passed then "Passed" else "Failed" end) | \(.urls.testRun) |"' \
192
+ >> "$GITHUB_STEP_SUMMARY"
226
193
  ```
227
194
 
228
- ### Reading Results Programmatically
229
-
230
- ```javascript
231
- import fs from "fs";
232
- import path from "path";
195
+ To read the results in Node.js:
233
196
 
234
- const resultsDir = ".testdriver/results";
197
+ ```javascript scripts/report.mjs
198
+ import fs from 'node:fs';
199
+ import path from 'node:path';
235
200
 
236
- function readResults(dir) {
237
- const results = [];
238
- for (const testDir of fs.readdirSync(dir, { recursive: true })) {
239
- const fullPath = path.join(dir, testDir);
240
- if (fullPath.endsWith(".json") && fs.statSync(fullPath).isFile()) {
241
- results.push(JSON.parse(fs.readFileSync(fullPath, "utf-8")));
242
- }
243
- }
244
- return results;
245
- }
201
+ const dir = '.testdriver/results';
202
+ const results = fs
203
+ .readdirSync(dir, { recursive: true })
204
+ .filter((file) => file.endsWith('.json'))
205
+ .map((file) => JSON.parse(fs.readFileSync(path.join(dir, file), 'utf8')));
246
206
 
247
- const results = readResults(resultsDir);
248
- const passed = results.filter(r => r.test.passed);
249
- const failed = results.filter(r => !r.test.passed);
207
+ const failed = results.filter((result) => !result.test.passed);
208
+ console.log(`${results.length - failed.length} passed, ${failed.length} failed`);
250
209
 
251
- console.log(`${passed.length} passed, ${failed.length} failed`);
252
- for (const r of failed) {
253
- console.log(` FAIL: ${r.test.name} — ${r.test.error}`);
254
- console.log(` Recording: ${r.urls.testRun}`);
255
- console.log(` Embed: ${r.replay.markdown}`);
210
+ for (const result of failed) {
211
+ console.log(`FAIL ${result.test.name}: ${result.test.error}`);
212
+ console.log(` Report: ${result.urls.testRun}`);
256
213
  }
257
214
  ```
215
+
216
+ ## Related
217
+
218
+ - [Dashcam](/dashcam): how the replay is recorded
219
+ - [Run in CI/CD](/ci-cd): run your tests on every pull request
220
+ - [Run tests](/copilot/running-tests): run tests locally and in parallel