@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.
Files changed (60) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/core/src/lint.js +6 -2
  3. package/dist/core/src/spec/types.d.ts +4 -1
  4. package/dist/playwright-reporter/src/evidence.d.ts +122 -0
  5. package/dist/playwright-reporter/src/evidence.js +327 -0
  6. package/dist/playwright-reporter/src/index.d.ts +114 -0
  7. package/dist/playwright-reporter/src/index.js +312 -0
  8. package/dist/reports/src/compose.js +7 -14
  9. package/dist/reports/src/recorded-specs.d.ts +33 -0
  10. package/dist/reports/src/recorded-specs.js +42 -0
  11. package/dist/reports/src/report-index.d.ts +6 -0
  12. package/dist/reports/src/report-index.js +14 -2
  13. package/dist/reports/src/test-catalog.d.ts +386 -0
  14. package/dist/reports/src/test-catalog.js +655 -0
  15. package/dist/schema/src/api.d.ts +585 -0
  16. package/dist/schema/src/api.js +105 -0
  17. package/dist/schema/src/spec.d.ts +2 -1
  18. package/dist/schema/src/spec.js +5 -2
  19. package/dist/server/src/app.js +82 -4
  20. package/dist/server/src/llms.js +14 -0
  21. package/dist/server/src/openapi.d.ts +1 -1
  22. package/dist/server/src/openapi.js +60 -3
  23. package/docs/agents.md +1 -0
  24. package/docs/integrating.md +1 -0
  25. package/docs/reference/core.md +7 -2
  26. package/docs/reference/http-api.md +134 -2
  27. package/docs/reference/playwright-reporter.md +332 -0
  28. package/docs/reference/reports.md +632 -0
  29. package/docs/reference/schema.md +58 -1
  30. package/docs/rich-evidence.md +198 -0
  31. package/docs/server.md +41 -0
  32. package/docs/statecharts.md +2 -1
  33. package/llms-full.txt +380 -3
  34. package/llms.txt +2 -0
  35. package/package.json +6 -1
  36. package/packages/schema/schemas/report-run.schema.json +251 -0
  37. package/packages/schema/schemas/report-runs.schema.json +177 -0
  38. package/packages/schema/schemas/state-node.schema.json +7 -0
  39. package/packages/schema/schemas/test-catalog.schema.json +1177 -0
  40. package/packages/schema/schemas/test-history.schema.json +696 -0
  41. package/packages/server/openapi.json +8676 -5351
  42. package/packages/visualizer/src/app/AppShell.tsx +7 -3
  43. package/packages/visualizer/src/app/router.tsx +26 -3
  44. package/packages/visualizer/src/components/Header.tsx +2 -2
  45. package/packages/visualizer/src/evidence/evidence-context.tsx +10 -1
  46. package/packages/visualizer/src/explorer/Explorer.tsx +433 -0
  47. package/packages/visualizer/src/explorer/ExplorerIndex.tsx +120 -0
  48. package/packages/visualizer/src/explorer/RunsView.tsx +164 -0
  49. package/packages/visualizer/src/explorer/TestDetail.tsx +214 -0
  50. package/packages/visualizer/src/explorer/catalog.tsx +274 -0
  51. package/packages/visualizer/src/explorer/explorer.module.css +1238 -0
  52. package/packages/visualizer/src/explorer/groups.test.ts +87 -0
  53. package/packages/visualizer/src/explorer/groups.ts +126 -0
  54. package/packages/visualizer/src/explorer/navigate.ts +36 -0
  55. package/packages/visualizer/src/explorer/parts.tsx +59 -0
  56. package/packages/visualizer/src/explorer/search.ts +97 -0
  57. package/packages/visualizer/src/find/Finder.tsx +2 -0
  58. package/packages/visualizer/src/find/corpus.ts +13 -6
  59. package/packages/visualizer/src/find/rank.ts +2 -0
  60. package/packages/visualizer/src/evidence/project-home.tsx +0 -45
