@recursica/adapter-tester 2.1.0 → 3.0.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/README.md +59 -16
- package/dist/adapter-tester.schema.json.d.ts +14 -10
- package/dist/cli.cjs +20 -24
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +240 -4840
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +46 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/fileConfig.d.ts +9 -2
- package/dist/fileConfig.d.ts.map +1 -1
- package/dist/golden/diffPng.d.ts +8 -0
- package/dist/golden/diffPng.d.ts.map +1 -0
- package/dist/golden/manifest.schema.json.d.ts +27 -0
- package/dist/golden/manifestStore.d.ts +15 -0
- package/dist/golden/manifestStore.d.ts.map +1 -0
- package/dist/golden/resolveSourceOfTruthGolden.d.ts +29 -0
- package/dist/golden/resolveSourceOfTruthGolden.d.ts.map +1 -0
- package/dist/golden/validateManifest.d.ts +7 -0
- package/dist/golden/validateManifest.d.ts.map +1 -0
- package/dist/index-C6uYPRmx.cjs +9 -0
- package/dist/index-C6uYPRmx.cjs.map +1 -0
- package/dist/index-DqQzFSAH.js +4667 -0
- package/dist/index-DqQzFSAH.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -6
- package/dist/index.js.map +1 -1
- package/dist/testing/runVisualRegression.d.ts +22 -5
- package/dist/testing/runVisualRegression.d.ts.map +1 -1
- package/dist/testing.cjs +4 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +221 -151
- package/dist/testing.js.map +1 -1
- package/package.json +3 -2
- package/src/adapter-tester.schema.json +14 -10
- package/src/golden/manifest.schema.json +24 -0
- package/dist/config-B0Eop8Az.cjs +0 -2
- package/dist/config-B0Eop8Az.cjs.map +0 -1
- package/dist/config-CDxTeSAY.js +0 -21
- package/dist/config-CDxTeSAY.js.map +0 -1
package/README.md
CHANGED
|
@@ -8,13 +8,13 @@ The `@recursica/adapter-tester` ensures that a Recursica adapter's components vi
|
|
|
8
8
|
|
|
9
9
|
This package provides three primary utilities:
|
|
10
10
|
|
|
11
|
-
1. **Automated Visual Tests:** Headless,
|
|
11
|
+
1. **Automated Visual Tests:** Headless, golden-image regression checks for all stories, run as a single CLI command (`adapter-tester`) reading a small JSON config — no Playwright config or spec files to author. See [Golden Images](#golden-images) below for the model.
|
|
12
12
|
2. **Interactive Dev Mode:** A side-by-side synchronized browser environment with built-in note taking for auditing components and feeding fixes directly to an AI agent.
|
|
13
|
-
3. **An installable devDependency**,
|
|
13
|
+
3. **An installable devDependency**, wired into `@recursica/mantine-adapter` — the source-of-truth adapter, run in `isSourceOfTruthAdapter` mode (own-drift check only, since it has nothing above it to diverge from). Any other adapter repo — including one that never checked out this monorepo — can install it the same way. See [Using this package in another adapter repo](#using-this-package-in-another-adapter-repo).
|
|
14
14
|
|
|
15
|
-
**Default mode** (used by
|
|
15
|
+
**Default mode** (used by any adapter repo installing this package): checks this project's own Storybook — the one already defined by its `storybook` npm script — against its own committed golden images, and flags divergence from the source-of-truth adapter's (`@recursica/mantine-adapter`) own golden images. No monorepo checkout, no manual config, in most cases no config file at all.
|
|
16
16
|
|
|
17
|
-
**Non-standard mode**: this monorepo also runs adapter-tester against itself
|
|
17
|
+
**Non-standard mode**: this monorepo also runs adapter-tester against itself, pointed at an adapter's and `@recursica/mantine-adapter`'s local sibling workspace packages — so the divergence check sees local, uncommitted `mantine-adapter` golden changes before they're published, not whatever was last published to npm. See `adapter-tester.config.json` in this package for that config; it's the same CLI, just pointed at `sourceOfTruth.type: "url"` instead of the default Mantine harness.
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -86,13 +86,20 @@ npm run adapter-tester:automated # runs the `adapter-tester` CLI
|
|
|
86
86
|
|
|
87
87
|
Pass `--dry-run` to print the resolved config and generated files without booting anything — useful for checking what a config resolves to.
|
|
88
88
|
|
|
89
|
+
Any other args are forwarded to `playwright test`, so you can scope a run to specific stories instead of running the full suite every time:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npm run adapter-tester:automated -- --grep "Toast"
|
|
93
|
+
```
|
|
94
|
+
|
|
89
95
|
### What happens during execution?
|
|
90
96
|
|
|
91
|
-
1. **Automatic Storybook Bootup**: `adapter-tester` boots
|
|
92
|
-
2. **Story Discovery**: The test suite fetches
|
|
93
|
-
3. **Headless
|
|
94
|
-
4. **
|
|
95
|
-
5. **
|
|
97
|
+
1. **Automatic Storybook Bootup**: `adapter-tester` boots only this project's own Storybook — the divergence check reads the source-of-truth adapter's stored golden files, never a live Storybook, so nothing else needs to boot.
|
|
98
|
+
2. **Story Discovery**: The test suite fetches this project's own Storybook index (`/index.json`) to dynamically discover and parameterize tests for every component story, excluding `@recursica/storybook-template`'s own default token/theme demo stories (`Theme/*`, `Tokens/*`) and each adapter's own onboarding stories (`Introduction/*`).
|
|
99
|
+
3. **Headless Snapshot**: It launches headless Chrome, navigates to the isolated iframe view, and takes a screenshot.
|
|
100
|
+
4. **Own-Drift Check**: Diffs the screenshot against this project's own `test/golden/<story-id>.png` using `pixelmatch`, against the configured mismatch threshold. No golden yet for a story is not a failure — one is captured from this run.
|
|
101
|
+
5. **Divergence Check**: Diffs this project's own golden against the source-of-truth adapter's golden (skipped for the source-of-truth adapter's own config). Different and not yet reviewed via `--approve-divergence`? Flagged as a report annotation — never a failure on its own.
|
|
102
|
+
6. **Native Report Generation**: Screenshots, diff overlays, and divergence flags are embedded directly as test attachments/annotations.
|
|
96
103
|
|
|
97
104
|
### Output & Reports
|
|
98
105
|
|
|
@@ -107,6 +114,35 @@ All test outcomes and visual outputs are compiled into the standard, git-ignored
|
|
|
107
114
|
|
|
108
115
|
---
|
|
109
116
|
|
|
117
|
+
## Golden Images
|
|
118
|
+
|
|
119
|
+
Each adapter's `test/golden/` directory — committed to git, alongside a `manifest.json` tracking when each was captured — is its own baseline:
|
|
120
|
+
|
|
121
|
+
- **Own-drift check (hard fail):** this run's live render vs this project's own golden. Catches unintended CSS regressions.
|
|
122
|
+
- **Divergence check (soft flag, never fails a run):** this project's own golden vs the source-of-truth adapter's golden — different underlying UI libraries can legitimately render a component differently, so a divergence isn't automatically wrong, just unreviewed.
|
|
123
|
+
|
|
124
|
+
These are explicit, developer-run workflows — not run in CI, and not scoped down automatically; use `--grep` to target specific stories.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Capture/refresh this project's own goldens for stories matching "Toast",
|
|
128
|
+
# from the current live render. Use after an intentional styling change.
|
|
129
|
+
npm run adapter-tester:automated -- --grep "Toast" --update-golden
|
|
130
|
+
|
|
131
|
+
# Review a flagged divergence from the source of truth, and accept it as
|
|
132
|
+
# intentional. Also (re)captures the own golden from the current live render.
|
|
133
|
+
npm run adapter-tester:automated -- --grep "Toast" --approve-divergence
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`--approve-divergence` records the source-of-truth adapter's own `manifest.json` `createdAt` for that story at review time. If the source of truth's golden is recaptured later, the divergence flags again for re-review — approval isn't a permanent exemption.
|
|
137
|
+
|
|
138
|
+
A story with no golden yet (new story, or one never captured) is not a failure in either mode — one is captured from the current run automatically.
|
|
139
|
+
|
|
140
|
+
Renamed/removed stories just leave an orphaned `test/golden/<story-id>.png`/manifest entry behind; nothing prunes these automatically.
|
|
141
|
+
|
|
142
|
+
`manifest.json` is validated against [`src/golden/manifest.schema.json`](./src/golden/manifest.schema.json) on every read/write — don't hand-edit it.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
110
146
|
## Configuring `adapter-tester.config.json`
|
|
111
147
|
|
|
112
148
|
All fields are optional — an adapter repo with a normal `storybook` npm script (e.g. `storybook dev -p 6012`) needs no config file at all.
|
|
@@ -120,18 +156,19 @@ Every `adapter-tester.config.json` is validated against [`src/adapter-tester.sch
|
|
|
120
156
|
"storybook": { "port": 6006, "command": "npm run storybook" },
|
|
121
157
|
"sourceOfTruth": { "type": "mantine-harness" },
|
|
122
158
|
"diffThresholdPixels": 3500,
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
159
|
+
"storyThresholds": { "ui-kit-slider": 15000 },
|
|
160
|
+
"excludeTitlePrefixes": ["Theme", "Tokens", "Introduction"],
|
|
161
|
+
"excludeStoryIds": ["ui-kit-slider--range-mode-with-icons-and-inputs"]
|
|
126
162
|
}
|
|
127
163
|
```
|
|
128
164
|
|
|
129
165
|
- `name` — label for this project's own target. Defaults to the unscoped `package.json` name.
|
|
130
166
|
- `storybook.port` — defaults to whatever `-p`/`--port` is set on this project's own `storybook` script; falls back to Storybook's default of `6006`.
|
|
131
167
|
- `storybook.command`/`storybook.cwd` — default to `npm run storybook` in the current directory.
|
|
132
|
-
- `sourceOfTruth` — defaults to `{ "type": "mantine-harness" }`: a throwaway harness that installs the _published_ `@recursica/mantine-adapter` from npm, so you never need this monorepo checked out. This is the standard mode every external adapter repo
|
|
133
|
-
- `sourceOfTruth.type: "url"` — the **non-standard** mode: points at an already-addressable Storybook via `command`/`port`/`cwd` instead of the harness
|
|
134
|
-
- `
|
|
168
|
+
- `sourceOfTruth` — defaults to `{ "type": "mantine-harness" }`: a throwaway harness that installs the _published_ `@recursica/mantine-adapter` from npm, so you never need this monorepo checked out. This is the standard mode every external adapter repo uses.
|
|
169
|
+
- `sourceOfTruth.type: "url"` — the **non-standard** mode: points at an already-addressable Storybook via `command`/`port`/`cwd` instead of the harness, and reads that sibling package's `test/golden/` directly from disk for the divergence check (including uncommitted local changes) instead of resolving a published npm version. Used inside this monorepo — see `adapter-tester.config.json` in this package.
|
|
170
|
+
- `isSourceOfTruthAdapter` — set `true` only in the source-of-truth adapter's own config (`@recursica/mantine-adapter`). Skips `sourceOfTruth`/the divergence check entirely; runs the own-drift check standalone. Also disables Dev Mode (`--serve`) — there's nothing to sync against.
|
|
171
|
+
- `diffThresholdPixels`/`storyThresholds`/`excludeTitlePrefixes`/`excludeStoryIds` — same meaning as before; see `src/adapter-tester.schema.json` for full docs.
|
|
135
172
|
|
|
136
173
|
---
|
|
137
174
|
|
|
@@ -151,4 +188,10 @@ npm run adapter-tester # Interactive Dev Mode
|
|
|
151
188
|
npm run adapter-tester:automated # headless Playwright suite
|
|
152
189
|
```
|
|
153
190
|
|
|
154
|
-
|
|
191
|
+
Any extra args after `adapter-tester:automated` are passed straight through to `playwright test`, so you can scope a run instead of executing the full suite:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npm run adapter-tester:automated -- --grep "Toast"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Add `adapter-tester.config.json` only to override defaults (see [Configuring `adapter-tester.config.json`](#configuring-adapter-testerconfigjson) above), e.g. to raise the diff threshold or relax specific stories. Add `.adapter-tester/` to your `.gitignore` — it's regenerated on every run. Commit `test/golden/` — that's your project's actual baseline, not a build artifact.
|
|
@@ -12,7 +12,7 @@ declare const _default: {
|
|
|
12
12
|
},
|
|
13
13
|
"name": {
|
|
14
14
|
"type": "string",
|
|
15
|
-
"description": "Label for this project's own target. Defaults to the unscoped name in this project's package.json (e.g. \"@recursica/
|
|
15
|
+
"description": "Label for this project's own target. Defaults to the unscoped name in this project's package.json (e.g. \"@recursica/some-adapter\" -> \"some-adapter\")."
|
|
16
16
|
},
|
|
17
17
|
"storybook": {
|
|
18
18
|
"type": "object",
|
|
@@ -89,25 +89,29 @@ declare const _default: {
|
|
|
89
89
|
}
|
|
90
90
|
]
|
|
91
91
|
},
|
|
92
|
+
"isSourceOfTruthAdapter": {
|
|
93
|
+
"type": "boolean",
|
|
94
|
+
"description": "True only for the source-of-truth adapter's own config (mantine-adapter). Skips `sourceOfTruth` entirely — there's nothing above it to diverge from — and runs the own-drift golden check standalone, against just this project's own Storybook. Defaults to false."
|
|
95
|
+
},
|
|
92
96
|
"diffThresholdPixels": {
|
|
93
97
|
"type": "number",
|
|
94
98
|
"minimum": 0,
|
|
95
99
|
"description": "Global visual diff threshold, in mismatched pixels, before a story is considered a failure. Defaults to 3500. AI agents must not modify this field — see AGENT.md."
|
|
96
100
|
},
|
|
97
|
-
"
|
|
98
|
-
"type": "
|
|
99
|
-
"
|
|
100
|
-
"description": "
|
|
101
|
-
},
|
|
102
|
-
"relaxedThresholdPixels": {
|
|
103
|
-
"type": "number",
|
|
104
|
-
"minimum": 0,
|
|
105
|
-
"description": "Diff threshold applied to stories matching `relaxedThresholdStoryIds`."
|
|
101
|
+
"storyThresholds": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"additionalProperties": { "type": "number", "minimum": 0 },
|
|
104
|
+
"description": "Per-story diff threshold overrides, keyed by story id prefix (a story matches if its id equals the key or starts with it). Overrides `diffThresholdPixels` for matching stories. When more than one key matches a story, the longest (most specific) key wins."
|
|
106
105
|
},
|
|
107
106
|
"excludeTitlePrefixes": {
|
|
108
107
|
"type": "array",
|
|
109
108
|
"items": { "type": "string" },
|
|
110
109
|
"description": "Storybook title prefixes to exclude from comparison, in addition to the built-in denylist (`Theme/*`, `Tokens/*`, `Introduction`)."
|
|
110
|
+
},
|
|
111
|
+
"excludeStoryIds": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"items": { "type": "string" },
|
|
114
|
+
"description": "Story id prefixes to skip entirely — no own-drift check, no divergence check, no golden captured. For excluding individual stories that don't have a cross-adapter counterpart; use `excludeTitlePrefixes` to drop a whole title instead."
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
117
|
}
|