@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,257 +1,220 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testdriver:test-results-json
|
|
3
|
-
description:
|
|
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
|
-
|
|
7
|
+
TestDriver writes a JSON file for each test after it finishes.
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
33
|
+
## Where the files go
|
|
80
34
|
|
|
81
|
-
```
|
|
82
|
-
|
|
35
|
+
```text
|
|
36
|
+
.testdriver/results/<test file>/<test id>.json
|
|
83
37
|
```
|
|
84
38
|
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
```json
|
|
46
|
+
```json .testdriver/results/tests/login.test.mjs/1223128da3_0_0.json
|
|
127
47
|
{
|
|
128
|
-
"
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
"
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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": "[](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": "
|
|
146
|
-
"instanceId":
|
|
84
|
+
"sandboxId": "sbx-123",
|
|
85
|
+
"instanceId": null,
|
|
147
86
|
"os": "linux",
|
|
148
|
-
"amiId":
|
|
87
|
+
"amiId": null,
|
|
149
88
|
"e2bTemplateId": null,
|
|
150
|
-
"imageVersion":
|
|
89
|
+
"imageVersion": null
|
|
151
90
|
},
|
|
152
91
|
"realtime": {
|
|
153
|
-
"channel": "sandbox:
|
|
92
|
+
"channel": "sandbox:sbx-123",
|
|
154
93
|
"messageCount": 42
|
|
155
94
|
},
|
|
156
95
|
"interactions": {
|
|
157
|
-
"total":
|
|
158
|
-
"cached":
|
|
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
|
-
|
|
103
|
+
Values that TestDriver doesn't know are `null`.
|
|
169
104
|
|
|
170
|
-
|
|
105
|
+
## Fields
|
|
171
106
|
|
|
172
|
-
###
|
|
107
|
+
### versions
|
|
173
108
|
|
|
174
|
-
|
|
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
|
-
|
|
177
|
-
- name: Run tests
|
|
178
|
-
run: vitest run tests/login.test.mjs
|
|
118
|
+
### test
|
|
179
119
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
185
|
+
- name: Summarize results
|
|
186
|
+
if: always()
|
|
222
187
|
run: |
|
|
223
|
-
echo '
|
|
224
|
-
|
|
225
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
```javascript
|
|
231
|
-
import fs from "fs";
|
|
232
|
-
import path from "path";
|
|
195
|
+
To read the results in Node.js:
|
|
233
196
|
|
|
234
|
-
|
|
197
|
+
```javascript scripts/report.mjs
|
|
198
|
+
import fs from 'node:fs';
|
|
199
|
+
import path from 'node:path';
|
|
235
200
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
|
248
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
console.log(`
|
|
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
|