@recursica/adapter-tester 1.1.0 → 2.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 +68 -78
- package/dist/adapter-tester.schema.json.d.ts +116 -0
- package/dist/cli.cjs +39 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +4923 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-B0Eop8Az.cjs.map +1 -1
- package/dist/{config-CKgyDyNF.js → config-CDxTeSAY.js} +2 -4
- package/dist/{config-CKgyDyNF.js.map → config-CDxTeSAY.js.map} +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/devServer.d.ts +8 -0
- package/dist/devServer.d.ts.map +1 -0
- package/dist/fileConfig.d.ts +60 -0
- package/dist/fileConfig.d.ts.map +1 -0
- package/dist/harness/mantineSourceOfTruth.d.ts.map +1 -1
- package/dist/index.cjs +1 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.html +29 -24
- package/dist/index.js +6 -117
- package/dist/index.js.map +1 -1
- package/dist/mantineSourceOfTruth-BiSfXKff.js +121 -0
- package/dist/mantineSourceOfTruth-BiSfXKff.js.map +1 -0
- package/dist/mantineSourceOfTruth-DCoJ2dU-.cjs +54 -0
- package/dist/mantineSourceOfTruth-DCoJ2dU-.cjs.map +1 -0
- package/dist/testing/runVisualRegression.d.ts.map +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +85 -81
- package/dist/testing.js.map +1 -1
- package/dist/validateFileConfig.d.ts +7 -0
- package/dist/validateFileConfig.d.ts.map +1 -0
- package/package.json +17 -7
- package/public/index.html +466 -0
- package/report-header.txt +8 -0
- package/src/adapter-tester.schema.json +113 -0
package/README.md
CHANGED
|
@@ -8,38 +8,47 @@ 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, pixel-by-pixel regression checks for all stories.
|
|
11
|
+
1. **Automated Visual Tests:** Headless, pixel-by-pixel 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.
|
|
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
|
|
13
|
+
3. **An installable devDependency**, currently wired into `@recursica/mui-adapter` (not `@recursica/mantine-adapter` — Mantine is itself the source of truth, so it has nothing to diff against). 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
|
-
|
|
15
|
+
**Default mode** (used by `@recursica/mui-adapter`, and any external adapter repo installing this package): compares this project's own Storybook — the one already defined by its `storybook` npm script — against a throwaway harness that installs the _published_ `@recursica/mantine-adapter` from npm. No monorepo checkout, no manual config, in most cases no config file at all.
|
|
16
|
+
|
|
17
|
+
**Non-standard mode**: this monorepo also runs adapter-tester against itself — Mantine and MUI both as local sibling workspace packages — to catch regressions in _uncommitted_ code before it's published. 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.
|
|
16
18
|
|
|
17
19
|
---
|
|
18
20
|
|
|
19
|
-
##
|
|
21
|
+
## npm scripts
|
|
22
|
+
|
|
23
|
+
Installing `@recursica/adapter-tester` as a devDependency (see [below](#using-this-package-in-another-adapter-repo)) wires up two scripts:
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"scripts": {
|
|
28
|
+
"adapter-tester": "adapter-tester --serve",
|
|
29
|
+
"adapter-tester:automated": "adapter-tester"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
22
33
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
34
|
+
- `npm run adapter-tester` — Interactive Dev Mode: boots both Storybooks (reusing them if already running) and opens the synced side-by-side comparison browser.
|
|
35
|
+
- `npm run adapter-tester:automated` — the headless Playwright pixel-diff suite; see [Automated Visual Tests](#automated-visual-tests) below.
|
|
25
36
|
|
|
26
|
-
|
|
37
|
+
Both boot Storybooks themselves — nothing needs to be running beforehand.
|
|
27
38
|
|
|
28
39
|
---
|
|
29
40
|
|
|
30
41
|
## Interactive Dev Mode
|
|
31
42
|
|
|
32
|
-
The **Dev Mode** is a powerful visual auditing tool that syncs the
|
|
43
|
+
The **Dev Mode** is a powerful visual auditing tool that syncs the source-of-truth and target Storybooks in real-time. When you interact with controls (like toggling 'disabled' or changing 'size') in the left pane, Dev Mode instantly updates the right pane to match that exact state.
|
|
33
44
|
|
|
34
45
|
### How to Start
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
3. Open your browser to [http://localhost:6010](http://localhost:6010).
|
|
47
|
+
```bash
|
|
48
|
+
npm run adapter-tester
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This boots both Storybooks (reusing them if already running) and opens [http://localhost:6010](http://localhost:6010) automatically.
|
|
43
52
|
|
|
44
53
|
### Taking Component Notes
|
|
45
54
|
|
|
@@ -70,95 +79,76 @@ The Dev Mode server fetches this file dynamically, so any changes you make to `r
|
|
|
70
79
|
To execute a full headless visual regression scan across all components:
|
|
71
80
|
|
|
72
81
|
```bash
|
|
73
|
-
|
|
74
|
-
npm run test:visual
|
|
82
|
+
npm run adapter-tester:automated # runs the `adapter-tester` CLI
|
|
75
83
|
```
|
|
76
84
|
|
|
85
|
+
`adapter-tester` reads `adapter-tester.config.json` from the current directory (or falls back to defaults if the file doesn't exist), generates a throwaway Playwright config + spec under `.adapter-tester/run/` (git-ignore this directory), and runs it. There's no Playwright config or spec file to hand-author.
|
|
86
|
+
|
|
87
|
+
Pass `--dry-run` to print the resolved config and generated files without booting anything — useful for checking what a config resolves to.
|
|
88
|
+
|
|
77
89
|
### What happens during execution?
|
|
78
90
|
|
|
79
|
-
1. **Automatic Storybook Bootup**:
|
|
80
|
-
2. **Story Discovery**: The test suite fetches the source of truth's Storybook index (
|
|
81
|
-
3. **Headless Snapshots**: It launches headless Chrome in the background, navigates to the isolated iframe views for both
|
|
82
|
-
4. **Pixel Diffing**: It diffs the images using `pixelmatch` against
|
|
91
|
+
1. **Automatic Storybook Bootup**: `adapter-tester` boots both sides of the comparison — this project's own Storybook, and the source-of-truth Storybook (a throwaway Mantine harness by default) — reusing them if already running.
|
|
92
|
+
2. **Story Discovery**: The test suite fetches the source of truth's 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/*`).
|
|
93
|
+
3. **Headless Snapshots**: It launches headless Chrome in the background, navigates to the isolated iframe views for both targets, and takes side-by-side snapshots.
|
|
94
|
+
4. **Pixel Diffing**: It diffs the images using `pixelmatch` against the configured mismatch threshold.
|
|
83
95
|
5. **Native Report Generation**: All raw snapshots, highlighted pixel diff overlays, and extracted computed CSS DOM trees are embedded directly as test attachments.
|
|
84
96
|
|
|
85
97
|
### Output & Reports
|
|
86
98
|
|
|
87
99
|
All test outcomes and visual outputs are compiled into the standard, git-ignored Playwright reports folder:
|
|
88
100
|
|
|
89
|
-
- **Interactive HTML Dashboard**: View the full side-by-side browser layout, visual difference overlays, and style audits by opening
|
|
90
|
-
`packages/adapter-tester/playwright-report/index.html`
|
|
101
|
+
- **Interactive HTML Dashboard**: View the full side-by-side browser layout, visual difference overlays, and style audits by opening `playwright-report/index.html`.
|
|
91
102
|
- **Review in Browser**: Open the interactive dashboard directly from your terminal by running:
|
|
92
103
|
```bash
|
|
93
104
|
npx playwright show-report
|
|
94
105
|
```
|
|
95
|
-
- **Raw Screenshot Assets**: Individual screenshot buffers and visual diff outputs are retained in the standard `
|
|
106
|
+
- **Raw Screenshot Assets**: Individual screenshot buffers and visual diff outputs are retained in the standard `test-results/` folder for reference.
|
|
96
107
|
|
|
97
108
|
---
|
|
98
109
|
|
|
99
|
-
##
|
|
100
|
-
|
|
101
|
-
`@recursica/adapter-tester` is a real, installable devDependency — a standalone adapter repo (not checked out inside this monorepo) can use it to diff its own Storybook against Mantine, Recursica's source-of-truth adapter, without cloning this monorepo at all.
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
npm install --save-dev @recursica/adapter-tester
|
|
105
|
-
```
|
|
110
|
+
## Configuring `adapter-tester.config.json`
|
|
106
111
|
|
|
107
|
-
|
|
112
|
+
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.
|
|
108
113
|
|
|
109
|
-
|
|
110
|
-
// adapter-tester.config.ts
|
|
111
|
-
import { defineAdapterTesterConfig } from "@recursica/adapter-tester";
|
|
114
|
+
Every `adapter-tester.config.json` is validated against [`src/adapter-tester.schema.json`](./src/adapter-tester.schema.json) before a run — unknown fields, wrong types, and invalid `sourceOfTruth` shapes fail fast with a specific error instead of silently doing the wrong thing. Point your editor at it for autocomplete/inline docs:
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"$schema": "./node_modules/@recursica/adapter-tester/src/adapter-tester.schema.json",
|
|
119
|
+
"name": "MyAdapter",
|
|
120
|
+
"storybook": { "port": 6006, "command": "npm run storybook" },
|
|
121
|
+
"sourceOfTruth": { "type": "mantine-harness" },
|
|
122
|
+
"diffThresholdPixels": 3500,
|
|
123
|
+
"relaxedThresholdStoryIds": ["ui-kit-slider"],
|
|
124
|
+
"relaxedThresholdPixels": 15000,
|
|
125
|
+
"excludeTitlePrefixes": ["Theme", "Tokens", "Introduction"]
|
|
126
|
+
}
|
|
120
127
|
```
|
|
121
128
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
import config from "./adapter-tester.config";
|
|
129
|
-
|
|
130
|
-
export default defineConfig({
|
|
131
|
-
testDir: "./tests",
|
|
132
|
-
webServer: [
|
|
133
|
-
mantineSourceOfTruthWebServer({
|
|
134
|
-
dir: "./.adapter-tester/mantine-harness", // add to .gitignore
|
|
135
|
-
port: 6011,
|
|
136
|
-
}),
|
|
137
|
-
{
|
|
138
|
-
command: "npm run storybook", // your own adapter's Storybook
|
|
139
|
-
port: 6006,
|
|
140
|
-
reuseExistingServer: !process.env.CI,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
});
|
|
144
|
-
```
|
|
129
|
+
- `name` — label for this project's own target. Defaults to the unscoped `package.json` name.
|
|
130
|
+
- `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
|
+
- `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 (and `@recursica/mui-adapter`) uses.
|
|
133
|
+
- `sourceOfTruth.type: "url"` — the **non-standard** mode: points at an already-addressable Storybook via `command`/`port`/`cwd` instead of the harness. Used inside this monorepo to compare local, uncommitted `mantine-adapter`/`mui-adapter` workspace packages against each other — see `adapter-tester.config.json` in this package.
|
|
134
|
+
- `diffThresholdPixels`/`relaxedThresholdStoryIds`/`relaxedThresholdPixels`/`excludeTitlePrefixes` — same meaning as before; see `src/adapter-tester.schema.json` for full docs.
|
|
145
135
|
|
|
146
|
-
|
|
136
|
+
---
|
|
147
137
|
|
|
148
|
-
|
|
149
|
-
// tests/visual-regression.spec.ts
|
|
150
|
-
import { runVisualRegression } from "@recursica/adapter-tester/testing";
|
|
151
|
-
import config from "../adapter-tester.config";
|
|
138
|
+
## Using this package in another adapter repo
|
|
152
139
|
|
|
153
|
-
|
|
154
|
-
```
|
|
140
|
+
`@recursica/adapter-tester` is a real, installable devDependency — a standalone adapter repo (not checked out inside this monorepo) can use it to diff its own Storybook against Mantine, Recursica's source-of-truth adapter, without cloning this monorepo at all.
|
|
155
141
|
|
|
156
142
|
```bash
|
|
157
|
-
|
|
143
|
+
npm install --save-dev @recursica/adapter-tester @playwright/test
|
|
144
|
+
npx playwright install chromium
|
|
158
145
|
```
|
|
159
146
|
|
|
160
|
-
|
|
147
|
+
If your repo already has a `storybook` npm script with a port set (`storybook dev -p 6006`), no config file is required. Add the two scripts from [npm scripts](#npm-scripts) above to your `package.json`, then:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npm run adapter-tester # Interactive Dev Mode
|
|
151
|
+
npm run adapter-tester:automated # headless Playwright suite
|
|
152
|
+
```
|
|
161
153
|
|
|
162
|
-
- `
|
|
163
|
-
- Pass `mantineAdapterVersion`/`storybookTemplateVersion` to pin the harness to a specific published release instead of tracking `latest`.
|
|
164
|
-
- `defineAdapterTesterConfig` requires exactly one target marked `sourceOfTruth: true`; it throws otherwise.
|
|
154
|
+
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.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/borderux/recursica/tree/main/packages/adapter-tester/src/adapter-tester.schema.json",
|
|
4
|
+
"title": "adapter-tester.config.json",
|
|
5
|
+
"description": "Configuration for @recursica/adapter-tester. All fields are optional — an adapter repo with a normal `storybook` npm script needs no config file at all.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Optional pointer to this schema for editor autocomplete, e.g. \"./node_modules/@recursica/adapter-tester/src/adapter-tester.schema.json\"."
|
|
12
|
+
},
|
|
13
|
+
"name": {
|
|
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/mui-adapter\" -> \"mui-adapter\")."
|
|
16
|
+
},
|
|
17
|
+
"storybook": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"additionalProperties": false,
|
|
20
|
+
"description": "This project's own Storybook target.",
|
|
21
|
+
"properties": {
|
|
22
|
+
"port": {
|
|
23
|
+
"type": "integer",
|
|
24
|
+
"minimum": 1,
|
|
25
|
+
"maximum": 65535,
|
|
26
|
+
"description": "Port the target's Storybook is served on. Auto-detected from this project's own `scripts.storybook` (a `-p <port>`/`--port <port>` flag) when omitted, falling back to Storybook's own default of 6006."
|
|
27
|
+
},
|
|
28
|
+
"command": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Command that boots the target's Storybook. Defaults to `npm run storybook`."
|
|
31
|
+
},
|
|
32
|
+
"cwd": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Directory the command runs in, relative to the config file. Defaults to \".\"."
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"sourceOfTruth": {
|
|
39
|
+
"description": "The comparison target. Defaults to `{ \"type\": \"mantine-harness\" }`.",
|
|
40
|
+
"oneOf": [
|
|
41
|
+
{
|
|
42
|
+
"type": "object",
|
|
43
|
+
"additionalProperties": false,
|
|
44
|
+
"description": "Default mode: boots a throwaway harness that installs the published @recursica/mantine-adapter from npm — no monorepo checkout required.",
|
|
45
|
+
"properties": {
|
|
46
|
+
"type": { "const": "mantine-harness" },
|
|
47
|
+
"port": {
|
|
48
|
+
"type": "integer",
|
|
49
|
+
"minimum": 1,
|
|
50
|
+
"maximum": 65535,
|
|
51
|
+
"description": "Port the throwaway harness's Storybook is served on. Defaults to 6011."
|
|
52
|
+
},
|
|
53
|
+
"mantineAdapterVersion": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "npm version/tag of @recursica/mantine-adapter to install in the harness. Defaults to `latest`."
|
|
56
|
+
},
|
|
57
|
+
"storybookTemplateVersion": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "npm version/tag of @recursica/storybook-template to install in the harness. Defaults to `latest`."
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"type": "object",
|
|
65
|
+
"additionalProperties": false,
|
|
66
|
+
"description": "Non-standard mode: points at an already-addressable Storybook — e.g. a sibling workspace package's own Storybook inside this monorepo.",
|
|
67
|
+
"required": ["type", "port"],
|
|
68
|
+
"properties": {
|
|
69
|
+
"type": { "const": "url" },
|
|
70
|
+
"name": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"description": "Label for the source-of-truth target. Defaults to \"Mantine\"."
|
|
73
|
+
},
|
|
74
|
+
"port": {
|
|
75
|
+
"type": "integer",
|
|
76
|
+
"minimum": 1,
|
|
77
|
+
"maximum": 65535,
|
|
78
|
+
"description": "Port the source-of-truth Storybook is served on."
|
|
79
|
+
},
|
|
80
|
+
"command": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"description": "Command that boots the source-of-truth Storybook. Defaults to `npm run storybook`."
|
|
83
|
+
},
|
|
84
|
+
"cwd": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"description": "Directory the command runs in, relative to the config file. Defaults to \".\"."
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
"diffThresholdPixels": {
|
|
93
|
+
"type": "number",
|
|
94
|
+
"minimum": 0,
|
|
95
|
+
"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
|
+
},
|
|
97
|
+
"relaxedThresholdStoryIds": {
|
|
98
|
+
"type": "array",
|
|
99
|
+
"items": { "type": "string" },
|
|
100
|
+
"description": "Story id prefixes that use `relaxedThresholdPixels` instead of the global `diffThresholdPixels`."
|
|
101
|
+
},
|
|
102
|
+
"relaxedThresholdPixels": {
|
|
103
|
+
"type": "number",
|
|
104
|
+
"minimum": 0,
|
|
105
|
+
"description": "Diff threshold applied to stories matching `relaxedThresholdStoryIds`."
|
|
106
|
+
},
|
|
107
|
+
"excludeTitlePrefixes": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": { "type": "string" },
|
|
110
|
+
"description": "Storybook title prefixes to exclude from comparison, in addition to the built-in denylist (`Theme/*`, `Tokens/*`, `Introduction`)."
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
;
|
|
115
|
+
|
|
116
|
+
export default _default;
|