@crvouga/atlas 0.8.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 +12 -0
- package/dist/core/src/lint.js +6 -2
- package/dist/core/src/spec/types.d.ts +4 -1
- 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/schema/src/spec.d.ts +2 -1
- package/dist/schema/src/spec.js +5 -2
- 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/core.md +7 -2
- 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 +58 -1
- package/docs/rich-evidence.md +198 -0
- package/docs/server.md +41 -0
- package/docs/statecharts.md +2 -1
- package/llms-full.txt +380 -3
- 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/state-node.schema.json +7 -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/llms-full.txt
CHANGED
|
@@ -120,6 +120,7 @@ The complete public export map is generated from the package manifest (wildcards
|
|
|
120
120
|
@crvouga/atlas/codecept
|
|
121
121
|
@crvouga/atlas/jest
|
|
122
122
|
@crvouga/atlas/node-test
|
|
123
|
+
@crvouga/atlas/playwright-reporter
|
|
123
124
|
```
|
|
124
125
|
<!-- /generated:public-exports -->
|
|
125
126
|
|
|
@@ -605,6 +606,7 @@ bunx atlas report publish --producer e2e --junit out.xml --attach ci.log --attac
|
|
|
605
606
|
Files are stored in the layer by content, shown by what they are (pictures, videos, page snapshots, text) and
|
|
606
607
|
offered for download otherwise. [Evidence](extending.md) is the full model, and why a new kind of evidence never
|
|
607
608
|
breaks anything.
|
|
609
|
+
[Send rich evidence](rich-evidence.md) lists what to send and what the viewer does with it, and covers the Playwright Test reporter.
|
|
608
610
|
|
|
609
611
|
### Statecharts
|
|
610
612
|
|
|
@@ -949,6 +951,207 @@ Run `atlas server` once for the projects the node hosts; point local and CI publ
|
|
|
949
951
|
Native reporters send a heartbeat every 5 seconds. The server interrupts invocations after 30 seconds of silence, or after the configurable progress-stall timeout. It preserves finished results and never marks missing tests as passed. See [live test runs](server.md#live-test-runs-and-heartbeats).
|
|
950
952
|
</doc>
|
|
951
953
|
|
|
954
|
+
<doc path="docs/rich-evidence.md">
|
|
955
|
+
# Send rich evidence
|
|
956
|
+
|
|
957
|
+
A check that says only its title and `passed` answers one question: did it pass? A check that also has its duration,
|
|
958
|
+
the device it ran on, its steps, its retries and its video answers the next ones too: how slow is it, where does it
|
|
959
|
+
fail, what happened, is it flaky. This guide covers which fields a producer should send, what the viewer does with
|
|
960
|
+
each, and two ways to send them: the Playwright Test reporter, which sends all of them for you, and `createReporter` /
|
|
961
|
+
`publishChecks` for any other producer.
|
|
962
|
+
|
|
963
|
+
Every field here is optional and none of them changes a result: a check's status, its slot and which result wins are
|
|
964
|
+
decided exactly as before ([the report contract](report-contract.md)). Evidence only adds information.
|
|
965
|
+
[Evidence](extending.md) is the full model, with the rules that keep it compatible.
|
|
966
|
+
|
|
967
|
+
- [What to send, and what it is for](#what-to-send-and-what-it-is-for)
|
|
968
|
+
- [Labels describe, parameters split](#labels-describe-parameters-split)
|
|
969
|
+
- [Playwright Test](#playwright-test)
|
|
970
|
+
- [Any other producer](#any-other-producer)
|
|
971
|
+
|
|
972
|
+
## What to send, and what it is for
|
|
973
|
+
|
|
974
|
+
| Field | Where | What the viewer does with it |
|
|
975
|
+
| --- | --- | --- |
|
|
976
|
+
| `durationMs` | check, attempt, step | Averages, p95 and the slowest tests, per environment and over time. |
|
|
977
|
+
| `environment` | layer | Which client was checked (`desktop-web`, `mobile-web`, `ios`, `android`…). A check on two environments is two results, side by side. |
|
|
978
|
+
| `labels` (`browser`, `device`, `os`, `viewport`…) | check, layer | Shows each result's browser, device and system, and lets you filter by them. |
|
|
979
|
+
| `attachments` with a `role` | check, attempt, step, layer | Plays `video`, shows a `screenshot`, opens a `trace`, shows logs and offers anything else for download. |
|
|
980
|
+
| `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. |
|
|
981
|
+
| `attempts` | check | Every try of a retried check, with its own status, detail, steps and attachments. A check that passed after failing is flaky. |
|
|
982
|
+
| `tags`, `labels` | check, layer | Filters and groups (`smoke`, `flaky`, an owner, a browser). |
|
|
983
|
+
| `annotations`, `links` | check, step, attempt, layer | Notes, warnings and issue links next to the result. |
|
|
984
|
+
| `specPath` | check | The spec a check belongs to (a `.feature`, a test file), relative to the repository. Checks are grouped by it. |
|
|
985
|
+
| `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. |
|
|
986
|
+
| `detail` | check, attempt, step | Why it failed: the error message and stack, as plain text. |
|
|
987
|
+
|
|
988
|
+
Send `sha`, `branch` and `runUrl` on every layer too. They never change a result, but they tie results to a commit
|
|
989
|
+
and to the CI run that produced them.
|
|
990
|
+
|
|
991
|
+
## Labels describe, parameters split
|
|
992
|
+
|
|
993
|
+
A result's **slot** is its producer, check id, part kind, spec, environment and **parameters**. The newest completed
|
|
994
|
+
result of a slot wins. So:
|
|
995
|
+
|
|
996
|
+
- Put what describes a run in `labels`: browser, device name, viewport, operating system, Playwright version, shard.
|
|
997
|
+
Two runs that differ only in labels fill the same slot, and the newer one wins.
|
|
998
|
+
- Put what makes a run a different result in `parameters` (a locale, a tenant, a feature flag): each value is a slot
|
|
999
|
+
of its own, kept side by side.
|
|
1000
|
+
- Put the client in `environment`. It is a parameter that every view understands.
|
|
1001
|
+
|
|
1002
|
+
If you label a check `device: Pixel 7` on one run and `device: iPhone 15` on the next, both in `mobile-web`, the report
|
|
1003
|
+
shows the newer one. To see both, give them different environments or a parameter.
|
|
1004
|
+
|
|
1005
|
+
## Playwright Test
|
|
1006
|
+
|
|
1007
|
+
`@crvouga/atlas/playwright-reporter` is a Playwright Test reporter. Add it beside your console reporter:
|
|
1008
|
+
|
|
1009
|
+
```ts
|
|
1010
|
+
// playwright.config.ts
|
|
1011
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
1012
|
+
|
|
1013
|
+
export default defineConfig({
|
|
1014
|
+
retries: process.env.CI ? 2 : 0,
|
|
1015
|
+
reporter: [['list'], ['@crvouga/atlas/playwright-reporter', { project: 'checkout', producer: 'e2e-web' }]],
|
|
1016
|
+
use: { video: 'retain-on-failure', trace: 'retain-on-failure', screenshot: 'only-on-failure' },
|
|
1017
|
+
projects: [
|
|
1018
|
+
{ name: 'Desktop Chrome', use: { ...devices['Desktop Chrome'] } },
|
|
1019
|
+
{ name: 'Pixel 7', use: { ...devices['Pixel 7'] } }
|
|
1020
|
+
]
|
|
1021
|
+
});
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
Then run your tests as usual, with the destination in the environment:
|
|
1025
|
+
|
|
1026
|
+
```sh
|
|
1027
|
+
ATLAS_SERVER_URL=https://atlas.example.com ATLAS_TOKEN=$ATLAS_PUBLISH_TOKEN ATLAS_PROJECT=checkout npx playwright test
|
|
1028
|
+
# … Playwright's own output …
|
|
1029
|
+
# Atlas: 3512 checks in 140 layers to https://atlas.example.com
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
What it sends:
|
|
1033
|
+
|
|
1034
|
+
- Each test as `running` when it starts, then with its result when its last try ends, every few seconds, so the
|
|
1035
|
+
report follows the run as it happens.
|
|
1036
|
+
- One stream of layers per Playwright project. The environment is `mobile-web` for a project that emulates a mobile
|
|
1037
|
+
device (`use.isMobile`), else `desktop-web`. Every check is labelled `browser`, `device` (the project name),
|
|
1038
|
+
`viewport`, `os` and `playwright` (its version), and `shard` when the run is sharded.
|
|
1039
|
+
- A check id of `<specPath>#<describe titles> > <test title>`, the same in every run.
|
|
1040
|
+
- `passed` for a test that got the result it expected, `failed` for a failure, a timeout or an interruption,
|
|
1041
|
+
`not-run` for a skipped test or one the run ended before it finished. A test that passed on a retry is `passed`,
|
|
1042
|
+
tagged and labelled `flaky`, with one attempt per try.
|
|
1043
|
+
- The failure message and stack without terminal colours, the duration, `test.tags` (without `@`) and annotation
|
|
1044
|
+
types as tags, annotations, links (annotations whose description is a URL), and Playwright's steps as the timeline
|
|
1045
|
+
(`hook`, `fixture`, `action` for `pw:api`, `assertion` for `expect`, `step` for `test.step`).
|
|
1046
|
+
- Every attachment, bytes included: `video`, `screenshot` and `trace` take that role, other attachments their own
|
|
1047
|
+
name, and standard output and error are `log`s. Attachments of earlier tries go with their attempt.
|
|
1048
|
+
- The project's spec files in `specs[]`, so the server can group checks by spec.
|
|
1049
|
+
|
|
1050
|
+
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
|
|
1051
|
+
once, and the summary line says how many checks could not be sent.
|
|
1052
|
+
|
|
1053
|
+
### Options
|
|
1054
|
+
|
|
1055
|
+
| Option | Default | |
|
|
1056
|
+
| --- | --- | --- |
|
|
1057
|
+
| `url` | `ATLAS_SERVER_URL`, else `ATLAS_STORE` | The Atlas server, or any store location (`./atlas-reports`, `s3://bucket/prefix`). |
|
|
1058
|
+
| `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. |
|
|
1059
|
+
| `project` | `ATLAS_PROJECT` | The project on a shared Atlas server. |
|
|
1060
|
+
| `store` | | Publish to this `ObjectStore` instead of a URL (a directory store, an in-memory store in tests). |
|
|
1061
|
+
| `producer` | `playwright` | A stable name for this suite. |
|
|
1062
|
+
| `kind` | `checks` | The part kind of every layer. |
|
|
1063
|
+
| `environment` | `mobile-web` or `desktop-web` | A string, or `(project) => string`. |
|
|
1064
|
+
| `parameters` | `{}` | Choices that make a result its own slot. An object, or `(project) => object`. |
|
|
1065
|
+
| `labels` | | More labels for every check. An object, or `(project) => object`. |
|
|
1066
|
+
| `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. |
|
|
1067
|
+
| `specPath` | the `.feature` of a playwright-bdd test, else the test file | `(test) => string`, relative to the repository. |
|
|
1068
|
+
| `rootDir` | the git root above Playwright's `rootDir` | Paths are relative to it. |
|
|
1069
|
+
| `attachments` | `all` | `all`, `failures` (failed checks and failed tries only) or `none`. |
|
|
1070
|
+
| `maxAttachmentBytes` | 50 MiB | A larger file is not uploaded; the check gets an `attachment-skipped` annotation. |
|
|
1071
|
+
| `maxSteps` | 500 | Timeline steps kept per try; the rest are counted in a `steps-truncated` annotation. |
|
|
1072
|
+
| `specs` | `true` | Record the project's spec files in each layer. |
|
|
1073
|
+
| `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. |
|
|
1074
|
+
| `quiet` | `false` | Print nothing, not even the summary. |
|
|
1075
|
+
|
|
1076
|
+
Playwright decides what there is to upload: set `video`, `trace` and `screenshot` in `use` (`retain-on-failure` and
|
|
1077
|
+
`only-on-failure` keep uploads small), and anything you `testInfo.attach()` is uploaded too. Each file is stored once
|
|
1078
|
+
by its content, in chunks, so a server's object size limit does not cap a video.
|
|
1079
|
+
|
|
1080
|
+
### playwright-bdd
|
|
1081
|
+
|
|
1082
|
+
Tests generated by [playwright-bdd](https://github.com/vitalets/playwright-bdd) belong to their `.feature` file: a
|
|
1083
|
+
test in `.features-gen/<path>.feature.spec.js` gets the `specPath` of `<path>.feature`, found beside `.features-gen`
|
|
1084
|
+
(a per-project output folder in between is skipped). The scenario's title is the check's title (an outline's example
|
|
1085
|
+
is `<outline>: Example #1`), feature tags are tags, `Given` / `When` / `Then` steps are timeline steps of that kind,
|
|
1086
|
+
and the feature's name is the spec's title in `specs[]`. If your features are elsewhere, give `specPath`:
|
|
1087
|
+
|
|
1088
|
+
```ts
|
|
1089
|
+
['@crvouga/atlas/playwright-reporter', { specPath: (test) => test.location.file.replace(/^.*\/generated\//, 'features/').replace(/\.spec\.js$/, '') }]
|
|
1090
|
+
```
|
|
1091
|
+
|
|
1092
|
+
## Any other producer
|
|
1093
|
+
|
|
1094
|
+
`createReporter` streams checks as they finish, one layer per flush, to a server or any store
|
|
1095
|
+
([streaming a run](server.md#streaming-a-run-as-it-happens)); `publishChecks` publishes one finished layer. Both take
|
|
1096
|
+
the same check. Attachment bytes go in as `data` (a `Uint8Array`); read files yourself (only the command line reads a
|
|
1097
|
+
`path`). Here is a check that carries everything:
|
|
1098
|
+
|
|
1099
|
+
```ts
|
|
1100
|
+
import { readFile } from 'node:fs/promises';
|
|
1101
|
+
import { createReporter } from '@crvouga/atlas/reports/reporter';
|
|
1102
|
+
import { httpStore } from '@crvouga/atlas/reports/http-store';
|
|
1103
|
+
|
|
1104
|
+
const reporter = createReporter(
|
|
1105
|
+
{
|
|
1106
|
+
producer: 'e2e-web',
|
|
1107
|
+
environment: 'mobile-web',
|
|
1108
|
+
sha: process.env.GITHUB_SHA ?? null,
|
|
1109
|
+
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || null,
|
|
1110
|
+
runUrl: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`,
|
|
1111
|
+
// Names and groups each spec, so checks are grouped by spec without a published spec set.
|
|
1112
|
+
specs: [{ path: 'features/checkout/pay.feature', domain: 'checkout', kind: 'feature', title: 'Paying for an order' }]
|
|
1113
|
+
},
|
|
1114
|
+
{ store: httpStore({ url: 'https://atlas.example.com', project: 'shop', token: process.env.ATLAS_TOKEN }) }
|
|
1115
|
+
);
|
|
1116
|
+
|
|
1117
|
+
reporter.check({ id: 'features/checkout/pay.feature#Pays by card', title: 'Pays by card', status: 'running', specPath: 'features/checkout/pay.feature' });
|
|
1118
|
+
|
|
1119
|
+
reporter.check({
|
|
1120
|
+
id: 'features/checkout/pay.feature#Pays by card',
|
|
1121
|
+
title: 'Pays by card',
|
|
1122
|
+
status: 'passed',
|
|
1123
|
+
detail: 'Passed on retry 1 (flaky)',
|
|
1124
|
+
specPath: 'features/checkout/pay.feature',
|
|
1125
|
+
durationMs: 4180,
|
|
1126
|
+
tags: ['smoke', 'flaky'],
|
|
1127
|
+
labels: { browser: 'chromium', device: 'Pixel 7', os: 'linux', viewport: '412x839' },
|
|
1128
|
+
steps: [
|
|
1129
|
+
{ id: 's1', name: 'Given a cart with one item', kind: 'given', status: 'passed', offsetMs: 0, durationMs: 900 },
|
|
1130
|
+
{ id: 's2', name: 'When I pay by card', kind: 'when', status: 'passed', offsetMs: 900, durationMs: 2600 },
|
|
1131
|
+
{ id: 's3', parentId: 's2', name: 'click #pay', kind: 'action', status: 'passed', offsetMs: 1200, durationMs: 80 },
|
|
1132
|
+
{ id: 's4', name: 'Then I see the receipt', kind: 'then', status: 'passed', offsetMs: 3500, durationMs: 680 }
|
|
1133
|
+
],
|
|
1134
|
+
attempts: [
|
|
1135
|
+
{ index: 0, status: 'failed', durationMs: 30000, startedAtMs: Date.now() - 40000, detail: 'Timeout 30000ms exceeded',
|
|
1136
|
+
attachments: [{ name: 'retry-0.png', role: 'screenshot', contentType: 'image/png', data: await readFile('test-results/retry-0.png') }] },
|
|
1137
|
+
{ index: 1, status: 'passed', durationMs: 4180, startedAtMs: Date.now() - 5000 }
|
|
1138
|
+
],
|
|
1139
|
+
attachments: [
|
|
1140
|
+
{ name: 'video.webm', role: 'video', contentType: 'video/webm', data: await readFile('test-results/video.webm') },
|
|
1141
|
+
{ name: 'trace.zip', role: 'trace', contentType: 'application/zip', data: await readFile('test-results/trace.zip') }
|
|
1142
|
+
]
|
|
1143
|
+
});
|
|
1144
|
+
|
|
1145
|
+
const { checks, layers, lost } = await reporter.close(); // never throws; `lost` counts what never arrived
|
|
1146
|
+
```
|
|
1147
|
+
|
|
1148
|
+
With `publishChecks`, pass the same identity and checks with `recordedAtMs`, once the run is over. From a checks file
|
|
1149
|
+
or the command line, an attachment may name a `path` instead; `atlas report publish` reads it
|
|
1150
|
+
([attach evidence](extending.md#attach-evidence)). A CTRF report already carries most of this, and
|
|
1151
|
+
`atlas report publish --ctrf` keeps it ([native runner reporters](runners.md) cover CodeceptJS, Mocha, Jest and Node's
|
|
1152
|
+
test runner).
|
|
1153
|
+
</doc>
|
|
1154
|
+
|
|
952
1155
|
<doc path="docs/server.md">
|
|
953
1156
|
# The Atlas server
|
|
954
1157
|
|
|
@@ -1195,6 +1398,39 @@ report the server would have sent whole (`applyEffectiveDelta`, tested against e
|
|
|
1195
1398
|
runs); a version the server does not remember, or an older server, answers with the whole report, which a client
|
|
1196
1399
|
takes as it always did. A result streamed into a 100 000-check report costs a client a few kilobytes.
|
|
1197
1400
|
|
|
1401
|
+
## Reading the report as an agent
|
|
1402
|
+
|
|
1403
|
+
The effective report says what each check's result is now. To explore a project, or to answer "what is tested,
|
|
1404
|
+
where, how long does it take, what is flaky", read the tests instead. Every endpoint here answers JSON, or Markdown
|
|
1405
|
+
with `format=markdown` (or `Accept: text/markdown`), and takes the project prefix like every other
|
|
1406
|
+
(`/api/projects/<slug>/reports/tests`).
|
|
1407
|
+
|
|
1408
|
+
| Ask | Endpoint |
|
|
1409
|
+
| --- | --- |
|
|
1410
|
+
| Every test, a summary (by status, environment, producer, domain), insights (failing, flaky, slowest) and facets | `GET /api/reports/tests` |
|
|
1411
|
+
| 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` |
|
|
1412
|
+
| One test: every recorded result (status, duration, environment, branch, commit, CI run), newest first | `GET /api/reports/tests/history?key=<key>` |
|
|
1413
|
+
| The runs that recorded the report (by CI run URL, else branch and commit) | `GET /api/reports/runs` |
|
|
1414
|
+
| Every test one run recorded | `GET /api/reports/runs/detail?key=<run key>` |
|
|
1415
|
+
|
|
1416
|
+
```sh
|
|
1417
|
+
curl "$ATLAS_SERVER_URL/api/projects/$ATLAS_PROJECT/reports/tests?format=markdown&limit=50"
|
|
1418
|
+
```
|
|
1419
|
+
|
|
1420
|
+
- A **test** is a check identity, its spec path and id, across producers and environments. `outcomes` holds its
|
|
1421
|
+
current result on each environment (the report's winners, so a test's status here is always the gate's);
|
|
1422
|
+
`stats` describes its recorded history: pass rate, flips, whether it is flaky and why (it passed and failed on the
|
|
1423
|
+
same commit, passed only after a retry, or its producer said so), durations (avg, p50, p95, min, max, last), runs
|
|
1424
|
+
and branches.
|
|
1425
|
+
- 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
|
|
1426
|
+
arrive; it is rebuilt from the layers on restart. History never changes a result.
|
|
1427
|
+
- Without a published spec set, tests are grouped under the specs their layers recorded (`specs[]`: path, domain,
|
|
1428
|
+
title), and the gate and the outline do the same, so a project needs no spec set to be browsable. A path no layer
|
|
1429
|
+
described is titled from its file name and grouped by its folder under `specs/`.
|
|
1430
|
+
- Statistics are only as rich as what producers send: durations need `durationMs`, devices need an environment and
|
|
1431
|
+
labels (`browser`, `device`, `os`), videos and screenshots need attachments. See
|
|
1432
|
+
[Send rich evidence](rich-evidence.md).
|
|
1433
|
+
|
|
1198
1434
|
## API reference
|
|
1199
1435
|
|
|
1200
1436
|
<!-- generated:server-operations -->
|
|
@@ -1235,6 +1471,14 @@ takes as it always did. A result streamed into a 100 000-check report costs a cl
|
|
|
1235
1471
|
| `PUT /api/projects/{project}/store/{key}` | publish | Upload an object. |
|
|
1236
1472
|
| `DELETE /api/store/{key}` | publish | Remove a scratch object. |
|
|
1237
1473
|
| `DELETE /api/projects/{project}/store/{key}` | publish | Remove a scratch object. |
|
|
1474
|
+
| `GET /api/reports/tests` | read | Every test, with insights, facets and history statistics. |
|
|
1475
|
+
| `GET /api/projects/{project}/reports/tests` | read | Every test, with insights, facets and history statistics. |
|
|
1476
|
+
| `GET /api/reports/tests/history` | read | One test and every result recorded for it. |
|
|
1477
|
+
| `GET /api/projects/{project}/reports/tests/history` | read | One test and every result recorded for it. |
|
|
1478
|
+
| `GET /api/reports/runs` | read | The runs that recorded the report. |
|
|
1479
|
+
| `GET /api/projects/{project}/reports/runs` | read | The runs that recorded the report. |
|
|
1480
|
+
| `GET /api/reports/runs/detail` | read | Every test one run recorded. |
|
|
1481
|
+
| `GET /api/projects/{project}/reports/runs/detail` | read | Every test one run recorded. |
|
|
1238
1482
|
| `GET /api/reports/outline` | read | The specs a report is laid over. |
|
|
1239
1483
|
| `GET /api/projects/{project}/reports/outline` | read | The specs a report is laid over. |
|
|
1240
1484
|
| `GET /api/reports/outline/spec` | read | The text of one spec. |
|
|
@@ -2727,7 +2971,8 @@ Atlas walks charts without running any code, so it executes only the parts of a
|
|
|
2727
2971
|
are pure structure:
|
|
2728
2972
|
|
|
2729
2973
|
- states, nesting (`initial`), `parallel` regions and `final` states;
|
|
2730
|
-
- event transitions, written as a target (`Opens: Open` or `{ target: '#Open' }`)
|
|
2974
|
+
- event transitions, written as a target (`Opens: Open` or `{ target: '#Open' }`), with
|
|
2975
|
+
optional declarative metadata (`{ target: '#Open', meta: { source: ['specs/door.feature'] } }`);
|
|
2731
2976
|
- `invoke` that names another chart (`src`, `id`, `onDone`), composed statically;
|
|
2732
2977
|
- `meta`.
|
|
2733
2978
|
|
|
@@ -4200,11 +4445,143 @@ Scoped to one project. The same project may be selected on the unprefixed API us
|
|
|
4200
4445
|
|
|
4201
4446
|
Responses: `204` Removed (or it was not there).; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `403` Not a scratch object, or the token may not.
|
|
4202
4447
|
|
|
4448
|
+
### Every test, with insights, facets and history statistics
|
|
4449
|
+
|
|
4450
|
+
`GET /api/reports/tests` · role: read
|
|
4451
|
+
|
|
4452
|
+
The report as a list of tests, for exploring it or for an agent to read in one request. A test is a check identity (its spec path and id) across producers and environments; `outcomes` holds its current result on each environment, and `stats` how it went over its recorded history (pass rate, flips, flaky, durations avg/p50/p95, runs, branches).
|
|
4453
|
+
|
|
4454
|
+
`summary` and `facets` cover every test (counts by status, by environment, by producer and by domain, the slowest, flakiest and failing tests); `tests` is the page the query matched. Without a published spec set, specs come from the `specs[]` the layers recorded.
|
|
4455
|
+
|
|
4456
|
+
Send `format=markdown` (or `Accept: text/markdown`) for the same as a Markdown report. The current status of a test is always the report's winner; history never changes it.
|
|
4457
|
+
|
|
4458
|
+
- `q` (query): Words that must all appear in the title, id, spec, domain, tags, labels, environments or producers. Case does not matter.
|
|
4459
|
+
- `status` (query): Current status, or `flaky`. Repeatable or comma-separated.
|
|
4460
|
+
- `environment` (query): Only tests with a result on this environment. Repeatable or comma-separated.
|
|
4461
|
+
- `producer` (query): Only tests from this producer. Repeatable or comma-separated.
|
|
4462
|
+
- `domain` (query): Only tests whose spec is in this domain (`(no spec)` for none). Repeatable or comma-separated.
|
|
4463
|
+
- `spec` (query): Only tests of this spec path. Repeatable or comma-separated.
|
|
4464
|
+
- `tag` (query): Only tests with this tag. Repeatable or comma-separated.
|
|
4465
|
+
- `run` (query): Only tests recorded in this run (a `key` from `/api/reports/runs`).
|
|
4466
|
+
- `sort` (query): The order: `spec` (default: domain, spec, title), `title`, `recent`, `slowest`, `failures`, `flaky` or `runs`.
|
|
4467
|
+
- `offset` (query): Skip this many matching tests.
|
|
4468
|
+
- `limit` (query): At most this many tests (default 500, at most 20000).
|
|
4469
|
+
- `format` (query): `markdown` for a Markdown report instead of JSON.
|
|
4470
|
+
- `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4471
|
+
|
|
4472
|
+
Responses: `200` The catalog.; `304` Unchanged since the `If-None-Match` ETag.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4473
|
+
|
|
4474
|
+
### Every test, with insights, facets and history statistics
|
|
4475
|
+
|
|
4476
|
+
`GET /api/projects/{project}/reports/tests` · role: read
|
|
4477
|
+
|
|
4478
|
+
The report as a list of tests, for exploring it or for an agent to read in one request. A test is a check identity (its spec path and id) across producers and environments; `outcomes` holds its current result on each environment, and `stats` how it went over its recorded history (pass rate, flips, flaky, durations avg/p50/p95, runs, branches).
|
|
4479
|
+
|
|
4480
|
+
`summary` and `facets` cover every test (counts by status, by environment, by producer and by domain, the slowest, flakiest and failing tests); `tests` is the page the query matched. Without a published spec set, specs come from the `specs[]` the layers recorded.
|
|
4481
|
+
|
|
4482
|
+
Send `format=markdown` (or `Accept: text/markdown`) for the same as a Markdown report. The current status of a test is always the report's winner; history never changes it.
|
|
4483
|
+
|
|
4484
|
+
Scoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.
|
|
4485
|
+
|
|
4486
|
+
- `project` (path, required): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4487
|
+
- `q` (query): Words that must all appear in the title, id, spec, domain, tags, labels, environments or producers. Case does not matter.
|
|
4488
|
+
- `status` (query): Current status, or `flaky`. Repeatable or comma-separated.
|
|
4489
|
+
- `environment` (query): Only tests with a result on this environment. Repeatable or comma-separated.
|
|
4490
|
+
- `producer` (query): Only tests from this producer. Repeatable or comma-separated.
|
|
4491
|
+
- `domain` (query): Only tests whose spec is in this domain (`(no spec)` for none). Repeatable or comma-separated.
|
|
4492
|
+
- `spec` (query): Only tests of this spec path. Repeatable or comma-separated.
|
|
4493
|
+
- `tag` (query): Only tests with this tag. Repeatable or comma-separated.
|
|
4494
|
+
- `run` (query): Only tests recorded in this run (a `key` from `/api/reports/runs`).
|
|
4495
|
+
- `sort` (query): The order: `spec` (default: domain, spec, title), `title`, `recent`, `slowest`, `failures`, `flaky` or `runs`.
|
|
4496
|
+
- `offset` (query): Skip this many matching tests.
|
|
4497
|
+
- `limit` (query): At most this many tests (default 500, at most 20000).
|
|
4498
|
+
- `format` (query): `markdown` for a Markdown report instead of JSON.
|
|
4499
|
+
|
|
4500
|
+
Responses: `200` The catalog.; `304` Unchanged since the `If-None-Match` ETag.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4501
|
+
|
|
4502
|
+
### One test and every result recorded for it
|
|
4503
|
+
|
|
4504
|
+
`GET /api/reports/tests/history` · role: read
|
|
4505
|
+
|
|
4506
|
+
The test (as `/api/reports/tests` lists it) and up to 100 recorded results, newest first: status, duration, environment, producer, branch, commit, CI run, layer and the first 500 characters of the detail. Open a result's evidence (attachments, steps, retries) with `/api/reports/evidence/detail/{backend}/{id}?check=<id>`. Send `format=markdown` for Markdown.
|
|
4507
|
+
|
|
4508
|
+
- `key` (query, required): The test's `key` from `/api/reports/tests`: `JSON.stringify([specPath, id])`, URL-encoded.
|
|
4509
|
+
- `format` (query): `markdown` for Markdown instead of JSON.
|
|
4510
|
+
- `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4511
|
+
|
|
4512
|
+
Responses: `200` The test and its history.; `304` Unchanged since the `If-None-Match` ETag.; `400` No `key`.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `404` No test in the report has that key.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4513
|
+
|
|
4514
|
+
### One test and every result recorded for it
|
|
4515
|
+
|
|
4516
|
+
`GET /api/projects/{project}/reports/tests/history` · role: read
|
|
4517
|
+
|
|
4518
|
+
The test (as `/api/reports/tests` lists it) and up to 100 recorded results, newest first: status, duration, environment, producer, branch, commit, CI run, layer and the first 500 characters of the detail. Open a result's evidence (attachments, steps, retries) with `/api/reports/evidence/detail/{backend}/{id}?check=<id>`. Send `format=markdown` for Markdown.
|
|
4519
|
+
|
|
4520
|
+
Scoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.
|
|
4521
|
+
|
|
4522
|
+
- `project` (path, required): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4523
|
+
- `key` (query, required): The test's `key` from `/api/reports/tests`: `JSON.stringify([specPath, id])`, URL-encoded.
|
|
4524
|
+
- `format` (query): `markdown` for Markdown instead of JSON.
|
|
4525
|
+
|
|
4526
|
+
Responses: `200` The test and its history.; `304` Unchanged since the `If-None-Match` ETag.; `400` No `key`.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `404` No test in the report has that key.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4527
|
+
|
|
4528
|
+
### The runs that recorded the report
|
|
4529
|
+
|
|
4530
|
+
`GET /api/reports/runs` · role: read
|
|
4531
|
+
|
|
4532
|
+
Every run, newest first: layers grouped by their CI run URL (else branch and commit), with their environments, producers, how many tests they recorded, their results by status, the time they spanned and up to twenty failures. Send `format=markdown` for Markdown.
|
|
4533
|
+
|
|
4534
|
+
- `limit` (query): At most this many runs (default 100).
|
|
4535
|
+
- `format` (query): `markdown` for Markdown instead of JSON.
|
|
4536
|
+
- `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4537
|
+
|
|
4538
|
+
Responses: `200` The runs.; `304` Unchanged since the `If-None-Match` ETag.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4539
|
+
|
|
4540
|
+
### The runs that recorded the report
|
|
4541
|
+
|
|
4542
|
+
`GET /api/projects/{project}/reports/runs` · role: read
|
|
4543
|
+
|
|
4544
|
+
Every run, newest first: layers grouped by their CI run URL (else branch and commit), with their environments, producers, how many tests they recorded, their results by status, the time they spanned and up to twenty failures. Send `format=markdown` for Markdown.
|
|
4545
|
+
|
|
4546
|
+
Scoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.
|
|
4547
|
+
|
|
4548
|
+
- `project` (path, required): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4549
|
+
- `limit` (query): At most this many runs (default 100).
|
|
4550
|
+
- `format` (query): `markdown` for Markdown instead of JSON.
|
|
4551
|
+
|
|
4552
|
+
Responses: `200` The runs.; `304` Unchanged since the `If-None-Match` ETag.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4553
|
+
|
|
4554
|
+
### Every test one run recorded
|
|
4555
|
+
|
|
4556
|
+
`GET /api/reports/runs/detail` · role: read
|
|
4557
|
+
|
|
4558
|
+
One run and its last result for every test, environment and producer it recorded, failures first. Send `format=markdown` for Markdown.
|
|
4559
|
+
|
|
4560
|
+
- `key` (query, required): The run's `key` from `/api/reports/runs`, URL-encoded.
|
|
4561
|
+
- `format` (query): `markdown` for Markdown instead of JSON.
|
|
4562
|
+
- `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4563
|
+
|
|
4564
|
+
Responses: `200` The run and its results.; `304` Unchanged since the `If-None-Match` ETag.; `400` No `key`.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `404` No run has that key.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4565
|
+
|
|
4566
|
+
### Every test one run recorded
|
|
4567
|
+
|
|
4568
|
+
`GET /api/projects/{project}/reports/runs/detail` · role: read
|
|
4569
|
+
|
|
4570
|
+
One run and its last result for every test, environment and producer it recorded, failures first. Send `format=markdown` for Markdown.
|
|
4571
|
+
|
|
4572
|
+
Scoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.
|
|
4573
|
+
|
|
4574
|
+
- `project` (path, required): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4575
|
+
- `key` (query, required): The run's `key` from `/api/reports/runs`, URL-encoded.
|
|
4576
|
+
- `format` (query): `markdown` for Markdown instead of JSON.
|
|
4577
|
+
|
|
4578
|
+
Responses: `200` The run and its results.; `304` Unchanged since the `If-None-Match` ETag.; `400` No `key`.; `401` No token, or an unknown one. Send `Authorization: Bearer <token>`.; `404` No run has that key.; `503` The server is still reading its backends. Retry after the number of seconds in `Retry-After`.
|
|
4579
|
+
|
|
4203
4580
|
### The specs a report is laid over
|
|
4204
4581
|
|
|
4205
4582
|
`GET /api/reports/outline` · role: read
|
|
4206
4583
|
|
|
4207
|
-
The specs of the newest committed spec set (of `main`, else the newest), so the report needs no checkout. A spec here with no result shows as having none.
|
|
4584
|
+
The specs of the newest committed spec set (of `main`, else the newest), so the report needs no checkout. Without a spec set, the specs the layers recorded (`specs[]`), newest per path. A spec here with no result shows as having none.
|
|
4208
4585
|
|
|
4209
4586
|
- `project` (query): Project slug. Alternatively send X-Atlas-Project or use the project-prefixed route. Omit for the default project. Conflicting selectors are refused.
|
|
4210
4587
|
|
|
@@ -4214,7 +4591,7 @@ Responses: `200` The outline.; `401` No token, or an unknown one. Send `Authoriz
|
|
|
4214
4591
|
|
|
4215
4592
|
`GET /api/projects/{project}/reports/outline` · role: read
|
|
4216
4593
|
|
|
4217
|
-
The specs of the newest committed spec set (of `main`, else the newest), so the report needs no checkout. A spec here with no result shows as having none.
|
|
4594
|
+
The specs of the newest committed spec set (of `main`, else the newest), so the report needs no checkout. Without a spec set, the specs the layers recorded (`specs[]`), newest per path. A spec here with no result shows as having none.
|
|
4218
4595
|
|
|
4219
4596
|
Scoped to one project. The same project may be selected on the unprefixed API using ?project= or X-Atlas-Project. Unknown projects return 404 on reads and are created by an authenticated upload.
|
|
4220
4597
|
|
package/llms.txt
CHANGED
|
@@ -10,6 +10,7 @@ Given only the repository link, start at docs/agents.md: install `@crvouga/atlas
|
|
|
10
10
|
- [Verify Atlas locally](https://raw.githubusercontent.com/crvouga/atlas/main/docs/quickstart.md): Prove that the installed Atlas can publish, combine and gate evidence before connecting your project's real suites.
|
|
11
11
|
- [Integrating Atlas into a project](https://raw.githubusercontent.com/crvouga/atlas/main/docs/integrating.md): This guide takes a project from nothing to a layered, gated report of its specs.
|
|
12
12
|
- [Native test runner reporters](https://raw.githubusercontent.com/crvouga/atlas/main/docs/runners.md): Projects upload results to a shared Atlas node under their own project slug.
|
|
13
|
+
- [Send rich evidence](https://raw.githubusercontent.com/crvouga/atlas/main/docs/rich-evidence.md): A check that says only its title and passed answers one question:
|
|
13
14
|
|
|
14
15
|
## Run and use the server
|
|
15
16
|
|
|
@@ -43,6 +44,7 @@ Given only the repository link, start at docs/agents.md: install `@crvouga/atlas
|
|
|
43
44
|
- [TypeScript API: detox](https://raw.githubusercontent.com/crvouga/atlas/main/docs/reference/detox.md): The Detox driver for statechart runs of React Native apps.
|
|
44
45
|
- [TypeScript API: runners](https://raw.githubusercontent.com/crvouga/atlas/main/docs/reference/runners.md): Native reporters that upload to the project server.
|
|
45
46
|
- [TypeScript API: vitest](https://raw.githubusercontent.com/crvouga/atlas/main/docs/reference/vitest.md): Run a statechart plan as Vitest tests.
|
|
47
|
+
- [TypeScript API: playwright-reporter](https://raw.githubusercontent.com/crvouga/atlas/main/docs/reference/playwright-reporter.md): A Playwright Test reporter that streams every test to Atlas with its duration, device labels, steps, retries, videos, screenshots and traces.
|
|
46
48
|
- [JSON Schemas](https://unpkg.com/@crvouga/atlas/packages/schema/schemas/): the layer format, checks file, report status, command results, server responses, server configuration.
|
|
47
49
|
|
|
48
50
|
## Optional
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crvouga/atlas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Atlas: specs of any kind, reported as layered evidence. Publish checks from any runner (JUnit, CTRF, a script), combine them across nodes, branches, environments and backends, gate CI on the result, and run statecharts against the real app.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -111,6 +111,10 @@
|
|
|
111
111
|
"./node-test": {
|
|
112
112
|
"types": "./dist/runners/src/node-test.d.ts",
|
|
113
113
|
"default": "./dist/runners/src/node-test.js"
|
|
114
|
+
},
|
|
115
|
+
"./playwright-reporter": {
|
|
116
|
+
"types": "./dist/playwright-reporter/src/index.d.ts",
|
|
117
|
+
"default": "./dist/playwright-reporter/src/index.js"
|
|
114
118
|
}
|
|
115
119
|
},
|
|
116
120
|
"publishConfig": {
|
|
@@ -141,6 +145,7 @@
|
|
|
141
145
|
"docs/deploying.md",
|
|
142
146
|
"docs/server.md",
|
|
143
147
|
"docs/extending.md",
|
|
148
|
+
"docs/rich-evidence.md",
|
|
144
149
|
"docs/statecharts.md",
|
|
145
150
|
"docs/report-contract.md",
|
|
146
151
|
"docs/report-backends.md",
|