@@ -0,0 +1,332 @@
1
+ # Reference: playwright-reporter
2
+
3
+ A Playwright Test reporter that streams every test to Atlas with its duration, device labels, steps, retries, videos, screenshots and traces. Import path `@crvouga/atlas/playwright-reporter`.
4
+
5
+ > Generated from the doc comments of `packages/playwright-reporter/src` by `bun run docs`. Do not edit: change the comment next to the code.
6
+
7
+ ### Playwright results as Atlas evidence
8
+
9
+ Source: `packages/playwright-reporter/src/evidence.ts`
10
+
11
+ The pure half of the Playwright Test reporter: how one Playwright test and its results become one Atlas check, with
12
+ its status, failure detail, duration, tags, annotations, links, timeline steps, retry attempts and attachments, and
13
+ how a project becomes an environment and labels. Nothing here talks to a store; the only input/output is reading the
14
+ files Playwright attached (videos, traces, screenshots) and looking for a repository root or a `.feature` file.
15
+
16
+ See docs/rich-evidence.md
17
+
18
+ #### `CheckInput`
19
+
20
+ ```ts
21
+ export type CheckInput = PublishChecksInput['checks'][number];
22
+ ```
23
+
24
+ One check as handed to the streaming reporter: the input type of a check in `PublishChecksSchema`.
25
+
26
+ #### `AttachmentMode`
27
+
28
+ ```ts
29
+ export type AttachmentMode = 'all' | 'failures' | 'none';
30
+ ```
31
+
32
+ Which results upload their attachments: every one, only failed checks and failed attempts, or none.
33
+
34
+ #### `AttachmentPolicy`
35
+
36
+ ```ts
37
+ export type AttachmentPolicy = {
38
+ /** `all`, `failures` (failed checks and failed attempts only) or `none`. */
39
+ readonly mode: AttachmentMode;
40
+ /** A larger file is not uploaded; the check gets an `attachment-skipped` annotation instead. */
41
+ readonly maxBytes: number;
42
+ };
43
+ ```
44
+
45
+ What to upload of the files Playwright attached: the `mode`, and the largest single file in bytes (`maxBytes`).
46
+
47
+ #### `CheckContext`
48
+
49
+ ```ts
50
+ export type CheckContext = {
51
+ /** The check's stable id: `<specPath>#<describe titles > test title>`. */
52
+ readonly id: string;
53
+ readonly title: string;
54
+ /** The spec the check belongs to, relative to the repository. */
55
+ readonly specPath: string;
56
+ /** Facts about where it ran: browser, device, viewport, os, playwright version. */
57
+ readonly labels: Readonly<Record<string, string>>;
58
+ /** Relative paths (source locations) are written relative to this directory. */
59
+ readonly root: string;
60
+ readonly attachments: AttachmentPolicy;
61
+ /** The most timeline steps recorded per result; the rest are counted in an annotation. */
62
+ readonly maxSteps: number;
63
+ };
64
+ ```
65
+
66
+ Where a check comes from and how it is recorded, as worked out by the reporter before its evidence is collected.
67
+
68
+ #### `stripAnsi`
69
+
70
+ ```ts
71
+ export function stripAnsi(text: string): string
72
+ ```
73
+
74
+ Removes terminal colour and cursor codes, which Playwright puts in error messages and step titles.
75
+
76
+ **Example**
77
+
78
+ ```ts
79
+ stripAnsi('\u001b[31mExpected\u001b[39m'); // 'Expected'
80
+ ```
81
+
82
+ #### `errorDetail`
83
+
84
+ ```ts
85
+ export function errorDetail(error: TestError | undefined, maxChars = 8000): string
86
+ ```
87
+
88
+ The failure detail of an error: its message and stack without terminal codes, the message once, cut to `maxChars`.
89
+ An absent error is the empty string.
90
+
91
+ - `error`: A Playwright `TestError` (a result's or a step's).
92
+
93
+ - `maxChars`: The longest detail kept. Default 8000.
94
+
95
+ #### `resultStatus`
96
+
97
+ ```ts
98
+ export function resultStatus(test: Pick<TestCase, 'expectedStatus'>, result: Pick<TestResult, 'status'>): 'passed' | 'failed' | 'not-run'
99
+ ```
100
+
101
+ The Atlas status of one Playwright result: skipped is `not-run`; the status the test expected (`passed`, or `failed`
102
+ for a `test.fail()`) is `passed`; anything else (failed, timed out, interrupted, an expected failure that passed) is
103
+ `failed`.
104
+
105
+ #### `willRetry`
106
+
107
+ ```ts
108
+ export function willRetry(test: Pick<TestCase, 'expectedStatus' | 'retries'>, result: Pick<TestResult, 'status' | 'retry'>): boolean
109
+ ```
110
+
111
+ Whether Playwright will run this test again after this result: it did not get what it expected and has retries left.
112
+
113
+ #### `stepKind`
114
+
115
+ ```ts
116
+ export function stepKind(step: Pick<TestStep, 'category' | 'title'>): string
117
+ ```
118
+
119
+ The timeline kind of a Playwright step, by its category: `test.step` is `step` (or the Gherkin keyword, `given`,
120
+ `when`, `then`, `and`, `but`, for a playwright-bdd step), `expect` is `assertion`, `pw:api` is `action`, `hook`,
121
+ `fixture`; any other category is kept as it is.
122
+
123
+ #### `flattenSteps`
124
+
125
+ ```ts
126
+ export function flattenSteps(steps: readonly TestStep[], startedAtMs: number, max: number): { steps: StepInput[]; dropped: number }
127
+ ```
128
+
129
+ Playwright's step tree as Atlas's flat timeline: each step gets an id (`s1`, `s2`, …), its parent's id, its kind,
130
+ when it started after the result did (`offsetMs`), how long it took, and `failed` with the error as detail when it
131
+ failed. At most `max` steps are kept, in order; `dropped` counts the rest.
132
+
133
+ - `steps`: `result.steps`.
134
+
135
+ - `startedAtMs`: When the result started (`result.startTime`), in epoch milliseconds.
136
+
137
+ - `max`: The most steps kept.
138
+
139
+ #### `findRepoRoot`
140
+
141
+ ```ts
142
+ export function findRepoRoot(start: string, exists: (file: string) => boolean = existsSync): string | null
143
+ ```
144
+
145
+ The closest directory at or above `start` that holds `.git` (a folder, or a file in a worktree), or null. Reads the
146
+ file system only; it never runs git.
147
+
148
+ #### `repoPath`
149
+
150
+ ```ts
151
+ export function repoPath(file: string, root: string): string
152
+ ```
153
+
154
+ `file` relative to `root`, with forward slashes on every OS.
155
+
156
+ #### `bddFeaturePath`
157
+
158
+ ```ts
159
+ export function bddFeaturePath(file: string, exists: (file: string) => boolean = existsSync): string | undefined
160
+ ```
161
+
162
+ The `.feature` file a playwright-bdd generated test came from, or undefined for any other test file. playwright-bdd
163
+ writes `<outputDir>/<path>.feature.spec.js` (its outputDir is `.features-gen` by default, mirroring the feature
164
+ folders); this returns the first `<path>.feature` that exists beside `.features-gen` (dropping leading folders, such
165
+ as a per-project output folder, until one does), else the mapped path even if no such file is found.
166
+
167
+ - `file`: The absolute path of the test file (`test.location.file`).
168
+
169
+ **Example**
170
+
171
+ ```ts
172
+ bddFeaturePath('/repo/e2e/.features-gen/features/login.feature.spec.js'); // '/repo/e2e/features/login.feature'
173
+ ```
174
+
175
+ #### `projectEnvironment`
176
+
177
+ ```ts
178
+ export function projectEnvironment(project: Pick<FullProject, 'use'> | undefined): string
179
+ ```
180
+
181
+ The environment a project tests by default: `mobile-web` when it emulates a mobile device (`use.isMobile`), else `desktop-web`.
182
+
183
+ #### `projectLabels`
184
+
185
+ ```ts
186
+ export function projectLabels(project: Pick<FullProject, 'name' | 'use'> | undefined, version?: string): Record<string, string>
187
+ ```
188
+
189
+ What every check of a project carries as labels: `browser` (`use.browserName`, else the device's
190
+ `defaultBrowserType`), `channel`, `device` (the project name), `viewport` (`<width>x<height>`), `os`
191
+ (`process.platform`) and `playwright` (its version). Labels describe a result; they never split its slot.
192
+
193
+ - `project`: The Playwright project, or undefined when it is not known.
194
+
195
+ - `version`: Playwright's version (`config.version`).
196
+
197
+ #### `resultAttachments`
198
+
199
+ ```ts
200
+ export async function resultAttachments(result: Pick<TestResult, 'attachments' | 'stdout' | 'stderr'>, failed: boolean, policy: AttachmentPolicy): Promise<{ attachments: AttachmentInput[]; annotations: AnnotationInput[] }>
201
+ ```
202
+
203
+ The files and output of one result as attachments with their bytes: every `result.attachments` entry (role `video`,
204
+ `screenshot` or `trace` by its Playwright name, else the name itself; bytes from `body`, or read from `path`), and
205
+ standard output and error as `log` text. A file over the size limit, or that cannot be read, is left out with an
206
+ `attachment-skipped` annotation saying why. Never throws.
207
+
208
+ - `result`: The Playwright result.
209
+
210
+ - `failed`: Whether the result failed, for the `failures` mode.
211
+
212
+ - `policy`: What to upload.
213
+
214
+ #### `checkOf`
215
+
216
+ ```ts
217
+ export async function checkOf(test: TestCase, results: readonly TestResult[], context: CheckContext): Promise<CheckInput>
218
+ ```
219
+
220
+ The final check of a Playwright test from all its results (one per try): status of the last result (`flaky`, as a
221
+ tag and a label, when it passed after a failed try), failure detail without terminal codes, duration, tags (the
222
+ test's tags without `@`, and its annotation types), annotations, links (annotations whose description is a URL),
223
+ timeline steps, one attempt per try when it was retried, attachments, and the test's location under the
224
+ `playwright` extension. Reads attached files; never throws for a file it cannot read.
225
+
226
+ - `test`: The Playwright test.
227
+
228
+ - `results`: Its results, oldest first (`test.results`).
229
+
230
+ - `context`: Its identity and what to record.
231
+
232
+ ### Playwright Test reporter
233
+
234
+ Source: `packages/playwright-reporter/src/index.ts`. Import: `@crvouga/atlas/playwright-reporter`
235
+
236
+ `@crvouga/atlas/playwright-reporter` is a Playwright Test reporter that streams every test to an Atlas server (or any
237
+ store) as it runs, with the evidence Playwright already has: durations, failure details, steps as a timeline, retries
238
+ as attempts (and `flaky`), tags, annotations, and the videos, screenshots and traces it attached. Each Playwright
239
+ project is its own stream of layers, so a desktop and a mobile project are two environments of the same checks, and
240
+ every check is labelled with its browser, device, viewport, operating system and Playwright version.
241
+
242
+ It never throws into the test run: a destination that is not configured, a store that is down or a file that cannot
243
+ be read is said once, and the run goes on. Playwright is only imported for its types, so importing this module loads
244
+ nothing of Playwright.
245
+
246
+ See docs/rich-evidence.md
247
+
248
+ #### `PerProject`
249
+
250
+ ```ts
251
+ export type PerProject<T> = T | ((project: FullProject) => T);
252
+ ```
253
+
254
+ A value given once for every project, or worked out from each project.
255
+
256
+ #### `AtlasPlaywrightReporterOptions`
257
+
258
+ ```ts
259
+ export type AtlasPlaywrightReporterOptions = {
260
+ /** Project namespace on a shared Atlas server. Default `ATLAS_PROJECT`. */
261
+ readonly project?: string;
262
+ /** The Atlas server (`https://atlas.example.com`), or any store location (`./atlas-reports`, `s3://bucket/prefix`). Default `ATLAS_SERVER_URL`, else `ATLAS_STORE`. */
263
+ readonly url?: string;
264
+ /** A publish token. Default `ATLAS_PUBLISH_TOKEN`, else `ATLAS_TOKEN` (or the file `ATLAS_TOKEN_FILE` names). */
265
+ readonly token?: string;
266
+ /** Publish to this store instead of a URL: a directory store, an in-memory store in tests, anything that implements `ObjectStore`. */
267
+ readonly store?: ObjectStore;
268
+ /** A stable name for this suite. With the check id, environment and parameters it picks the slot a result fills. Default `playwright`. */
269
+ readonly producer?: string;
270
+ /** The part kind of every layer. Default `checks`. */
271
+ readonly kind?: string;
272
+ /** The environment of a project's checks. Default `mobile-web` for a project with `use.isMobile`, else `desktop-web`. */
273
+ readonly environment?: PerProject<string>;
274
+ /** Choices that make a result its own slot (a locale, a tenant). Empty by default: labels never split slots, parameters do. */
275
+ readonly parameters?: PerProject<Readonly<Record<string, string>>>;
276
+ /** More labels for every check of a project, beside browser, device, viewport, os and playwright. */
277
+ readonly labels?: PerProject<Readonly<Record<string, string>>>;
278
+ /** The commit tested. Default `ATLAS_SHA`, then the CI's own variables (`GITHUB_SHA`…), then git. */
279
+ readonly sha?: string;
280
+ /** The branch tested. Default `ATLAS_BRANCH`, then `GITHUB_HEAD_REF`, `GITHUB_REF_NAME`…, then git. */
281
+ readonly branch?: string;
282
+ /** Where to read the CI run. Default the GitHub Actions run (or the CI's own run URL variable). */
283
+ readonly runUrl?: string;
284
+ /** The spec a test belongs to, relative to the repository. Default: the `.feature` of a playwright-bdd test, else the test file. */
285
+ readonly specPath?: (test: TestCase) => string | undefined;
286
+ /** Paths are relative to this directory. Default the git root above Playwright's `rootDir`, else `rootDir`. */
287
+ readonly rootDir?: string;
288
+ /** Which results upload their attachments (videos, screenshots, traces, output): `all`, `failures` or `none`. Default `all`. */
289
+ readonly attachments?: AttachmentMode;
290
+ /** A larger file is not uploaded; the check says so in an annotation. Default 50 MiB. */
291
+ readonly maxAttachmentBytes?: number;
292
+ /** The most timeline steps recorded per result. Default 500. */
293
+ readonly maxSteps?: number;
294
+ /** Record the project's spec files (path, domain, kind, title) in every layer, so a server can group checks by spec without a published spec set. Default true. */
295
+ readonly specs?: boolean;
296
+ /** Send what has finished this often, in ms. Default 5000 (every layer repeats the spec list). */
297
+ readonly flushMs?: number;
298
+ /** Send at once when this many checks are waiting. Default 50 (their attachments are held in memory until sent). */
299
+ …
300
+ ```
301
+
302
+ Options of the Playwright Test reporter, given as the second element of its entry in `reporter` in
303
+ `playwright.config.ts`. Every one is optional: with `ATLAS_SERVER_URL`, `ATLAS_TOKEN` and `ATLAS_PROJECT` set, none
304
+ is needed.
305
+
306
+ #### `AtlasPlaywrightReporter`
307
+
308
+ ```ts
309
+ export default class AtlasPlaywrightReporter implements PlaywrightReporter
310
+ ```
311
+
312
+ The Playwright Test reporter of Atlas. Add it beside your console reporter; it streams each test as `running` when
313
+ it starts and with its full evidence when its last try ends, one stream of layers per Playwright project, and
314
+ prints one summary line when the run ends. It never fails or slows the run on account of Atlas.
315
+
316
+ **Example**
317
+
318
+ ```ts
319
+ // playwright.config.ts
320
+ import { defineConfig } from '@playwright/test';
321
+
322
+ export default defineConfig({
323
+ reporter: [['list'], ['@crvouga/atlas/playwright-reporter', { project: 'checkout', producer: 'e2e-web' }]],
324
+ use: { video: 'retain-on-failure', trace: 'retain-on-failure', screenshot: 'only-on-failure' }
325
+ });
326
+ ```
327
+
328
+ - `printsToStdio(): boolean` — This reporter prints only a summary line, so Playwright keeps its own console output.
329
+ - `onBegin(config: FullConfig, _suite: Suite): void` — Resolves where layers go, where the run came from, and the directory paths are relative to. Never throws.
330
+ - `onTestBegin(test: TestCase, _result: TestResult): void` — Reports the test as `running`, so the report shows it while it runs.
331
+ - `onTestEnd(test: TestCase, result: TestResult): void` — On a test's last try, collects its evidence (reading its attached files) and reports it. A try Playwright will repeat leaves the test `running`.
332
+ - `async onEnd(): Promise<void>` — Waits for every result, marks tests the run did not finish as `not-run`, sends the rest, and prints one summary line.