@crvouga/atlas 0.4.0 → 0.6.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 +13 -1
- package/README.md +191 -611
- package/dist/bun/src/driver.d.ts +41 -7
- package/dist/bun/src/driver.js +47 -6
- package/dist/bun/src/index.d.ts +8 -0
- package/dist/bun/src/index.js +8 -0
- package/dist/core/src/cli.d.ts +14 -1
- package/dist/core/src/cli.js +35 -1
- package/dist/core/src/config.d.ts +77 -4
- package/dist/core/src/config.js +110 -17
- package/dist/core/src/events/cloudevents.d.ts +54 -9
- package/dist/core/src/events/cloudevents.js +60 -9
- package/dist/core/src/graph.d.ts +21 -0
- package/dist/core/src/graph.js +26 -0
- package/dist/core/src/index.d.ts +11 -0
- package/dist/core/src/index.js +11 -0
- package/dist/core/src/lint.d.ts +30 -0
- package/dist/core/src/lint.js +13 -0
- package/dist/core/src/plan.d.ts +39 -1
- package/dist/core/src/plan.js +28 -1
- package/dist/core/src/privacy.d.ts +29 -2
- package/dist/core/src/privacy.js +19 -2
- package/dist/core/src/report/formats.d.ts +34 -4
- package/dist/core/src/report/formats.js +24 -4
- package/dist/core/src/report/markdown.d.ts +15 -0
- package/dist/core/src/report/markdown.js +8 -0
- package/dist/core/src/run/clients.d.ts +44 -5
- package/dist/core/src/run/clients.js +46 -2
- package/dist/core/src/run/execute.d.ts +75 -16
- package/dist/core/src/run/execute.js +71 -18
- package/dist/core/src/run/frames.d.ts +13 -4
- package/dist/core/src/run/frames.js +19 -4
- package/dist/core/src/run/http.d.ts +34 -1
- package/dist/core/src/run/http.js +14 -1
- package/dist/core/src/run/types.d.ts +76 -3
- package/dist/core/src/run/types.js +19 -3
- package/dist/core/src/signals.d.ts +49 -5
- package/dist/core/src/signals.js +22 -5
- package/dist/core/src/spec/compose.d.ts +23 -1
- package/dist/core/src/spec/compose.js +10 -1
- package/dist/core/src/spec/index.d.ts +9 -1
- package/dist/core/src/spec/index.js +9 -1
- package/dist/core/src/spec/load.d.ts +22 -1
- package/dist/core/src/spec/load.js +31 -1
- package/dist/core/src/spec/parse.d.ts +16 -2
- package/dist/core/src/spec/parse.js +25 -2
- package/dist/core/src/spec/scxml.d.ts +25 -4
- package/dist/core/src/spec/scxml.js +36 -4
- package/dist/core/src/spec/types.d.ts +52 -1
- package/dist/core/src/spec/types.js +24 -0
- package/dist/detox/src/index.d.ts +54 -11
- package/dist/detox/src/index.js +45 -7
- package/dist/playwright/src/driver.d.ts +39 -3
- package/dist/playwright/src/driver.js +27 -3
- package/dist/playwright/src/index.d.ts +10 -0
- package/dist/playwright/src/index.js +10 -0
- package/dist/playwright/src/media.d.ts +50 -4
- package/dist/playwright/src/media.js +55 -4
- package/dist/playwright/src/signals.d.ts +44 -5
- package/dist/playwright/src/signals.js +29 -5
- package/dist/reports/src/attachment-files.d.ts +44 -0
- package/dist/reports/src/attachment-files.js +121 -0
- package/dist/reports/src/attachment-response.d.ts +31 -0
- package/dist/reports/src/attachment-response.js +55 -0
- package/dist/reports/src/aws-credentials.d.ts +48 -0
- package/dist/reports/src/aws-credentials.js +221 -0
- package/dist/reports/src/browser-navigation.d.ts +14 -0
- package/dist/reports/src/browser-navigation.js +7 -0
- package/dist/reports/src/bundle.d.ts +34 -2
- package/dist/reports/src/bundle.js +38 -2
- package/dist/reports/src/catalog.d.ts +34 -3
- package/dist/reports/src/catalog.js +17 -3
- package/dist/reports/src/cli-stores.d.ts +36 -0
- package/dist/reports/src/cli-stores.js +73 -0
- package/dist/reports/src/clock.d.ts +7 -2
- package/dist/reports/src/clock.js +5 -2
- package/dist/reports/src/completion-order.d.ts +18 -5
- package/dist/reports/src/completion-order.js +18 -5
- package/dist/reports/src/compose.d.ts +80 -0
- package/dist/reports/src/compose.js +117 -0
- package/dist/reports/src/copy-store.d.ts +29 -0
- package/dist/reports/src/copy-store.js +52 -0
- package/dist/reports/src/directory-outline.d.ts +38 -0
- package/dist/reports/src/directory-outline.js +103 -0
- package/dist/reports/src/directory-store.d.ts +20 -0
- package/dist/reports/src/directory-store.js +166 -0
- package/dist/reports/src/doctor.d.ts +29 -0
- package/dist/reports/src/doctor.js +85 -0
- package/dist/reports/src/effective-delta.d.ts +34 -0
- package/dist/reports/src/effective-delta.js +25 -0
- package/dist/reports/src/evidence-detail.d.ts +64 -0
- package/dist/reports/src/evidence-detail.js +92 -0
- package/dist/reports/src/evidence-live.d.ts +35 -5
- package/dist/reports/src/evidence-live.js +18 -2
- package/dist/reports/src/evidence-types.d.ts +68 -1
- package/dist/reports/src/evidence-types.js +5 -1
- package/dist/reports/src/evidence-view.d.ts +43 -4
- package/dist/reports/src/evidence-view.js +13 -2
- package/dist/reports/src/explorer-types.d.ts +40 -3
- package/dist/reports/src/explorer-types.js +8 -0
- package/dist/reports/src/explorer-versions.d.ts +9 -1
- package/dist/reports/src/explorer-versions.js +18 -1
- package/dist/reports/src/export-evidence.d.ts +16 -1
- package/dist/reports/src/export-evidence.js +52 -1
- package/dist/reports/src/fetcher.d.ts +27 -3
- package/dist/reports/src/fetcher.js +11 -3
- package/dist/reports/src/format-date.d.ts +6 -0
- package/dist/reports/src/format-date.js +6 -0
- package/dist/reports/src/format.d.ts +16 -0
- package/dist/reports/src/format.js +10 -0
- package/dist/reports/src/frames.d.ts +36 -3
- package/dist/reports/src/frames.js +22 -3
- package/dist/reports/src/hash.d.ts +18 -0
- package/dist/reports/src/hash.js +13 -0
- package/dist/reports/src/host.d.ts +29 -0
- package/dist/reports/src/host.js +64 -0
- package/dist/reports/src/html-frame.d.ts +5 -6
- package/dist/reports/src/html-frame.js +12 -1
- package/dist/reports/src/http-store.d.ts +56 -0
- package/dist/reports/src/http-store.js +148 -0
- package/dist/reports/src/http.d.ts +7 -0
- package/dist/reports/src/http.js +6 -0
- package/dist/reports/src/ingest.d.ts +54 -0
- package/dist/reports/src/ingest.js +210 -0
- package/dist/reports/src/init.d.ts +40 -0
- package/dist/reports/src/init.js +369 -0
- package/dist/reports/src/junit.d.ts +33 -6
- package/dist/reports/src/junit.js +87 -21
- package/dist/reports/src/keyboard.d.ts +20 -0
- package/dist/reports/src/keyboard.js +11 -0
- package/dist/reports/src/keys.d.ts +21 -3
- package/dist/reports/src/keys.js +21 -3
- package/dist/reports/src/layer-axes.d.ts +35 -5
- package/dist/reports/src/layer-axes.js +25 -5
- package/dist/reports/src/layer-catalog.d.ts +28 -1
- package/dist/reports/src/layer-catalog.js +18 -1
- package/dist/reports/src/layer-merge.d.ts +98 -9
- package/dist/reports/src/layer-merge.js +147 -31
- package/dist/reports/src/layer-source.d.ts +18 -0
- package/dist/reports/src/layer-source.js +11 -0
- package/dist/reports/src/layer-store.d.ts +42 -0
- package/dist/reports/src/layer-store.js +63 -5
- package/dist/reports/src/layer-types.d.ts +32 -1
- package/dist/reports/src/layers-route.d.ts +47 -4
- package/dist/reports/src/layers-route.js +86 -7
- package/dist/reports/src/live-reporter.d.ts +34 -0
- package/dist/reports/src/live-reporter.js +122 -0
- package/dist/reports/src/media-types.d.ts +11 -0
- package/dist/reports/src/media-types.js +22 -0
- package/dist/reports/src/namespace-guard.d.ts +10 -1
- package/dist/reports/src/namespace-guard.js +10 -1
- package/dist/reports/src/navigation.d.ts +12 -0
- package/dist/reports/src/navigation.js +7 -0
- package/dist/reports/src/object-io.d.ts +11 -4
- package/dist/reports/src/object-io.js +4 -4
- package/dist/reports/src/object-store-conformance.d.ts +27 -0
- package/dist/reports/src/object-store-conformance.js +87 -0
- package/dist/reports/src/object-store.d.ts +33 -24
- package/dist/reports/src/object-store.js +17 -24
- package/dist/reports/src/parse-with.d.ts +16 -0
- package/dist/reports/src/parse-with.js +14 -0
- package/dist/reports/src/performance-part.d.ts +25 -1
- package/dist/reports/src/performance-part.js +15 -1
- package/dist/reports/src/performance.d.ts +22 -2
- package/dist/reports/src/performance.js +12 -2
- package/dist/reports/src/persist.d.ts +12 -3
- package/dist/reports/src/persist.js +12 -3
- package/dist/reports/src/phone.d.ts +18 -1
- package/dist/reports/src/phone.js +18 -1
- package/dist/reports/src/protocol.d.ts +26 -4
- package/dist/reports/src/protocol.js +15 -4
- package/dist/reports/src/publication.d.ts +21 -1
- package/dist/reports/src/publication.js +21 -1
- package/dist/reports/src/publish-checks.d.ts +35 -0
- package/dist/reports/src/publish-checks.js +122 -0
- package/dist/reports/src/publish.d.ts +42 -9
- package/dist/reports/src/publish.js +36 -7
- package/dist/reports/src/read.d.ts +46 -16
- package/dist/reports/src/read.js +38 -14
- package/dist/reports/src/recording-bundle.d.ts +13 -2
- package/dist/reports/src/recording-bundle.js +4 -2
- package/dist/reports/src/recording-keys.d.ts +15 -1
- package/dist/reports/src/recording-keys.js +15 -1
- package/dist/reports/src/remote-report.d.ts +28 -7
- package/dist/reports/src/remote-report.js +15 -7
- package/dist/reports/src/report-cli.d.ts +51 -0
- package/dist/reports/src/report-cli.js +486 -0
- package/dist/reports/src/report-index.d.ts +99 -0
- package/dist/reports/src/report-index.js +337 -0
- package/dist/reports/src/report-loader.d.ts +10 -0
- package/dist/reports/src/report-loader.js +6 -0
- package/dist/reports/src/report-parts.d.ts +29 -3
- package/dist/reports/src/report-parts.js +37 -3
- package/dist/reports/src/report-status.d.ts +48 -0
- package/dist/reports/src/report-status.js +156 -0
- package/dist/reports/src/report-types.d.ts +73 -0
- package/dist/reports/src/report-types.js +3 -0
- package/dist/reports/src/reporter.d.ts +67 -0
- package/dist/reports/src/reporter.js +128 -0
- package/dist/reports/src/reports-explorer-route.d.ts +541 -0
- package/dist/reports/src/reports-explorer-route.js +11 -0
- package/dist/reports/src/reports-list-route.d.ts +9 -0
- package/dist/reports/src/reports-list-route.js +9 -0
- package/dist/reports/src/reports-route.d.ts +561 -22
- package/dist/reports/src/reports-route.js +11 -3
- package/dist/reports/src/reports-store.d.ts +19 -2
- package/dist/reports/src/reports-store.js +10 -2
- package/dist/reports/src/resilient-cache.d.ts +14 -1
- package/dist/reports/src/resilient-cache.js +8 -1
- package/dist/reports/src/retention.d.ts +17 -1
- package/dist/reports/src/retention.js +5 -1
- package/dist/reports/src/run-bundle.d.ts +63 -0
- package/dist/reports/src/run-bundle.js +159 -0
- package/dist/reports/src/s3-store.d.ts +79 -0
- package/dist/reports/src/s3-store.js +295 -0
- package/dist/reports/src/scenario.d.ts +14 -4
- package/dist/reports/src/scenario.js +5 -4
- package/dist/reports/src/sigv4.d.ts +72 -0
- package/dist/reports/src/sigv4.js +96 -0
- package/dist/reports/src/snapshot-bundle.d.ts +24 -1
- package/dist/reports/src/snapshot-bundle.js +27 -2
- package/dist/reports/src/snapshot-surface.d.ts +20 -9
- package/dist/reports/src/snapshot-surface.js +32 -19
- package/dist/reports/src/source-content.d.ts +23 -0
- package/dist/reports/src/source-content.js +30 -1
- package/dist/reports/src/source-entries.d.ts +13 -0
- package/dist/reports/src/source-entries.js +6 -0
- package/dist/reports/src/source-part.d.ts +15 -0
- package/dist/reports/src/source-part.js +8 -0
- package/dist/reports/src/source-reader.d.ts +11 -0
- package/dist/reports/src/source-reader.js +5 -0
- package/dist/reports/src/spec-evidence.d.ts +12 -2
- package/dist/reports/src/spec-evidence.js +6 -2
- package/dist/reports/src/spec-inventory.d.ts +15 -1
- package/dist/reports/src/spec-inventory.js +22 -1
- package/dist/reports/src/spec-link.d.ts +28 -0
- package/dist/reports/src/spec-link.js +70 -0
- package/dist/reports/src/spec-set.d.ts +63 -0
- package/dist/reports/src/spec-set.js +177 -0
- package/dist/reports/src/status.d.ts +10 -0
- package/dist/reports/src/status.js +5 -0
- package/dist/reports/src/store-prefix.d.ts +28 -0
- package/dist/reports/src/store-prefix.js +22 -0
- package/dist/reports/src/store-url.d.ts +89 -0
- package/dist/reports/src/store-url.js +160 -0
- package/dist/reports/src/test-catalog-entity.d.ts +11 -0
- package/dist/reports/src/test-catalog-entity.js +6 -0
- package/dist/reports/src/types.d.ts +6 -1
- package/dist/reports/src/use-report-nav.d.ts +35 -0
- package/dist/reports/src/use-report-nav.js +12 -0
- package/dist/runners/src/codecept.d.ts +14 -0
- package/dist/runners/src/codecept.js +16 -0
- package/dist/runners/src/jest.d.ts +50 -0
- package/dist/runners/src/jest.js +52 -0
- package/dist/runners/src/mocha.d.ts +40 -0
- package/dist/runners/src/mocha.js +39 -0
- package/dist/runners/src/node-test.d.ts +28 -0
- package/dist/runners/src/node-test.js +44 -0
- package/dist/runners/src/publish.d.ts +30 -0
- package/dist/runners/src/publish.js +68 -0
- package/dist/schema/src/api.d.ts +800 -0
- package/dist/schema/src/api.js +201 -0
- package/dist/schema/src/cli-results.d.ts +210 -0
- package/dist/schema/src/cli-results.js +124 -0
- package/dist/schema/src/common.d.ts +53 -0
- package/dist/schema/src/common.js +42 -0
- package/dist/schema/src/index.d.ts +16 -0
- package/dist/schema/src/index.js +16 -0
- package/dist/schema/src/layer.d.ts +2273 -0
- package/dist/schema/src/layer.js +462 -0
- package/dist/schema/src/live-run.d.ts +123 -0
- package/dist/schema/src/live-run.js +30 -0
- package/dist/schema/src/manifest.d.ts +97 -2
- package/dist/schema/src/manifest.js +84 -0
- package/dist/schema/src/project.d.ts +20 -0
- package/dist/schema/src/project.js +10 -0
- package/dist/schema/src/report-sources.d.ts +29 -0
- package/dist/schema/src/report-sources.js +27 -1
- package/dist/schema/src/runs-index.d.ts +17 -1
- package/dist/schema/src/runs-index.js +15 -0
- package/dist/schema/src/server-config.d.ts +177 -0
- package/dist/schema/src/server-config.js +85 -0
- package/dist/schema/src/spec.d.ts +69 -0
- package/dist/schema/src/spec.js +58 -0
- package/dist/server/src/app.d.ts +72 -0
- package/dist/server/src/app.js +557 -0
- package/dist/server/src/auth.d.ts +41 -0
- package/dist/server/src/auth.js +59 -0
- package/dist/server/src/config.d.ts +83 -0
- package/dist/server/src/config.js +204 -0
- package/dist/server/src/dev.d.ts +12 -0
- package/dist/server/src/dev.js +89 -0
- package/dist/server/src/events.d.ts +29 -0
- package/dist/server/src/events.js +101 -0
- package/dist/server/src/host.d.ts +30 -0
- package/dist/server/src/host.js +115 -0
- package/dist/server/src/index.d.ts +18 -0
- package/dist/server/src/index.js +18 -0
- package/dist/server/src/live-runs.d.ts +52 -0
- package/dist/server/src/live-runs.js +229 -0
- package/dist/server/src/llms.d.ts +19 -0
- package/dist/server/src/llms.js +63 -0
- package/dist/server/src/main.d.ts +30 -0
- package/dist/server/src/main.js +114 -0
- package/dist/server/src/openapi.d.ts +56 -0
- package/dist/server/src/openapi.js +438 -0
- package/dist/server/src/problem.d.ts +8 -0
- package/dist/server/src/problem.js +39 -0
- package/dist/server/src/projects.d.ts +3 -0
- package/dist/server/src/projects.js +154 -0
- package/dist/server/src/settings-page.d.ts +9 -0
- package/dist/server/src/settings-page.js +93 -0
- package/dist/server/src/settings.d.ts +23 -0
- package/dist/server/src/settings.js +72 -0
- package/dist/server/src/site.d.ts +15 -0
- package/dist/server/src/site.js +78 -0
- package/dist/server/src/store-api.d.ts +28 -0
- package/dist/server/src/store-api.js +180 -0
- package/dist/server/src/validate.d.ts +71 -0
- package/dist/server/src/validate.js +197 -0
- package/dist/vitest/src/index.d.ts +27 -5
- package/dist/vitest/src/index.js +18 -5
- package/dist/webdriver/src/driver.d.ts +63 -11
- package/dist/webdriver/src/driver.js +57 -6
- package/dist/webdriver/src/index.d.ts +8 -0
- package/dist/webdriver/src/index.js +1 -0
- package/dist/webdriver/src/protocol.d.ts +75 -6
- package/dist/webdriver/src/protocol.js +79 -6
- package/docs/agents.md +137 -0
- package/docs/deploying.md +345 -0
- package/docs/dogfooding.md +175 -0
- package/docs/extending.md +242 -0
- package/docs/integrating.md +485 -0
- package/docs/reference/bun.md +141 -0
- package/docs/reference/cli.md +148 -0
- package/docs/reference/core.md +2432 -0
- package/docs/reference/detox.md +150 -0
- package/docs/reference/http-api.md +799 -0
- package/docs/reference/playwright.md +303 -0
- package/docs/reference/reports.md +7152 -0
- package/docs/reference/runners.md +169 -0
- package/docs/reference/schema.md +1762 -0
- package/docs/reference/server.md +825 -0
- package/docs/reference/vitest.md +45 -0
- package/docs/reference/webdriver.md +330 -0
- package/docs/report-backends.md +144 -0
- package/docs/report-contract.md +400 -0
- package/docs/reporting-issues.md +160 -0
- package/docs/runners.md +69 -0
- package/docs/server.md +321 -0
- package/docs/statecharts.md +643 -0
- package/llms-full.txt +4114 -0
- package/llms.txt +49 -0
- package/package.json +61 -11
- package/packages/core/README.md +2 -1
- package/packages/reports/README.md +65 -0
- package/packages/reports/STORAGE.md +4 -0
- package/packages/runners/README.md +6 -0
- package/packages/runners/compat/codecept.cjs +2 -0
- package/packages/runners/compat/jest.cjs +2 -0
- package/packages/runners/compat/mocha.cjs +2 -0
- package/packages/schema/README.md +14 -0
- package/packages/schema/schemas/atlas-change.schema.json +4 -0
- package/packages/schema/schemas/check-detail.schema.json +1032 -0
- package/packages/schema/schemas/checks-result.schema.json +26 -0
- package/packages/schema/schemas/command-error.schema.json +35 -0
- package/packages/schema/schemas/doctor-result.schema.json +60 -0
- package/packages/schema/schemas/effective-delta.schema.json +490 -0
- package/packages/schema/schemas/effective-evidence.schema.json +471 -0
- package/packages/schema/schemas/evidence-page.schema.json +271 -0
- package/packages/schema/schemas/hello-event.schema.json +26 -0
- package/packages/schema/schemas/init-plan.schema.json +347 -0
- package/packages/schema/schemas/layer-rows.schema.json +199 -0
- package/packages/schema/schemas/layer.schema.json +2888 -0
- package/packages/schema/schemas/live-run-start.schema.json +42 -0
- package/packages/schema/schemas/live-run-update.schema.json +93 -0
- package/packages/schema/schemas/live-run.schema.json +225 -0
- package/packages/schema/schemas/merge-result.schema.json +40 -0
- package/packages/schema/schemas/outline.schema.json +62 -0
- package/packages/schema/schemas/problem.schema.json +37 -0
- package/packages/schema/schemas/project-slug.schema.json +8 -0
- package/packages/schema/schemas/project.schema.json +22 -0
- package/packages/schema/schemas/projects.schema.json +33 -0
- package/packages/schema/schemas/publish-checks.schema.json +1413 -0
- package/packages/schema/schemas/publish-result.schema.json +168 -0
- package/packages/schema/schemas/ready.schema.json +68 -0
- package/packages/schema/schemas/report-event.schema.json +100 -0
- package/packages/schema/schemas/report-status.schema.json +370 -0
- package/packages/schema/schemas/server-config.schema.json +208 -0
- package/packages/schema/schemas/server-editable-settings.schema.json +132 -0
- package/packages/schema/schemas/server-info.schema.json +114 -0
- package/packages/schema/schemas/server-settings-snapshot.schema.json +285 -0
- package/packages/schema/schemas/spec-set.schema.json +103 -0
- package/packages/schema/schemas/store-listing.schema.json +29 -0
- package/packages/schema/schemas/store-write-result.schema.json +28 -0
- package/packages/schema/schemas/stream-result.schema.json +59 -0
- package/packages/server/README.md +43 -0
- package/packages/server/openapi.json +11021 -0
- package/packages/visualizer/README.md +32 -11
- package/packages/visualizer/bin/atlas-client.mjs +176 -0
- package/packages/visualizer/bin/atlas-visualizer.mjs +2 -175
- package/packages/visualizer/src/app/AppShell.tsx +32 -16
- package/packages/visualizer/src/app/report-sources.tsx +7 -4
- package/packages/visualizer/src/app/router.tsx +3 -3
- package/packages/visualizer/src/components/ActivityIndicator.module.css +4 -0
- package/packages/visualizer/src/components/ActivityIndicator.tsx +6 -0
- package/packages/visualizer/src/components/Header.module.css +101 -192
- package/packages/visualizer/src/components/Header.tsx +88 -13
- package/packages/visualizer/src/components/ProjectPicker.tsx +64 -0
- package/packages/visualizer/src/data/adapters/adapter.ts +5 -17
- package/packages/visualizer/src/data/adapters/index.ts +10 -1
- package/packages/visualizer/src/data/adapters/report-backend.test.ts +3 -2
- package/packages/visualizer/src/data/adapters/report-backend.ts +1 -1
- package/packages/visualizer/src/data/queries.ts +14 -7
- package/packages/visualizer/src/evidence/api.ts +16 -3
- package/packages/visualizer/src/evidence/artifacts.module.css +213 -0
- package/packages/visualizer/src/evidence/artifacts.tsx +272 -0
- package/packages/visualizer/src/evidence/check-detail.tsx +21 -4
- package/packages/visualizer/src/evidence/document-page.tsx +6 -2
- package/packages/visualizer/src/evidence/evidence-context.tsx +79 -12
- package/packages/visualizer/src/evidence/evidence.module.css +11 -1
- package/packages/visualizer/src/evidence/feature-page.tsx +7 -3
- package/packages/visualizer/src/evidence/model-page.tsx +6 -2
- package/packages/visualizer/src/evidence/project-home.tsx +45 -0
- package/packages/visualizer/src/evidence/recording-page.tsx +4 -1
- package/packages/visualizer/src/evidence/spec-index.tsx +2 -1
- package/packages/visualizer/src/evidence/spec-page.tsx +23 -16
- package/packages/visualizer/src/evidence/test-filter.tsx +21 -0
- package/packages/visualizer/src/find/Finder.tsx +1 -7
- package/packages/visualizer/src/find/open.ts +4 -0
- package/packages/visualizer/src/live/live-query.ts +21 -0
- package/packages/visualizer/src/live/live-runs.tsx +69 -0
- package/packages/visualizer/src/live/live-stream.ts +225 -0
- package/packages/visualizer/src/live/report-progress.ts +62 -0
- package/packages/visualizer/src/live/test-progress.tsx +34 -0
- package/packages/visualizer/src/runtime.ts +35 -0
- package/packages/visualizer/src/state/ui-store.ts +3 -2
- package/packages/visualizer/src/views/ChartPage.tsx +2 -0
- package/packages/visualizer/src/views/ChartTests.tsx +43 -0
- package/packages/visualizer/src/views/SidePanel.tsx +2 -0
- package/packages/visualizer/vite/atlas-files.test.ts +4 -4
- package/packages/visualizer/vite/atlas-files.ts +1 -5
- package/packages/visualizer/vite/atlas-server-proxy.ts +37 -0
- package/packages/visualizer/vite.config.ts +11 -3
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# The report contract
|
|
2
|
+
|
|
3
|
+
This is the normative description of what Atlas reads and writes when it reports on specs of any
|
|
4
|
+
kind: Gherkin features, Quint models, DMN tables, Alloy structures, OpenSLO objectives, statecharts,
|
|
5
|
+
unit tests, linters, anything that ends in "this check passed or failed". If this page and the code
|
|
6
|
+
disagree, that is a bug: [file it](reporting-issues.md).
|
|
7
|
+
|
|
8
|
+
The contract is small on purpose. It is one document (the **layer**), one rule (how layers compose),
|
|
9
|
+
and one interface (the **backend** that stores them). Everything else, the client, the gate, the CLI,
|
|
10
|
+
is built on those three and can be replaced.
|
|
11
|
+
|
|
12
|
+
- [Concepts](#concepts)
|
|
13
|
+
- [The layer document](#the-layer-document)
|
|
14
|
+
- [How layers compose](#how-layers-compose)
|
|
15
|
+
- [Guarantees](#guarantees)
|
|
16
|
+
- [Statuses and the gate](#statuses-and-the-gate)
|
|
17
|
+
- [Backends](#backends)
|
|
18
|
+
- [Where bytes go](#where-bytes-go)
|
|
19
|
+
- [Versioning and stability](#versioning-and-stability)
|
|
20
|
+
- [Failure behaviour](#failure-behaviour)
|
|
21
|
+
- [Speed](#speed)
|
|
22
|
+
- [Other documents of the contract](#other-documents-of-the-contract)
|
|
23
|
+
|
|
24
|
+
## Concepts
|
|
25
|
+
|
|
26
|
+
| Term | Meaning |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| **Check** | One thing a producer verified, with a stable `id` and a status: `passed`, `failed`, `running` or `not-run`. |
|
|
29
|
+
| **Layer** | One focused recording: the checks one **producer** ran, on one **environment**, from one version and branch, at one time. Immutable, addressed by its content. |
|
|
30
|
+
| **Producer** | A stable name for the suite or tool that makes layers: `gherkin`, `web-e2e`, `quint`, `openslo`. |
|
|
31
|
+
| **Environment** | The client that was checked: `desktop-web`, `mobile-web`, `ios`, `android`, or any other lowercase name. |
|
|
32
|
+
| **Slot** | The cell a check fills: producer, kind, spec, check id, environment and parameters. |
|
|
33
|
+
| **Backend** | A store that holds layers. Any [`ObjectStore`](#backends): a directory, a bucket, a device lab. |
|
|
34
|
+
| **Report** | The result of laying every layer of every backend over the current specs. Computed, never stored. |
|
|
35
|
+
|
|
36
|
+
Two ideas follow, and the rest of this page is their consequences.
|
|
37
|
+
|
|
38
|
+
1. **A report is a function of the set of layers.** There is no "the run". Nothing partitions a
|
|
39
|
+
report by run, commit, branch, machine or backend; those are provenance written on each layer.
|
|
40
|
+
2. **Partial runs are the normal way to build a report.** A node that runs one shard, a branch that
|
|
41
|
+
re-runs one scenario, a device lab that checks one environment: each publishes the layer of what it
|
|
42
|
+
ran. The report fills in as layers arrive, and no node needs to know about any other.
|
|
43
|
+
|
|
44
|
+
## The layer document
|
|
45
|
+
|
|
46
|
+
`layers/manifests/<id>.json`, schema version **1**. The JSON Schema (draft 2020-12) is shipped as
|
|
47
|
+
[`@crvouga/atlas/schemas/layer.schema.json`](../packages/schema/schemas/layer.schema.json), and the
|
|
48
|
+
Zod schema as `LayerDocumentSchema` from `@crvouga/atlas/schema`.
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"schemaVersion": 1,
|
|
53
|
+
"id": "9f2c…64 hex digits",
|
|
54
|
+
"producer": "gherkin",
|
|
55
|
+
"recordedAtMs": 1760000000000,
|
|
56
|
+
"sha": "0123456789abcdef0123456789abcdef01234567",
|
|
57
|
+
"branch": "main",
|
|
58
|
+
"runUrl": "https://ci.example.com/runs/42",
|
|
59
|
+
"environment": "ios",
|
|
60
|
+
"parameters": { "device": "iphone-15" },
|
|
61
|
+
"specs": [{ "path": "specs/join.feature", "domain": "list", "kind": "gherkin", "title": "Join a list", "fingerprint": "13:1a2b3c:4d5e6f" }],
|
|
62
|
+
"parts": [{
|
|
63
|
+
"id": "gherkin", "kind": "behavior", "title": "Gherkin", "recordedAtMs": 1760000000000, "sha": "0123…",
|
|
64
|
+
"checks": [
|
|
65
|
+
{ "id": "specs/join.feature > Joins", "title": "Joins", "status": "passed", "detail": "", "specPath": "specs/join.feature", "measurements": [], "durationMs": 120 },
|
|
66
|
+
{ "id": "specs/join.feature > Leaves", "title": "Leaves", "status": "failed", "detail": "expected 2 members, saw 3", "specPath": "specs/join.feature", "measurements": [{ "name": "latency", "value": 1400, "unit": "ms", "limit": 2500 }] }
|
|
67
|
+
]
|
|
68
|
+
}],
|
|
69
|
+
"source": null,
|
|
70
|
+
"recording": null,
|
|
71
|
+
"bundle": {}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Field | Rule |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| `schemaVersion` | `1`. A layer without it, written before it existed, is version 1. |
|
|
78
|
+
| `id` | 64 lowercase hex digits: the SHA-256 of this document without `id`. Opaque to readers. The same checks recorded the same way give the same id, so publishing twice is harmless. |
|
|
79
|
+
| `producer` | Required, non-empty. Part of the [slot](#how-layers-compose). |
|
|
80
|
+
| `recordedAtMs` | When the checks ran, epoch milliseconds, `>= 0`. The newest completed result wins its slot. Take it from the test run, never from the moment of publishing, or a retried publish would claim to be newer than a later run. |
|
|
81
|
+
| `sha`, `branch`, `runUrl` | Provenance, or `null`. **Never part of the slot.** |
|
|
82
|
+
| `environment` | The client checked, or absent. Normalised to a lowercase slug: `iOS` → `ios`, `Desktop Web` → `desktop-web`, `iphone` → `ios`, `mobile browser` → `mobile-web`. Any other name is kept. Part of the slot. |
|
|
83
|
+
| `parameters` | Other string choices that make a result its own slot, such as `{ "device": "iphone-15" }`. A parameter named `environment` is read as the environment. Part of the slot. |
|
|
84
|
+
| `freshness` | `modified`: recorded from a checkout with uncommitted changes. `unknown`: origin not captured. Advisory only; see [Statuses](#statuses-and-the-gate). |
|
|
85
|
+
| `specs` | The specs the layer was recorded against, with a `fingerprint` of their text, so a reader can warn when a spec changed since. Optional. |
|
|
86
|
+
| `parts[].kind` | An open category (`behavior`, `performance`, `accessibility`, …). A new kind needs no change to any reader. Part of the slot. |
|
|
87
|
+
| `parts[].checks[]` | `id` (required, stable), `title`, `status`, `detail`, `specPath`, `measurements`, `durationMs`. |
|
|
88
|
+
| `tags`, `labels`, `links`, `attachments`, `annotations`, `extensions` | Evidence, on the layer, a part or a check: what a result carries beyond its outcome. All optional and open. See [evidence](#evidence) and [the guide](extending.md). |
|
|
89
|
+
| `checks[].steps`, `checks[].attempts` | A check's timeline, and every try when it was retried. Optional. |
|
|
90
|
+
| `checks[].specPath` | The spec the check belongs to, as `specs/<path inside the specs directory>`. Anything before the first `specs/` is dropped, so `packages/app/specs/join.feature` and `specs/join.feature` are the same spec. |
|
|
91
|
+
| `measurements[]` | `{ name, value, unit, limit? }`, finite numbers. A measurement over its `limit` is shown, and never fails the check by itself. |
|
|
92
|
+
| `source`, `recording`, `bundle` | Optional timelines and captured files (screenshots, frames) a suite recorded. `null` and `{}` for a layer of plain checks. |
|
|
93
|
+
|
|
94
|
+
**Unknown fields are allowed and preserved.** Every object in the schema is loose. A later minor
|
|
95
|
+
version may add fields; an older reader ignores them and a copy carries them along.
|
|
96
|
+
|
|
97
|
+
### Evidence
|
|
98
|
+
|
|
99
|
+
A check, a part and a layer may carry evidence beyond their outcome. It is the part of the format meant to grow:
|
|
100
|
+
every field is optional, every object is open, every vocabulary is an open string, and none of it ever decides
|
|
101
|
+
a result. [Evidence: attachments, timelines, snapshots and everything else](extending.md) is the guide; the rules
|
|
102
|
+
are these.
|
|
103
|
+
|
|
104
|
+
| Field | Contents |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `attachments[]` | `{ name, role?, contentType?, bundleKey? \| uri? \| text?, bytes?, sha256?, width?, height?, durationMs?, description?, at?, poster?, captions?, id?, extensions? }`. A screenshot, a video, a trace, a log, a DOM snapshot, a HAR, anything. `bundleKey` is a key in the layer's `bundle` (`attachments/<sha256>`); `uri` is elsewhere; `text` is a short inline value. |
|
|
107
|
+
| `steps[]` | `{ id?, parentId?, name, kind?, status?, offsetMs?, durationMs?, detail?, attachments?, annotations?, extensions? }`. A flat, ordered timeline, nested by `parentId`. |
|
|
108
|
+
| `annotations[]` | `{ type, message, level?, at?, source?, links?, extensions? }`. |
|
|
109
|
+
| `attempts[]` | `{ index, status, durationMs?, startedAtMs?, detail?, steps?, attachments?, annotations?, extensions? }`. |
|
|
110
|
+
| `tags[]`, `labels{}`, `links[]` | Facts to filter by. `labels` are facts about the result; unlike `parameters` they never make it a different slot. |
|
|
111
|
+
| `extensions{}` | Structured data under a name the producer owns (`com.example.coverage`). |
|
|
112
|
+
|
|
113
|
+
The rules, which hold for every version of the format:
|
|
114
|
+
|
|
115
|
+
1. A new field is **optional**. No field is ever made required, renamed, removed or given a new meaning.
|
|
116
|
+
2. **Every object is open.** Unknown fields are kept at every level, and a copy carries them.
|
|
117
|
+
3. **Vocabularies are open.** `role`, `kind`, `type`, `level` and a step's `status` are strings with conventional
|
|
118
|
+
values; an unknown one is shown generically, never rejected.
|
|
119
|
+
4. **Only `status`, `freshness` and `schemaVersion` are closed.** They are the whole of what decides a result.
|
|
120
|
+
5. **Evidence never decides a result.** A reader that cannot read a piece of evidence drops that piece and keeps
|
|
121
|
+
the check, its status and its place in the report.
|
|
122
|
+
6. A file is stored once, in the layer, by content: `attachments/<sha256>` in `layers/blobs/`. Identical files
|
|
123
|
+
attached anywhere in a layer share it, and the layer's id still depends only on what was recorded.
|
|
124
|
+
7. A path inside a report is data from a test run. A publisher reads the files it names only from the report's own
|
|
125
|
+
folder and from folders the person chose, never a hidden file or a link out.
|
|
126
|
+
8. Attachment bytes are untrusted. They are served with the type the producer gave (when it is a well-formed media
|
|
127
|
+
type), never sniffed, under a sandboxing content-security policy, with `cross-origin-resource-policy:
|
|
128
|
+
same-origin`, and a `uri` is followed only if it is `http` or `https`.
|
|
129
|
+
|
|
130
|
+
### Choosing a check id
|
|
131
|
+
|
|
132
|
+
The check `id` is the one thing only the producer can get right, and everything depends on it: the
|
|
133
|
+
newer result replaces the older one only if both used the same id.
|
|
134
|
+
|
|
135
|
+
- Make it **stable** across runs: derive it from the check's identity (file, suite, name), never from
|
|
136
|
+
an index, a timestamp, a random seed or a path's position in a plan.
|
|
137
|
+
- Make it **unique** within the layer. Publishing refuses a layer with a repeated id. When importing
|
|
138
|
+
CTRF or JUnit, a repeated id gets `#2`, `#3`, … so no check is silently counted as another.
|
|
139
|
+
- Keep it **human**. It is what the gate prints.
|
|
140
|
+
- Changing an id retires the old check: its last result stays in the report until the layers that
|
|
141
|
+
hold it are left out. Rename deliberately.
|
|
142
|
+
|
|
143
|
+
Atlas's own importers build ids this way:
|
|
144
|
+
|
|
145
|
+
| Source | Check id | `specPath` |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| CTRF | `filePath > suite… > name` (parts that exist) | `filePath`, when present |
|
|
148
|
+
| JUnit XML | `file or classname > name` | the `file` attribute, when present |
|
|
149
|
+
| Atlas run (`manifest.json`) | the path's `key`, which the same start and events give in every run | the root chart's file |
|
|
150
|
+
| `publishChecks` / `--checks` | whatever you give | whatever you give |
|
|
151
|
+
|
|
152
|
+
## How layers compose
|
|
153
|
+
|
|
154
|
+
A **slot** is the tuple
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
(producer, kind, specPath, check id, environment, parameters)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
with `parameters` compared as sorted key/value pairs. Branch, commit, backend, layer id and run are
|
|
161
|
+
**not** in the slot. Each slot shows exactly one result: the winner among every layer that filled it.
|
|
162
|
+
|
|
163
|
+
The winner is decided by these rules, in order:
|
|
164
|
+
|
|
165
|
+
1. A **completed** result (`passed` or `failed`) beats an **unfinished** one (`running` or `not-run`),
|
|
166
|
+
whatever their times. An unfinished layer never erases a completed outcome.
|
|
167
|
+
2. Between results of the same completeness, the **newer** `recordedAtMs` wins.
|
|
168
|
+
3. At the same time, **`failed` beats `passed`**, and `running` beats `not-run`. A tie fails.
|
|
169
|
+
4. At the same status, the greater `layerId|backendId` wins, so no input order can change the answer.
|
|
170
|
+
|
|
171
|
+
Consequences you can rely on:
|
|
172
|
+
|
|
173
|
+
- Desktop web, mobile web, iOS and Android results of the same check sit side by side.
|
|
174
|
+
- A layer that ran one scenario leaves every other scenario as the newest layer that ran it.
|
|
175
|
+
- Re-running a failing check on any branch and passing replaces the failure. Re-running and failing
|
|
176
|
+
replaces the pass.
|
|
177
|
+
- A spec in the current specs with no layer at all stays visible as having no results. A spec that
|
|
178
|
+
was removed keeps its evidence, outside the outline.
|
|
179
|
+
- An immutable layer held by several backends is **one** layer, reported by the backend whose id sorts
|
|
180
|
+
first.
|
|
181
|
+
|
|
182
|
+
Leaving a layer, backend, environment, branch or version out of the input is how earlier outcomes are
|
|
183
|
+
inspected.
|
|
184
|
+
|
|
185
|
+
### What takes part
|
|
186
|
+
|
|
187
|
+
By default **every layer takes part**, wherever it was recorded: that is what a unified report is. The
|
|
188
|
+
publisher records where it came from, and the reader chooses what to include:
|
|
189
|
+
|
|
190
|
+
- `freshness` is set by the publisher from git: `modified` when the worktree has uncommitted edits to
|
|
191
|
+
tracked files, `unknown` outside git, and absent for a CI checkout or a clean worktree at its commit.
|
|
192
|
+
Untracked files do not count. A modified layer takes part with a warning and is never mistaken for the
|
|
193
|
+
commit's own result.
|
|
194
|
+
- `atlas report status` and `atlas serve` (and `GET /api/status?branch=&ignoreModified=1` on a server) take `--branch <name>` (repeatable) and `--ignore-modified`
|
|
195
|
+
(`ATLAS_ONLY_BRANCH`, `ATLAS_IGNORE_MODIFIED`). They only choose which layers are read; the rules above are
|
|
196
|
+
unchanged. A pull request's gate is `--branch "$PR_BRANCH" --branch main --ignore-modified`: the branch
|
|
197
|
+
laid over `main`, so what it did not re-run is inherited.
|
|
198
|
+
|
|
199
|
+
## Guarantees
|
|
200
|
+
|
|
201
|
+
These are tested (`packages/reports/tests/composition-laws.test.ts`, over random partial runs) and
|
|
202
|
+
are part of the contract:
|
|
203
|
+
|
|
204
|
+
| Guarantee | Meaning |
|
|
205
|
+
| --- | --- |
|
|
206
|
+
| **Order independence** | The report does not depend on the order backends or layers are read in. |
|
|
207
|
+
| **Partition independence** | Splitting the same layers across any number of backends, machines or branches, with any overlap, gives the same report. This is what makes partial runs on separate nodes safe. |
|
|
208
|
+
| **Idempotence** | A layer present twice, in one backend or several, counts once. Publishing the same checks again writes the same layer. |
|
|
209
|
+
| **Monotonic** | A layer changes only the slots it fills. Adding a layer never changes a result it did not record. |
|
|
210
|
+
| **Deletion-free** | Nothing in the contract removes or rewrites a layer. Retention is the operator's choice. |
|
|
211
|
+
| **Unknown is not a pass** | A layer that cannot be read, a backend that is down, and a check that is `running` or `not-run` never count as passing. The gate fails closed. |
|
|
212
|
+
| **Aggregation by copying** | Layers are immutable and never share a key with different bytes, so combining stores is copying files (`atlas report merge`, `cp -R`, `rsync`, a CI artifact download). Copying is idempotent and commutative. |
|
|
213
|
+
|
|
214
|
+
## Statuses and the gate
|
|
215
|
+
|
|
216
|
+
| Status | Meaning | Counts as |
|
|
217
|
+
| --- | --- | --- |
|
|
218
|
+
| `passed` | The check ran and its expectation held. | Pass |
|
|
219
|
+
| `failed` | The check ran and its expectation did not hold. | Fail |
|
|
220
|
+
| `running` | The check has started and not finished. | Not done: fails the gate |
|
|
221
|
+
| `not-run` | The check was skipped, pending, blocked, or never reached. | Nothing: never a pass, never a failure |
|
|
222
|
+
|
|
223
|
+
Tools map to these four. CTRF `skipped`, `pending` and `other`, and JUnit `<skipped>`, are `not-run`.
|
|
224
|
+
An Atlas path that passed on retry (`flaky`) is `passed`, with the detail "Passed on retry (flaky)".
|
|
225
|
+
|
|
226
|
+
Timings that only qualify a check (parts of kind `performance`) are not counted as checks when
|
|
227
|
+
anything else is recorded. A measurement over its allowance is reported and never fails a check.
|
|
228
|
+
|
|
229
|
+
**Freshness never changes a status.** A layer whose spec fingerprint no longer matches, whose
|
|
230
|
+
checkout was modified, or whose related code changed still shows its recorded outcome, with a
|
|
231
|
+
warning ("Potentially outdated: spec changed"). Atlas favours quick, possibly stale evidence over
|
|
232
|
+
none, and never invents a result.
|
|
233
|
+
|
|
234
|
+
### `atlas report status`
|
|
235
|
+
|
|
236
|
+
The gate passes (exit 0) only when **all** of these hold:
|
|
237
|
+
|
|
238
|
+
- at least one check has completed (`passed` or `failed`): a report where everything was skipped has
|
|
239
|
+
no evidence;
|
|
240
|
+
- no slot's winning result is `failed`;
|
|
241
|
+
- no slot's winning result is `running`;
|
|
242
|
+
- every backend and every layer could be read (a notice is a failure);
|
|
243
|
+
- every environment named by `--require-environments` has at least one check;
|
|
244
|
+
- with `--require-all-specs`, every spec in `--specs <dir>` has at least one result.
|
|
245
|
+
|
|
246
|
+
Exit codes: `0` the report passes, `1` it does not, `2` the command itself is wrong (a store
|
|
247
|
+
directory that does not exist, a missing flag). A CI job can tell a broken invocation from a red report.
|
|
248
|
+
|
|
249
|
+
`--format json` prints a [`ReportStatus`](../packages/schema/schemas/report-status.schema.json)
|
|
250
|
+
(`schemaVersion: 1`): `ok`, `reasons`, `checks`, `byEnvironment`, `layers`, `backends`, `notices`,
|
|
251
|
+
`specsWithoutEvidence`, `specs` (each spec's counts, per environment) and `failing`. The text and markdown formats are for people and are not a
|
|
252
|
+
contract; parse the JSON.
|
|
253
|
+
|
|
254
|
+
## Backends
|
|
255
|
+
|
|
256
|
+
A backend is any implementation of `ObjectStore` (`@crvouga/atlas/reports/object-store`), seven
|
|
257
|
+
async methods over keys and bytes:
|
|
258
|
+
|
|
259
|
+
| Method | Rule |
|
|
260
|
+
| --- | --- |
|
|
261
|
+
| `get(key)` | The object with its `contentType` and `size`, or `null` when missing. Transport errors throw. |
|
|
262
|
+
| `put(key, bytes, contentType)` | Idempotent: writing a key twice overwrites without error. The content type round-trips. |
|
|
263
|
+
| `head(key)` | `true`/`false`. Never throws for a missing key. |
|
|
264
|
+
| `delete(key)`, `deleteMany(keys)` | A missing key is a no-op. |
|
|
265
|
+
| `getUri(key)` | A URL the host can load directly, or `null`. |
|
|
266
|
+
| `listKeys(prefix?)` | Keys in code-unit order, optionally filtered by prefix. |
|
|
267
|
+
| `withPrefix(prefix)` | A store scoped to a prefix. Keys relative to it. Prefixes compose. |
|
|
268
|
+
|
|
269
|
+
It needs nothing else: no transactions, no rename, no locks, no conditional writes. That is what
|
|
270
|
+
lets a plain bucket, a directory and a device lab compose.
|
|
271
|
+
|
|
272
|
+
Atlas ships two backends, both named by one URL (`openStore`, `--store`, `ATLAS_STORE`):
|
|
273
|
+
|
|
274
|
+
- `directoryStore(dir)` (`@crvouga/atlas/reports/directory-store`): atomic writes, for a CI workspace, a
|
|
275
|
+
mount or a laptop.
|
|
276
|
+
- `s3Store({ bucket, prefix, region, endpoint })` (`@crvouga/atlas/reports/s3-store`): AWS S3 and every store
|
|
277
|
+
that speaks its protocol, such as R2 and MinIO, written without an SDK. `s3://bucket/folder?region=…&endpoint=…`.
|
|
278
|
+
Requests are signed with Signature Version 4, retried with backoff on throttling and server errors,
|
|
279
|
+
capped in flight, and follow a bucket's region. Credentials are never in a URL: they come from the
|
|
280
|
+
environment the way an AWS SDK finds them. It is tested against AWS's published signing vectors and a
|
|
281
|
+
live S3 server in CI. On S3 a missing object answers 403 instead of 404 for an account that cannot list
|
|
282
|
+
the bucket, so publishers need `s3:ListBucket` too (`atlas report policy` prints the permissions).
|
|
283
|
+
|
|
284
|
+
For anything else, write an adapter and prove it:
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
import { verifyObjectStore } from '@crvouga/atlas/reports/object-store-conformance';
|
|
288
|
+
|
|
289
|
+
const { ok, failures } = await verifyObjectStore(myS3Store); // writes under a scratch prefix, cleans up
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Several backends are one report: pass them all to `combineBackends`, to the client
|
|
293
|
+
(`reportsHost`), or to the CLI (`--store` for directories, `--backends <module>` for the rest). A
|
|
294
|
+
backend that cannot be reached is named in the notices and leaves the others usable; asking again
|
|
295
|
+
retries it.
|
|
296
|
+
|
|
297
|
+
## Where bytes go
|
|
298
|
+
|
|
299
|
+
All keys are relative to the backend. Layers are written **bottom up**, so a reader never meets an
|
|
300
|
+
entry whose content has not arrived:
|
|
301
|
+
|
|
302
|
+
A layer's checks are the contract. Next to them the store holds the two other things a whole project
|
|
303
|
+
needs, written the same way (content first, catalog entry last, nothing overwritten):
|
|
304
|
+
|
|
305
|
+
- **Spec sets** (`layers/specs/…`): the specs of one commit, so a client needs no checkout. A spec set is
|
|
306
|
+
`{ schemaVersion, id, branch, sha, recordedAtMs, freshness?, files: [{ path, digest, fingerprint, kind,
|
|
307
|
+
title, domain, bytes }] }` ([`spec-set.schema.json`](../packages/schema/schemas/spec-set.schema.json)). Its
|
|
308
|
+
id is the digest of the branch, commit and file digests, so one commit's specs are one set however many
|
|
309
|
+
nodes publish them. Bodies are `layers/specs/blobs/<sha256>.txt`, shared by every set that holds them.
|
|
310
|
+
The outline a report is laid over is the **newest set from `main`** (then `master`, then the newest);
|
|
311
|
+
a set from a modified checkout is used only if no committed set exists.
|
|
312
|
+
- **Run bundles** (`layers/runs/<run>/…` and `layers/runs/index/…`): a finished statechart run with its
|
|
313
|
+
screenshots and clips, for the client. Uploaded only when the run's privacy scan passed; the manifest is
|
|
314
|
+
written last, then the catalog entry.
|
|
315
|
+
|
|
316
|
+
The keys of a layer, bottom up:
|
|
317
|
+
|
|
318
|
+
1. `layers/blobs/<sha256>.gz`: recorded files (screenshots, frames), content-addressed and shared
|
|
319
|
+
between layers. Skipped entirely for a layer of plain checks.
|
|
320
|
+
2. `layers/manifests/<id>.json`: the layer document, written once.
|
|
321
|
+
3. `layers/index/<inverted-time>-<id>.json`: `{"id": "<id>"}`, the catalog entry, written last. The
|
|
322
|
+
time is inverted so a listing is newest first.
|
|
323
|
+
|
|
324
|
+
Two producers never write different bytes to one key: every key is derived from content. A crash
|
|
325
|
+
between steps leaves unreferenced blobs, never a catalog entry without its layer.
|
|
326
|
+
|
|
327
|
+
Everything under `layers/` is immutable and addressed by content, so `copyStore` and `atlas report merge`
|
|
328
|
+
carry spec sets and runs along with layers.
|
|
329
|
+
|
|
330
|
+
Stores written before layers existed (`commits/<sha>/…`, `versions/…`, `index/…`) are read in place
|
|
331
|
+
and composed with layers; Atlas never rewrites them. `copyStore` and `atlas report merge` copy
|
|
332
|
+
`layers/` only, because commit-keyed objects are mutable.
|
|
333
|
+
|
|
334
|
+
## Versioning and stability
|
|
335
|
+
|
|
336
|
+
- `schemaVersion` is the **major** version of the layer document. This is version 1.
|
|
337
|
+
- Within a version, changes are **additive**: a new optional field, a new open `kind`. Readers ignore
|
|
338
|
+
unknown fields, so an older Atlas reads a newer minor version.
|
|
339
|
+
- The closed vocabularies, `status` and `freshness`, change only with a new major version. A reader
|
|
340
|
+
never has to guess what an unknown status means.
|
|
341
|
+
- A reader reads every version **at or below its own**. A layer of a newer major version is refused by
|
|
342
|
+
name ("Written with layer schema version 2; … Upgrade @crvouga/atlas") and shows up as a notice. It
|
|
343
|
+
is never half understood and never counted as a pass.
|
|
344
|
+
- A breaking change to the document, to the [slot](#how-layers-compose) or to the
|
|
345
|
+
[winner rules](#how-layers-compose) is a major version of the contract **and** a major release of
|
|
346
|
+
`@crvouga/atlas` (a `!` commit). It also ships a migration note.
|
|
347
|
+
- Adding evidence (a new optional field, a new open vocabulary value, a new extension namespace) is a minor
|
|
348
|
+
change and needs no new `schemaVersion`. `packages/reports/tests/fixtures/layer-v1-extended.json` carries every
|
|
349
|
+
kind of evidence, and `layer-extensibility.test.ts` proves unknown fields survive at every level and that a
|
|
350
|
+
reader of the first version of the format still reads it.
|
|
351
|
+
- The contract is guarded by `packages/reports/tests/fixtures/layer-v1.json`, a layer that must keep
|
|
352
|
+
parsing, and by the emitted JSON Schemas, which a test keeps equal to the Zod schemas. **Never edit
|
|
353
|
+
the fixture to make a test pass.**
|
|
354
|
+
|
|
355
|
+
## Failure behaviour
|
|
356
|
+
|
|
357
|
+
| What happens | What Atlas does |
|
|
358
|
+
| --- | --- |
|
|
359
|
+
| A backend is unreachable | Named in `notices` and in the backend list as unavailable; every other backend is used. The gate fails. |
|
|
360
|
+
| A layer is not JSON, fails the schema, or is a newer major version | Skipped with a notice naming the layer and why. The gate fails. |
|
|
361
|
+
| A catalog entry names a layer that is missing | A notice; the gate fails. |
|
|
362
|
+
| Two layers disagree | The [winner rules](#how-layers-compose) decide, the same way everywhere. |
|
|
363
|
+
| A publish is interrupted | Unreferenced blobs may remain. No partial layer is ever visible. Publish again. |
|
|
364
|
+
| A publish is retried | The same layer; nothing changes. |
|
|
365
|
+
| Two nodes publish at once | They write different keys, or identical bytes to the same key. |
|
|
366
|
+
| A required field is missing at publish | `publishChecks` throws, naming each problem by its path. Nothing is written. |
|
|
367
|
+
| A check id repeats within a layer | `publishChecks` throws. Importers number repeats (`#2`). |
|
|
368
|
+
|
|
369
|
+
## Speed
|
|
370
|
+
|
|
371
|
+
- Publishing a layer of plain checks is one `head` and two small writes.
|
|
372
|
+
- A report is one linear pass over the checks of every layer. Reading dominates it: each layer is
|
|
373
|
+
one catalog read and one manifest read, a few at a time (16 by default, 64 for a node on S3).
|
|
374
|
+
- A long-lived reader does not redo that pass. `ReportIndex` reads each immutable layer once, folds it into
|
|
375
|
+
the winning result of every slot it fills, and drops it unless it still holds a winner, so memory follows
|
|
376
|
+
the number of checks (plus a few bytes for each layer ever read), not the age of the project, and a refresh
|
|
377
|
+
with nothing new is one request for the newest page of the catalog. Folding is exact in any order because the winner
|
|
378
|
+
rule is a total order; a test proves the incremental report equals combining every layer from scratch.
|
|
379
|
+
The node sends the client only that: one request, only winning rows, with an ETag.
|
|
380
|
+
- Measured on a laptop with a directory backend: 300 layers of 50 checks in about 0.2 s; 1,000 layers
|
|
381
|
+
of 100 checks, each recorded against 1,000 specs (100,000 results), in about 0.9 s. Composing two
|
|
382
|
+
thousand layers of 100 checks (200,000 results) already in memory takes about 0.3 s.
|
|
383
|
+
`performance.test.ts` holds budgets ten times looser, to catch an accidental quadratic step on a
|
|
384
|
+
slow machine.
|
|
385
|
+
- A directory backend lists only the directories a prefix can reach. The client polls a small index,
|
|
386
|
+
reads an immutable layer once and caches it forever, and loads recordings only when opened.
|
|
387
|
+
|
|
388
|
+
## Other documents of the contract
|
|
389
|
+
|
|
390
|
+
| Document | Schema | Purpose |
|
|
391
|
+
| --- | --- | --- |
|
|
392
|
+
| Layer | `layer.schema.json` | What a producer publishes. This page. |
|
|
393
|
+
| Publish checks | `publish-checks.schema.json` | The input of `publishChecks` and `atlas report publish --checks`: a layer without the parts the publisher fills in. |
|
|
394
|
+
| Report status | `report-status.schema.json` | The output of `atlas report status --format json`. |
|
|
395
|
+
| Spec set | `spec-set.schema.json` | The specs of one commit, as published beside the layers. |
|
|
396
|
+
| Run manifest | `manifest.schema.json` | What `atlas run` writes for a statechart run. Publish it as a layer with `--manifest`. |
|
|
397
|
+
| Runs index, sources, change notices | `runs-index`, `report-sources`, `atlas-change` | How the client finds runs. See [report backends](report-backends.md). |
|
|
398
|
+
| CloudEvents | `cloud-event.schema.json` | Business events a run observed. |
|
|
399
|
+
|
|
400
|
+
All of them are JSON Schema 2020-12 and ship in the package at `@crvouga/atlas/schemas/<name>.schema.json`.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Reporting issues
|
|
2
|
+
|
|
3
|
+
How people and coding agents in a project that uses Atlas report a bug or a missing feature. Issues
|
|
4
|
+
are the only way a project changes Atlas: maintainers and agents in this repository pick them up,
|
|
5
|
+
fix them here, and the fix reaches you as a new version ([dogfooding.md](dogfooding.md)).
|
|
6
|
+
|
|
7
|
+
This guide is written for coding agents. Read it top to bottom once, then use
|
|
8
|
+
[Quick reference](#quick-reference) as the checklist every time you file.
|
|
9
|
+
|
|
10
|
+
## Quick reference
|
|
11
|
+
|
|
12
|
+
| You found | Kind | Title | Template |
|
|
13
|
+
| --- | --- | --- | --- |
|
|
14
|
+
| Atlas crashes, gives a wrong result, contradicts its README or docs, or does not install, build or type-check | `bug` | `[<part>] bug: <what breaks>` | [bug.md][t-bug] |
|
|
15
|
+
| Atlas lacks an API, option, driver capability, CLI flag, schema field or visualizer view you need | `feature` | `[<part>] feature: <what is missing>` | [feature.md][t-feature] |
|
|
16
|
+
|
|
17
|
+
`<part>` is the part of `@crvouga/atlas` the issue is about: `core` (the main import and the
|
|
18
|
+
`atlas` command), or the import path after the package name: `playwright`, `bun`, `webdriver`,
|
|
19
|
+
`detox`, `vitest`, `schema`, `reports`; `visualizer` for the `atlas client` command. Use `core`
|
|
20
|
+
when you cannot tell.
|
|
21
|
+
|
|
22
|
+
1. [Search for an existing issue](#1-search-first). Comment on it instead of opening a duplicate.
|
|
23
|
+
2. [Leave out](#never-include) secrets, personal data and anything that identifies your product.
|
|
24
|
+
3. Copy the kind's template, fill in every section, and save it to a file.
|
|
25
|
+
4. File it:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
gh issue create --repo crvouga/atlas \
|
|
29
|
+
--title "[core] bug: plan skips a transition guarded by a parallel region" \
|
|
30
|
+
--label agent-reported,bug \
|
|
31
|
+
--body-file issue.md
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
5. Give your human the issue URL, and note the workaround you are using next to the code it is in.
|
|
35
|
+
|
|
36
|
+
File one issue per bug or missing feature, so each can be fixed, tested and closed on its own. The
|
|
37
|
+
title prefix alone is enough: a workflow applies the `agent-reported` and kind labels from it,
|
|
38
|
+
including when your account cannot set labels.
|
|
39
|
+
|
|
40
|
+
## When to file, and when not to
|
|
41
|
+
|
|
42
|
+
File when:
|
|
43
|
+
|
|
44
|
+
- **bug**: Atlas throws or hangs; lint, plan or a run gives a result the spec does not support;
|
|
45
|
+
a driver taps, types, waits or records differently from what its README says; the manifest or a
|
|
46
|
+
report does not match its JSON Schema; the Atlas client shows something other than what the run
|
|
47
|
+
recorded; the package fails to install, import, build or type-check.
|
|
48
|
+
- **feature**: you need something Atlas does not have: a spec construct, a config option, a driver
|
|
49
|
+
capability, a CLI flag, a field in the manifest, a view in the Atlas client, an export format. Check
|
|
50
|
+
that part's README and `docs/` first.
|
|
51
|
+
|
|
52
|
+
Do not file when:
|
|
53
|
+
|
|
54
|
+
- The cause is your own spec, implementation or configuration: a recogniser that matches the wrong
|
|
55
|
+
screen, a missing `implementation`, state left over from an earlier run. `atlas lint` findings
|
|
56
|
+
about your charts are Atlas working.
|
|
57
|
+
- You are on an old version. Upgrade (`bun update @crvouga/atlas --latest`) and try again first.
|
|
58
|
+
- You only suspect a problem. Reproduce it, and say what you ran and what happened.
|
|
59
|
+
|
|
60
|
+
Never fix Atlas from your project instead of filing: no edits to `node_modules`, no patch, no fork.
|
|
61
|
+
|
|
62
|
+
## Never include
|
|
63
|
+
|
|
64
|
+
Issues are public. Before you file, remove:
|
|
65
|
+
|
|
66
|
+
- API keys, tokens, passwords, cookies and signed URLs. Replace each with `<redacted>`.
|
|
67
|
+
- Real personal data. Use obviously fake values (`jane@example.com`).
|
|
68
|
+
- Your product: its name, real screen and event names, screenshots, clips and run manifests, and
|
|
69
|
+
your project's source. Rename states and events (`Screen A`, `Submits the form`) and reduce the
|
|
70
|
+
spec until it shows only the problem.
|
|
71
|
+
|
|
72
|
+
When you cannot show the problem without something on this list, stop and ask your human.
|
|
73
|
+
|
|
74
|
+
## 1. Search first
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
gh issue list --repo crvouga/atlas --state all --search "<part> <what breaks or is missing> in:title,body"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If an open issue covers the same thing, add a comment with your evidence (versions, reproduction,
|
|
81
|
+
the behavior you need) instead of opening a duplicate. A 👍 on a `feature` issue also counts as
|
|
82
|
+
demand. If a closed issue covers it, check that you are on the version its release comment names,
|
|
83
|
+
or a later one, before you reopen it.
|
|
84
|
+
|
|
85
|
+
## 2. Bugs: reduce to a reproduction
|
|
86
|
+
|
|
87
|
+
A bug report is ready when someone can reproduce it from a clean install without your project.
|
|
88
|
+
|
|
89
|
+
- **Versions.** The exact installed version (`bun pm ls`, or your package manager's equivalent), Bun
|
|
90
|
+
or Node, the driver and its browser or device.
|
|
91
|
+
- **The smallest spec.** One chart with only the states and transitions that show the problem.
|
|
92
|
+
`atlas lint --specs <dir>` needs no config and no implementation; say so when that alone
|
|
93
|
+
reproduces it.
|
|
94
|
+
- **The smallest config and command.** `atlas.config.ts` with a `functionDriver` or `httpDriver`
|
|
95
|
+
when the bug is not about a browser; the exact command line.
|
|
96
|
+
- **Expected and actual.** Quote the README or doc sentence Atlas contradicts. Paste the error and
|
|
97
|
+
stack trace, the lint finding, or the wrong part of the manifest, not the whole file.
|
|
98
|
+
- **Workaround.** What your project does in the meantime, or that you are blocked.
|
|
99
|
+
|
|
100
|
+
## 3. Features: describe the behavior
|
|
101
|
+
|
|
102
|
+
Describe what Atlas should do, not how your project is built.
|
|
103
|
+
|
|
104
|
+
- **What is missing.** What you are trying to specify, run or see, and where Atlas stops.
|
|
105
|
+
- **Proposed surface.** The option, API, spec metadata, CLI flag or view as you would want to use
|
|
106
|
+
it. A short code block is better than a paragraph.
|
|
107
|
+
- **Behaviors.** Numbered Given / When / Then statements, each one checkable by a test in this
|
|
108
|
+
repository, covering the failures as well as the happy path:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
B1. Given a chart with a `<parallel>` state, when I run `atlas plan --state Sync`, then only
|
|
112
|
+
paths that enter the Sync region are planned.
|
|
113
|
+
B2. Given `--state` names a state that does not exist, then the command exits 1 and names the
|
|
114
|
+
states it could have been.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- **Out of scope.** What you do not need, so the feature stays small.
|
|
118
|
+
|
|
119
|
+
A feature with a clear surface and concrete behaviors is ready to build. One that only names a goal
|
|
120
|
+
waits, labelled `needs-info`, until someone supplies them.
|
|
121
|
+
|
|
122
|
+
## 4. File the issue
|
|
123
|
+
|
|
124
|
+
Copy the template for the kind, fill in every section, delete the HTML comments, and save it to a
|
|
125
|
+
file. Then run:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
gh issue create --repo crvouga/atlas \
|
|
129
|
+
--title "<title in the format from the quick reference>" \
|
|
130
|
+
--label agent-reported,<kind> \
|
|
131
|
+
--body-file issue.md
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
| Kind | Template (raw, for copying) |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| `bug` | <https://raw.githubusercontent.com/crvouga/atlas/main/.github/ISSUE_TEMPLATE/bug.md> |
|
|
137
|
+
| `feature` | <https://raw.githubusercontent.com/crvouga/atlas/main/.github/ISSUE_TEMPLATE/feature.md> |
|
|
138
|
+
|
|
139
|
+
Each template begins with a `---` front-matter block; leave it out of the body file.
|
|
140
|
+
|
|
141
|
+
If `gh` is not installed or not authenticated, do not install it or log in on your own. Give your
|
|
142
|
+
human the finished title and body and the link to the matching form, for example
|
|
143
|
+
<https://github.com/crvouga/atlas/issues/new?template=bug.md>.
|
|
144
|
+
|
|
145
|
+
## What happens next
|
|
146
|
+
|
|
147
|
+
Maintainers and agents in this repository work the `agent-reported` queue.
|
|
148
|
+
|
|
149
|
+
- **bug**: they reproduce it, add a failing regression test, fix it, and merge a change that closes
|
|
150
|
+
the issue. If Atlas behaves as documented, they comment with what they observed and close it.
|
|
151
|
+
- **feature**: they settle the surface with you in the comments if it is not clear, then ship it
|
|
152
|
+
with a test for each behavior you listed.
|
|
153
|
+
|
|
154
|
+
An issue labelled `needs-info` is waiting on you: answer the question in the comments.
|
|
155
|
+
|
|
156
|
+
Merging the fix publishes it. The release then comments on the issue with the exact version that
|
|
157
|
+
carries it. Upgrade (`bun update @crvouga/atlas --latest`) and remove your workaround.
|
|
158
|
+
|
|
159
|
+
[t-bug]: https://github.com/crvouga/atlas/blob/main/.github/ISSUE_TEMPLATE/bug.md
|
|
160
|
+
[t-feature]: https://github.com/crvouga/atlas/blob/main/.github/ISSUE_TEMPLATE/feature.md
|
package/docs/runners.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Native test runner reporters
|
|
2
|
+
|
|
3
|
+
Projects upload results to a shared Atlas node under their own project slug. CodeceptJS, Mocha, Jest and Node's test runner have native reporters; other runners can publish their JUnit or CTRF output with `atlas report publish`. All reporters are entry points of the single `@crvouga/atlas` package.
|
|
4
|
+
|
|
5
|
+
## Configure the project once
|
|
6
|
+
|
|
7
|
+
Set these in the test process, locally or in CI:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
export ATLAS_SERVER_URL=https://atlas.example.com
|
|
11
|
+
export ATLAS_PROJECT=checkout-service
|
|
12
|
+
export ATLAS_PUBLISH_TOKEN=your-publish-token
|
|
13
|
+
export ATLAS_ENVIRONMENT=linux-chromium
|
|
14
|
+
export ATLAS_BRANCH=main
|
|
15
|
+
export ATLAS_SHA=your-commit-sha
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The server owns its storage configuration and credentials. Consumers only need the server URL and a publish token. Upload failures fail the test invocation; reporters wait for publication before finishing. Each invocation streams a live run, then publishes final evidence, with stable check IDs relative to the project directory, durations, failures and skipped outcomes. Unknown outcomes, TODOs and skipped tests are `not-run`, never passed. Parallel processes upload independent layers; use distinct producer/environment values for independent suites.
|
|
19
|
+
|
|
20
|
+
A test file is part of a check's identity, not automatically a specification: link checks to product specifications through the existing report mapping workflow when importing JUnit/CTRF, or publish explicit `specPath` checks through the API.
|
|
21
|
+
|
|
22
|
+
## CodeceptJS
|
|
23
|
+
|
|
24
|
+
Use its [Mocha reporter interface](https://codecept.io/reports/):
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
bunx codeceptjs run --reporter @crvouga/atlas/codecept
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Streams scenario starts and outcomes, then records durations and scenario steps when supplied by CodeceptJS. Use the standard single-process runner; parallel workers should each publish their own layer. Runner-native screenshot/video attachments can also be imported from CTRF/JUnit; this reporter does not read arbitrary files from runner objects.
|
|
31
|
+
|
|
32
|
+
## Mocha
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
bunx mocha --reporter @crvouga/atlas/mocha
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or configure `reporter` and `reporterOptions` in Mocha. Options include `url`, `token`, `producer`, `environment`, `branch`, `sha`, `rootDir` and `timeoutMs` (30 seconds by default); explicit options override the environment. Final failures and hook failures are failed checks. Passing retries include a flaky label. Mocha parallel mode is not supported by this reporter's event model; run each shard separately.
|
|
39
|
+
|
|
40
|
+
## Jest
|
|
41
|
+
|
|
42
|
+
Keep Jest's console reporter alongside Atlas:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
export default {
|
|
46
|
+
reporters: ['default', ['@crvouga/atlas/jest', { producer: 'unit' }]],
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The reporter streams test-case starts and results from workers and uploads full aggregated evidence after workers finish. File-level exceptions become failed checks even when no test ran. Watch mode resets publication errors on each invocation. It accepts the same options as Mocha.
|
|
51
|
+
|
|
52
|
+
## Node's test runner
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
node --test --test-reporter=spec --test-reporter-destination=stdout \
|
|
56
|
+
--test-reporter=@crvouga/atlas/node-test --test-reporter-destination=stdout
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Uses the native async event stream, with environment configuration. Reports leaf tests; successful suite containers are excluded, while suite hook failures remain failed checks. Test names include enclosing suites so identical names in different suites keep distinct IDs. Skips and TODOs remain not-run, including TODO failures.
|
|
60
|
+
|
|
61
|
+
## Other runners and frameworks
|
|
62
|
+
|
|
63
|
+
Playwright, Vitest, Bun, WebDriver/Appium and Detox already have Atlas statechart adapters. Pytest, JUnit/TestNG, NUnit, xUnit, Go, Rust, Cypress, WebdriverIO, Cucumber and Robot Framework can publish JUnit XML or CTRF JSON through the existing importer. See [integration commands](integrating.md) and the [report contract](report-contract.md). These report importers complement native reporters; they do not require a storage backend in the consumer project.
|
|
64
|
+
|
|
65
|
+
## Operate the singleton
|
|
66
|
+
|
|
67
|
+
Run `atlas server` once for the projects the node hosts; point local and CI publishers at that URL and set each project's `ATLAS_PROJECT`. Configure backends using environment variables or open **Settings** in the client (`/admin`). Authentication and listening addresses remain deployment configuration. Settings changes are validated and saved atomically for the next server restart. Environment variables and flags override saved values. A backend change does not migrate historical data: retain the old backend as a read source when switching the upload destination.
|
|
68
|
+
|
|
69
|
+
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).
|