@crvouga/atlas 0.9.0 → 0.10.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/CHANGELOG.md +6 -0
- package/dist/playwright-reporter/src/evidence.d.ts +122 -0
- package/dist/playwright-reporter/src/evidence.js +327 -0
- package/dist/playwright-reporter/src/index.d.ts +114 -0
- package/dist/playwright-reporter/src/index.js +312 -0
- package/dist/reports/src/compose.js +7 -14
- package/dist/reports/src/recorded-specs.d.ts +33 -0
- package/dist/reports/src/recorded-specs.js +42 -0
- package/dist/reports/src/report-index.d.ts +6 -0
- package/dist/reports/src/report-index.js +14 -2
- package/dist/reports/src/test-catalog.d.ts +386 -0
- package/dist/reports/src/test-catalog.js +655 -0
- package/dist/schema/src/api.d.ts +585 -0
- package/dist/schema/src/api.js +105 -0
- package/dist/server/src/app.js +82 -4
- package/dist/server/src/llms.js +14 -0
- package/dist/server/src/openapi.d.ts +1 -1
- package/dist/server/src/openapi.js +60 -3
- package/docs/agents.md +1 -0
- package/docs/integrating.md +1 -0
- package/docs/reference/http-api.md +134 -2
- package/docs/reference/playwright-reporter.md +332 -0
- package/docs/reference/reports.md +632 -0
- package/docs/reference/schema.md +57 -0
- package/docs/rich-evidence.md +198 -0
- package/docs/server.md +41 -0
- package/llms-full.txt +378 -2
- package/llms.txt +2 -0
- package/package.json +6 -1
- package/packages/schema/schemas/report-run.schema.json +251 -0
- package/packages/schema/schemas/report-runs.schema.json +177 -0
- package/packages/schema/schemas/test-catalog.schema.json +1177 -0
- package/packages/schema/schemas/test-history.schema.json +696 -0
- package/packages/server/openapi.json +8676 -5351
- package/packages/visualizer/src/app/AppShell.tsx +7 -3
- package/packages/visualizer/src/app/router.tsx +26 -3
- package/packages/visualizer/src/components/Header.tsx +2 -2
- package/packages/visualizer/src/evidence/evidence-context.tsx +10 -1
- package/packages/visualizer/src/explorer/Explorer.tsx +433 -0
- package/packages/visualizer/src/explorer/ExplorerIndex.tsx +120 -0
- package/packages/visualizer/src/explorer/RunsView.tsx +164 -0
- package/packages/visualizer/src/explorer/TestDetail.tsx +214 -0
- package/packages/visualizer/src/explorer/catalog.tsx +274 -0
- package/packages/visualizer/src/explorer/explorer.module.css +1238 -0
- package/packages/visualizer/src/explorer/groups.test.ts +87 -0
- package/packages/visualizer/src/explorer/groups.ts +126 -0
- package/packages/visualizer/src/explorer/navigate.ts +36 -0
- package/packages/visualizer/src/explorer/parts.tsx +59 -0
- package/packages/visualizer/src/explorer/search.ts +97 -0
- package/packages/visualizer/src/find/Finder.tsx +2 -0
- package/packages/visualizer/src/find/corpus.ts +13 -6
- package/packages/visualizer/src/find/rank.ts +2 -0
- package/packages/visualizer/src/evidence/project-home.tsx +0 -45
package/docs/reference/schema.md
CHANGED
|
@@ -209,6 +209,63 @@ export const PingEventSchema = …
|
|
|
209
209
|
|
|
210
210
|
The data of the `ping` event: sent every `heartbeatSeconds`, so a quiet server is told apart from a dead connection.
|
|
211
211
|
|
|
212
|
+
#### `TestResultEntrySchema`
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
export const TestResultEntrySchema = …
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
One recorded result of a test in the test catalog: when, where, how it went and how long it took, and where it came from.
|
|
219
|
+
|
|
220
|
+
#### `TestSummarySchema`
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
export const TestSummarySchema = …
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
One test of the catalog: what it is, its current result per environment, and how it has gone over its recorded history.
|
|
227
|
+
|
|
228
|
+
#### `TestCatalogSchema`
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
export const TestCatalogSchema = …
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`GET /api/reports/tests`: every test of the report with a summary, insights and facets. The summary and facets cover
|
|
235
|
+
every test; `tests` is the page of those the query matched.
|
|
236
|
+
|
|
237
|
+
#### `TestHistorySchema`
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
export const TestHistorySchema = …
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`GET /api/reports/tests/history`: one test and every result recorded for it (at most 100), newest first.
|
|
244
|
+
|
|
245
|
+
#### `ReportRunSchema`
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
export const ReportRunSchema = …
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
A run: the layers that share a run URL (else a branch and commit), with what they recorded.
|
|
252
|
+
|
|
253
|
+
#### `RunListSchema`
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
export const RunListSchema = …
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`GET /api/reports/runs`: runs, newest first.
|
|
260
|
+
|
|
261
|
+
#### `RunDetailSchema`
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
export const RunDetailSchema = …
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`GET /api/reports/runs/detail`: one run and its last result for every test, environment and producer it recorded.
|
|
268
|
+
|
|
212
269
|
### Command results (`--format json`)
|
|
213
270
|
|
|
214
271
|
Source: `packages/schema/src/cli-results.ts`
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Send rich evidence
|
|
2
|
+
|
|
3
|
+
A check that says only its title and `passed` answers one question: did it pass? A check that also has its duration,
|
|
4
|
+
the device it ran on, its steps, its retries and its video answers the next ones too: how slow is it, where does it
|
|
5
|
+
fail, what happened, is it flaky. This guide covers which fields a producer should send, what the viewer does with
|
|
6
|
+
each, and two ways to send them: the Playwright Test reporter, which sends all of them for you, and `createReporter` /
|
|
7
|
+
`publishChecks` for any other producer.
|
|
8
|
+
|
|
9
|
+
Every field here is optional and none of them changes a result: a check's status, its slot and which result wins are
|
|
10
|
+
decided exactly as before ([the report contract](report-contract.md)). Evidence only adds information.
|
|
11
|
+
[Evidence](extending.md) is the full model, with the rules that keep it compatible.
|
|
12
|
+
|
|
13
|
+
- [What to send, and what it is for](#what-to-send-and-what-it-is-for)
|
|
14
|
+
- [Labels describe, parameters split](#labels-describe-parameters-split)
|
|
15
|
+
- [Playwright Test](#playwright-test)
|
|
16
|
+
- [Any other producer](#any-other-producer)
|
|
17
|
+
|
|
18
|
+
## What to send, and what it is for
|
|
19
|
+
|
|
20
|
+
| Field | Where | What the viewer does with it |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `durationMs` | check, attempt, step | Averages, p95 and the slowest tests, per environment and over time. |
|
|
23
|
+
| `environment` | layer | Which client was checked (`desktop-web`, `mobile-web`, `ios`, `android`…). A check on two environments is two results, side by side. |
|
|
24
|
+
| `labels` (`browser`, `device`, `os`, `viewport`…) | check, layer | Shows each result's browser, device and system, and lets you filter by them. |
|
|
25
|
+
| `attachments` with a `role` | check, attempt, step, layer | Plays `video`, shows a `screenshot`, opens a `trace`, shows logs and offers anything else for download. |
|
|
26
|
+
| `steps` (`parentId`, `offsetMs`, `durationMs`, `status`, `kind`) | check, attempt | Draws the check's timeline: nested steps, when each started, how long it took, which one failed. |
|
|
27
|
+
| `attempts` | check | Every try of a retried check, with its own status, detail, steps and attachments. A check that passed after failing is flaky. |
|
|
28
|
+
| `tags`, `labels` | check, layer | Filters and groups (`smoke`, `flaky`, an owner, a browser). |
|
|
29
|
+
| `annotations`, `links` | check, step, attempt, layer | Notes, warnings and issue links next to the result. |
|
|
30
|
+
| `specPath` | check | The spec a check belongs to (a `.feature`, a test file), relative to the repository. Checks are grouped by it. |
|
|
31
|
+
| `specs[]` (`path`, `domain`, `kind`, `title`) | layer | Names each spec and its group (`domain`), so a server can group checks by spec with a title even when no [spec set](integrating.md#tell-atlas-which-spec-a-check-belongs-to) has been published. |
|
|
32
|
+
| `detail` | check, attempt, step | Why it failed: the error message and stack, as plain text. |
|
|
33
|
+
|
|
34
|
+
Send `sha`, `branch` and `runUrl` on every layer too. They never change a result, but they tie results to a commit
|
|
35
|
+
and to the CI run that produced them.
|
|
36
|
+
|
|
37
|
+
## Labels describe, parameters split
|
|
38
|
+
|
|
39
|
+
A result's **slot** is its producer, check id, part kind, spec, environment and **parameters**. The newest completed
|
|
40
|
+
result of a slot wins. So:
|
|
41
|
+
|
|
42
|
+
- Put what describes a run in `labels`: browser, device name, viewport, operating system, Playwright version, shard.
|
|
43
|
+
Two runs that differ only in labels fill the same slot, and the newer one wins.
|
|
44
|
+
- Put what makes a run a different result in `parameters` (a locale, a tenant, a feature flag): each value is a slot
|
|
45
|
+
of its own, kept side by side.
|
|
46
|
+
- Put the client in `environment`. It is a parameter that every view understands.
|
|
47
|
+
|
|
48
|
+
If you label a check `device: Pixel 7` on one run and `device: iPhone 15` on the next, both in `mobile-web`, the report
|
|
49
|
+
shows the newer one. To see both, give them different environments or a parameter.
|
|
50
|
+
|
|
51
|
+
## Playwright Test
|
|
52
|
+
|
|
53
|
+
`@crvouga/atlas/playwright-reporter` is a Playwright Test reporter. Add it beside your console reporter:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// playwright.config.ts
|
|
57
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
58
|
+
|
|
59
|
+
export default defineConfig({
|
|
60
|
+
retries: process.env.CI ? 2 : 0,
|
|
61
|
+
reporter: [['list'], ['@crvouga/atlas/playwright-reporter', { project: 'checkout', producer: 'e2e-web' }]],
|
|
62
|
+
use: { video: 'retain-on-failure', trace: 'retain-on-failure', screenshot: 'only-on-failure' },
|
|
63
|
+
projects: [
|
|
64
|
+
{ name: 'Desktop Chrome', use: { ...devices['Desktop Chrome'] } },
|
|
65
|
+
{ name: 'Pixel 7', use: { ...devices['Pixel 7'] } }
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Then run your tests as usual, with the destination in the environment:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
ATLAS_SERVER_URL=https://atlas.example.com ATLAS_TOKEN=$ATLAS_PUBLISH_TOKEN ATLAS_PROJECT=checkout npx playwright test
|
|
74
|
+
# … Playwright's own output …
|
|
75
|
+
# Atlas: 3512 checks in 140 layers to https://atlas.example.com
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
What it sends:
|
|
79
|
+
|
|
80
|
+
- Each test as `running` when it starts, then with its result when its last try ends, every few seconds, so the
|
|
81
|
+
report follows the run as it happens.
|
|
82
|
+
- One stream of layers per Playwright project. The environment is `mobile-web` for a project that emulates a mobile
|
|
83
|
+
device (`use.isMobile`), else `desktop-web`. Every check is labelled `browser`, `device` (the project name),
|
|
84
|
+
`viewport`, `os` and `playwright` (its version), and `shard` when the run is sharded.
|
|
85
|
+
- A check id of `<specPath>#<describe titles> > <test title>`, the same in every run.
|
|
86
|
+
- `passed` for a test that got the result it expected, `failed` for a failure, a timeout or an interruption,
|
|
87
|
+
`not-run` for a skipped test or one the run ended before it finished. A test that passed on a retry is `passed`,
|
|
88
|
+
tagged and labelled `flaky`, with one attempt per try.
|
|
89
|
+
- The failure message and stack without terminal colours, the duration, `test.tags` (without `@`) and annotation
|
|
90
|
+
types as tags, annotations, links (annotations whose description is a URL), and Playwright's steps as the timeline
|
|
91
|
+
(`hook`, `fixture`, `action` for `pw:api`, `assertion` for `expect`, `step` for `test.step`).
|
|
92
|
+
- Every attachment, bytes included: `video`, `screenshot` and `trace` take that role, other attachments their own
|
|
93
|
+
name, and standard output and error are `log`s. Attachments of earlier tries go with their attempt.
|
|
94
|
+
- The project's spec files in `specs[]`, so the server can group checks by spec.
|
|
95
|
+
|
|
96
|
+
It never fails the run. A destination that is not set, a server that is down or a file that cannot be read is said
|
|
97
|
+
once, and the summary line says how many checks could not be sent.
|
|
98
|
+
|
|
99
|
+
### Options
|
|
100
|
+
|
|
101
|
+
| Option | Default | |
|
|
102
|
+
| --- | --- | --- |
|
|
103
|
+
| `url` | `ATLAS_SERVER_URL`, else `ATLAS_STORE` | The Atlas server, or any store location (`./atlas-reports`, `s3://bucket/prefix`). |
|
|
104
|
+
| `token` | `ATLAS_PUBLISH_TOKEN`, else `ATLAS_TOKEN` (or `ATLAS_TOKEN_FILE`) | A publish token. A token is never sent over plain `http` beyond this machine. |
|
|
105
|
+
| `project` | `ATLAS_PROJECT` | The project on a shared Atlas server. |
|
|
106
|
+
| `store` | | Publish to this `ObjectStore` instead of a URL (a directory store, an in-memory store in tests). |
|
|
107
|
+
| `producer` | `playwright` | A stable name for this suite. |
|
|
108
|
+
| `kind` | `checks` | The part kind of every layer. |
|
|
109
|
+
| `environment` | `mobile-web` or `desktop-web` | A string, or `(project) => string`. |
|
|
110
|
+
| `parameters` | `{}` | Choices that make a result its own slot. An object, or `(project) => object`. |
|
|
111
|
+
| `labels` | | More labels for every check. An object, or `(project) => object`. |
|
|
112
|
+
| `sha`, `branch`, `runUrl` | `ATLAS_SHA`, `ATLAS_BRANCH`, then the CI's variables (`GITHUB_SHA`, `GITHUB_HEAD_REF` / `GITHUB_REF_NAME`, the GitHub Actions run URL…), then git | Where the run came from. |
|
|
113
|
+
| `specPath` | the `.feature` of a playwright-bdd test, else the test file | `(test) => string`, relative to the repository. |
|
|
114
|
+
| `rootDir` | the git root above Playwright's `rootDir` | Paths are relative to it. |
|
|
115
|
+
| `attachments` | `all` | `all`, `failures` (failed checks and failed tries only) or `none`. |
|
|
116
|
+
| `maxAttachmentBytes` | 50 MiB | A larger file is not uploaded; the check gets an `attachment-skipped` annotation. |
|
|
117
|
+
| `maxSteps` | 500 | Timeline steps kept per try; the rest are counted in a `steps-truncated` annotation. |
|
|
118
|
+
| `specs` | `true` | Record the project's spec files in each layer. |
|
|
119
|
+
| `flushMs`, `batchSize`, `attempts` | 5000, 50, 5 | How often to send, how many checks to send at once, how many tries per layer at the end. |
|
|
120
|
+
| `quiet` | `false` | Print nothing, not even the summary. |
|
|
121
|
+
|
|
122
|
+
Playwright decides what there is to upload: set `video`, `trace` and `screenshot` in `use` (`retain-on-failure` and
|
|
123
|
+
`only-on-failure` keep uploads small), and anything you `testInfo.attach()` is uploaded too. Each file is stored once
|
|
124
|
+
by its content, in chunks, so a server's object size limit does not cap a video.
|
|
125
|
+
|
|
126
|
+
### playwright-bdd
|
|
127
|
+
|
|
128
|
+
Tests generated by [playwright-bdd](https://github.com/vitalets/playwright-bdd) belong to their `.feature` file: a
|
|
129
|
+
test in `.features-gen/<path>.feature.spec.js` gets the `specPath` of `<path>.feature`, found beside `.features-gen`
|
|
130
|
+
(a per-project output folder in between is skipped). The scenario's title is the check's title (an outline's example
|
|
131
|
+
is `<outline>: Example #1`), feature tags are tags, `Given` / `When` / `Then` steps are timeline steps of that kind,
|
|
132
|
+
and the feature's name is the spec's title in `specs[]`. If your features are elsewhere, give `specPath`:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
['@crvouga/atlas/playwright-reporter', { specPath: (test) => test.location.file.replace(/^.*\/generated\//, 'features/').replace(/\.spec\.js$/, '') }]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Any other producer
|
|
139
|
+
|
|
140
|
+
`createReporter` streams checks as they finish, one layer per flush, to a server or any store
|
|
141
|
+
([streaming a run](server.md#streaming-a-run-as-it-happens)); `publishChecks` publishes one finished layer. Both take
|
|
142
|
+
the same check. Attachment bytes go in as `data` (a `Uint8Array`); read files yourself (only the command line reads a
|
|
143
|
+
`path`). Here is a check that carries everything:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { readFile } from 'node:fs/promises';
|
|
147
|
+
import { createReporter } from '@crvouga/atlas/reports/reporter';
|
|
148
|
+
import { httpStore } from '@crvouga/atlas/reports/http-store';
|
|
149
|
+
|
|
150
|
+
const reporter = createReporter(
|
|
151
|
+
{
|
|
152
|
+
producer: 'e2e-web',
|
|
153
|
+
environment: 'mobile-web',
|
|
154
|
+
sha: process.env.GITHUB_SHA ?? null,
|
|
155
|
+
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || null,
|
|
156
|
+
runUrl: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`,
|
|
157
|
+
// Names and groups each spec, so checks are grouped by spec without a published spec set.
|
|
158
|
+
specs: [{ path: 'features/checkout/pay.feature', domain: 'checkout', kind: 'feature', title: 'Paying for an order' }]
|
|
159
|
+
},
|
|
160
|
+
{ store: httpStore({ url: 'https://atlas.example.com', project: 'shop', token: process.env.ATLAS_TOKEN }) }
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
reporter.check({ id: 'features/checkout/pay.feature#Pays by card', title: 'Pays by card', status: 'running', specPath: 'features/checkout/pay.feature' });
|
|
164
|
+
|
|
165
|
+
reporter.check({
|
|
166
|
+
id: 'features/checkout/pay.feature#Pays by card',
|
|
167
|
+
title: 'Pays by card',
|
|
168
|
+
status: 'passed',
|
|
169
|
+
detail: 'Passed on retry 1 (flaky)',
|
|
170
|
+
specPath: 'features/checkout/pay.feature',
|
|
171
|
+
durationMs: 4180,
|
|
172
|
+
tags: ['smoke', 'flaky'],
|
|
173
|
+
labels: { browser: 'chromium', device: 'Pixel 7', os: 'linux', viewport: '412x839' },
|
|
174
|
+
steps: [
|
|
175
|
+
{ id: 's1', name: 'Given a cart with one item', kind: 'given', status: 'passed', offsetMs: 0, durationMs: 900 },
|
|
176
|
+
{ id: 's2', name: 'When I pay by card', kind: 'when', status: 'passed', offsetMs: 900, durationMs: 2600 },
|
|
177
|
+
{ id: 's3', parentId: 's2', name: 'click #pay', kind: 'action', status: 'passed', offsetMs: 1200, durationMs: 80 },
|
|
178
|
+
{ id: 's4', name: 'Then I see the receipt', kind: 'then', status: 'passed', offsetMs: 3500, durationMs: 680 }
|
|
179
|
+
],
|
|
180
|
+
attempts: [
|
|
181
|
+
{ index: 0, status: 'failed', durationMs: 30000, startedAtMs: Date.now() - 40000, detail: 'Timeout 30000ms exceeded',
|
|
182
|
+
attachments: [{ name: 'retry-0.png', role: 'screenshot', contentType: 'image/png', data: await readFile('test-results/retry-0.png') }] },
|
|
183
|
+
{ index: 1, status: 'passed', durationMs: 4180, startedAtMs: Date.now() - 5000 }
|
|
184
|
+
],
|
|
185
|
+
attachments: [
|
|
186
|
+
{ name: 'video.webm', role: 'video', contentType: 'video/webm', data: await readFile('test-results/video.webm') },
|
|
187
|
+
{ name: 'trace.zip', role: 'trace', contentType: 'application/zip', data: await readFile('test-results/trace.zip') }
|
|
188
|
+
]
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const { checks, layers, lost } = await reporter.close(); // never throws; `lost` counts what never arrived
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
With `publishChecks`, pass the same identity and checks with `recordedAtMs`, once the run is over. From a checks file
|
|
195
|
+
or the command line, an attachment may name a `path` instead; `atlas report publish` reads it
|
|
196
|
+
([attach evidence](extending.md#attach-evidence)). A CTRF report already carries most of this, and
|
|
197
|
+
`atlas report publish --ctrf` keeps it ([native runner reporters](runners.md) cover CodeceptJS, Mocha, Jest and Node's
|
|
198
|
+
test runner).
|
package/docs/server.md
CHANGED
|
@@ -243,6 +243,39 @@ report the server would have sent whole (`applyEffectiveDelta`, tested against e
|
|
|
243
243
|
runs); a version the server does not remember, or an older server, answers with the whole report, which a client
|
|
244
244
|
takes as it always did. A result streamed into a 100 000-check report costs a client a few kilobytes.
|
|
245
245
|
|
|
246
|
+
## Reading the report as an agent
|
|
247
|
+
|
|
248
|
+
The effective report says what each check's result is now. To explore a project, or to answer "what is tested,
|
|
249
|
+
where, how long does it take, what is flaky", read the tests instead. Every endpoint here answers JSON, or Markdown
|
|
250
|
+
with `format=markdown` (or `Accept: text/markdown`), and takes the project prefix like every other
|
|
251
|
+
(`/api/projects/<slug>/reports/tests`).
|
|
252
|
+
|
|
253
|
+
| Ask | Endpoint |
|
|
254
|
+
| --- | --- |
|
|
255
|
+
| Every test, a summary (by status, environment, producer, domain), insights (failing, flaky, slowest) and facets | `GET /api/reports/tests` |
|
|
256
|
+
| Only some: `q` (all words), `status` (or `flaky`), `environment`, `producer`, `domain`, `spec`, `tag`, `run`; `sort`, `offset`, `limit` | `GET /api/reports/tests?status=failed&environment=ios` |
|
|
257
|
+
| One test: every recorded result (status, duration, environment, branch, commit, CI run), newest first | `GET /api/reports/tests/history?key=<key>` |
|
|
258
|
+
| The runs that recorded the report (by CI run URL, else branch and commit) | `GET /api/reports/runs` |
|
|
259
|
+
| Every test one run recorded | `GET /api/reports/runs/detail?key=<run key>` |
|
|
260
|
+
|
|
261
|
+
```sh
|
|
262
|
+
curl "$ATLAS_SERVER_URL/api/projects/$ATLAS_PROJECT/reports/tests?format=markdown&limit=50"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
- A **test** is a check identity, its spec path and id, across producers and environments. `outcomes` holds its
|
|
266
|
+
current result on each environment (the report's winners, so a test's status here is always the gate's);
|
|
267
|
+
`stats` describes its recorded history: pass rate, flips, whether it is flaky and why (it passed and failed on the
|
|
268
|
+
same commit, passed only after a retry, or its producer said so), durations (avg, p50, p95, min, max, last), runs
|
|
269
|
+
and branches.
|
|
270
|
+
- The server keeps the newest 100 results of every test (progress reported as `running` is not history) and every run's last result per test, in memory, as layers
|
|
271
|
+
arrive; it is rebuilt from the layers on restart. History never changes a result.
|
|
272
|
+
- Without a published spec set, tests are grouped under the specs their layers recorded (`specs[]`: path, domain,
|
|
273
|
+
title), and the gate and the outline do the same, so a project needs no spec set to be browsable. A path no layer
|
|
274
|
+
described is titled from its file name and grouped by its folder under `specs/`.
|
|
275
|
+
- Statistics are only as rich as what producers send: durations need `durationMs`, devices need an environment and
|
|
276
|
+
labels (`browser`, `device`, `os`), videos and screenshots need attachments. See
|
|
277
|
+
[Send rich evidence](rich-evidence.md).
|
|
278
|
+
|
|
246
279
|
## API reference
|
|
247
280
|
|
|
248
281
|
<!-- generated:server-operations -->
|
|
@@ -283,6 +316,14 @@ takes as it always did. A result streamed into a 100 000-check report costs a cl
|
|
|
283
316
|
| `PUT /api/projects/{project}/store/{key}` | publish | Upload an object. |
|
|
284
317
|
| `DELETE /api/store/{key}` | publish | Remove a scratch object. |
|
|
285
318
|
| `DELETE /api/projects/{project}/store/{key}` | publish | Remove a scratch object. |
|
|
319
|
+
| `GET /api/reports/tests` | read | Every test, with insights, facets and history statistics. |
|
|
320
|
+
| `GET /api/projects/{project}/reports/tests` | read | Every test, with insights, facets and history statistics. |
|
|
321
|
+
| `GET /api/reports/tests/history` | read | One test and every result recorded for it. |
|
|
322
|
+
| `GET /api/projects/{project}/reports/tests/history` | read | One test and every result recorded for it. |
|
|
323
|
+
| `GET /api/reports/runs` | read | The runs that recorded the report. |
|
|
324
|
+
| `GET /api/projects/{project}/reports/runs` | read | The runs that recorded the report. |
|
|
325
|
+
| `GET /api/reports/runs/detail` | read | Every test one run recorded. |
|
|
326
|
+
| `GET /api/projects/{project}/reports/runs/detail` | read | Every test one run recorded. |
|
|
286
327
|
| `GET /api/reports/outline` | read | The specs a report is laid over. |
|
|
287
328
|
| `GET /api/projects/{project}/reports/outline` | read | The specs a report is laid over. |
|
|
288
329
|
| `GET /api/reports/outline/spec` | read | The text of one spec. |
|