@juxtapose/adapter-storybook 0.2.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/LICENSE +21 -0
- package/README.md +17 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +259 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Magic Factory LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# @juxtapose/adapter-storybook
|
|
2
|
+
|
|
3
|
+
Storybook platform adapter for juxtapose visual testing.
|
|
4
|
+
|
|
5
|
+
Part of [juxtapose](https://github.com/juxtapose-dev/juxtapose), visual
|
|
6
|
+
regression testing for component workbenches.
|
|
7
|
+
|
|
8
|
+
**You probably don't need to install this directly.** Use
|
|
9
|
+
[`@juxtapose/cli`](https://www.npmjs.com/package/@juxtapose/cli) for the
|
|
10
|
+
command line, or
|
|
11
|
+
[`@juxtapose/storybook`](https://www.npmjs.com/package/@juxtapose/storybook)
|
|
12
|
+
to review diffs inside Storybook. This package is a building block those
|
|
13
|
+
depend on.
|
|
14
|
+
|
|
15
|
+
Full documentation: https://github.com/juxtapose-dev/juxtapose
|
|
16
|
+
|
|
17
|
+
MIT © Magic Factory LLC
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { Platform, EnumerateTarget, SettleContext, StoryManifest, StoryParams } from '@juxtapose/core';
|
|
3
|
+
export declare class StorybookPlatform implements Platform {
|
|
4
|
+
readonly name = "storybook";
|
|
5
|
+
detect(target: EnumerateTarget): Promise<boolean>;
|
|
6
|
+
enumerate(target: EnumerateTarget): Promise<StoryManifest[]>;
|
|
7
|
+
storyUrl(baseUrl: string, storyId: string): string;
|
|
8
|
+
/** URL-addressable, so showing a story is just a navigation. */
|
|
9
|
+
showStory(page: Page, storyId: string, baseUrl: string): Promise<void>;
|
|
10
|
+
/** Blank preview URL, for warming a page before any story is selected. */
|
|
11
|
+
previewUrl(baseUrl: string): string;
|
|
12
|
+
settle(page: Page, ctx: SettleContext): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Switch stories on a warm page by emitting on Storybook's own channel.
|
|
15
|
+
*
|
|
16
|
+
* This is the single largest optimization in the tool — ~4x per story,
|
|
17
|
+
* because it re-renders instead of reloading the bundle and re-registering
|
|
18
|
+
* the service worker. Returns false if the preview runtime isn't reachable,
|
|
19
|
+
* and the pool falls back to a navigation.
|
|
20
|
+
*/
|
|
21
|
+
switchStory(page: Page, storyId: string, ctx: SettleContext): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Read parameters from the live preview.
|
|
24
|
+
*
|
|
25
|
+
* Necessary because Storybook only serializes a whitelist of parameters into
|
|
26
|
+
* index.json, so `parameters.juxtapose` is frequently absent there even when
|
|
27
|
+
* the story declares it. The original tool read the index in one code path
|
|
28
|
+
* and the live DOM in another, which meant per-story thresholds were silently
|
|
29
|
+
* ignored in the addon. Reading live everywhere keeps one source of truth.
|
|
30
|
+
*/
|
|
31
|
+
readLiveParams(page: Page, storyId: string): Promise<StoryParams | undefined>;
|
|
32
|
+
/** Directories whose changes invalidate every story. */
|
|
33
|
+
readonly configDirs: string[];
|
|
34
|
+
readonly storyFileGlobs: string[];
|
|
35
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
// Storybook platform adapter.
|
|
2
|
+
//
|
|
3
|
+
// Everything in this file is Storybook-specific by design. If it compiles
|
|
4
|
+
// against @juxtapose/core's Platform interface and nothing here leaks upward,
|
|
5
|
+
// the seam holds.
|
|
6
|
+
import { readFile } from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { navigateToStory } from '@juxtapose/core';
|
|
9
|
+
/**
|
|
10
|
+
* Phases where the story is settled enough to screenshot.
|
|
11
|
+
*
|
|
12
|
+
* An allowlist, not a denylist. Storybook's RenderPhase union is
|
|
13
|
+
* `preparing | loading | beforeEach | rendering | playing | played |
|
|
14
|
+
* afterEach | completed | finished | aborted | errored` — listing only the
|
|
15
|
+
* few we consider "still working" means any phase added later, or any
|
|
16
|
+
* transient one we forgot (`beforeEach` and `afterEach` both qualify),
|
|
17
|
+
* silently reads as ready and we screenshot mid-flight.
|
|
18
|
+
*
|
|
19
|
+
* `errored` and `aborted` are included deliberately: a story that failed to
|
|
20
|
+
* render should produce a capture showing that, which is a reviewable diff,
|
|
21
|
+
* rather than hanging until the timeout.
|
|
22
|
+
*/
|
|
23
|
+
const READY_PHASES = ['played', 'completed', 'finished', 'errored', 'aborted'];
|
|
24
|
+
/**
|
|
25
|
+
* Phases meaning the play function has finished.
|
|
26
|
+
*
|
|
27
|
+
* Used when a story opts into `captureAfterPlay`. Narrower than READY_PHASES
|
|
28
|
+
* because the point is to wait for interactions to complete.
|
|
29
|
+
*/
|
|
30
|
+
const PLAYED_PHASES = ['played', 'completed', 'finished'];
|
|
31
|
+
export class StorybookPlatform {
|
|
32
|
+
name = 'storybook';
|
|
33
|
+
async detect(target) {
|
|
34
|
+
if (target.origin) {
|
|
35
|
+
try {
|
|
36
|
+
const res = await fetch(new URL('index.json', withSlash(target.origin)));
|
|
37
|
+
return res.ok;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!target.buildDir)
|
|
44
|
+
return false;
|
|
45
|
+
return (await readIndex(target.buildDir)) !== null;
|
|
46
|
+
}
|
|
47
|
+
async enumerate(target) {
|
|
48
|
+
const index = target.origin
|
|
49
|
+
? await fetchIndex(target.origin)
|
|
50
|
+
: await readIndex(target.buildDir);
|
|
51
|
+
if (!index) {
|
|
52
|
+
throw new Error(`[storybook] no index.json at ${target.origin ?? target.buildDir}. ` +
|
|
53
|
+
`Build Storybook first, or point --origin at a running dev server.`);
|
|
54
|
+
}
|
|
55
|
+
// `importPath` is relative to the project root, not the build dir.
|
|
56
|
+
const base = target.projectRoot;
|
|
57
|
+
return Object.values(index.entries)
|
|
58
|
+
.filter((e) => e.type !== 'docs')
|
|
59
|
+
.map((e) => ({
|
|
60
|
+
storyId: e.id,
|
|
61
|
+
title: e.title,
|
|
62
|
+
name: e.name,
|
|
63
|
+
componentPath: path.resolve(base, e.importPath),
|
|
64
|
+
// Storybook does not serialize arbitrary parameters into index.json,
|
|
65
|
+
// so this is almost always empty in practice — readLiveParams is what
|
|
66
|
+
// actually resolves per-story config. Kept because a custom indexer
|
|
67
|
+
// may include them, and an empty object is the correct fallback.
|
|
68
|
+
params: e.parameters?.juxtapose ?? {},
|
|
69
|
+
}))
|
|
70
|
+
.sort((a, b) => a.storyId.localeCompare(b.storyId));
|
|
71
|
+
}
|
|
72
|
+
storyUrl(baseUrl, storyId) {
|
|
73
|
+
return `${stripSlash(baseUrl)}/iframe.html?id=${encodeURIComponent(storyId)}&viewMode=story`;
|
|
74
|
+
}
|
|
75
|
+
/** URL-addressable, so showing a story is just a navigation. */
|
|
76
|
+
async showStory(page, storyId, baseUrl) {
|
|
77
|
+
await navigateToStory((b, s) => this.storyUrl(b, s))(page, storyId, baseUrl);
|
|
78
|
+
}
|
|
79
|
+
/** Blank preview URL, for warming a page before any story is selected. */
|
|
80
|
+
previewUrl(baseUrl) {
|
|
81
|
+
return `${stripSlash(baseUrl)}/iframe.html`;
|
|
82
|
+
}
|
|
83
|
+
async settle(page, ctx) {
|
|
84
|
+
await waitForRenderPhase(page, ctx);
|
|
85
|
+
await waitForLayoutClass(page);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Switch stories on a warm page by emitting on Storybook's own channel.
|
|
89
|
+
*
|
|
90
|
+
* This is the single largest optimization in the tool — ~4x per story,
|
|
91
|
+
* because it re-renders instead of reloading the bundle and re-registering
|
|
92
|
+
* the service worker. Returns false if the preview runtime isn't reachable,
|
|
93
|
+
* and the pool falls back to a navigation.
|
|
94
|
+
*/
|
|
95
|
+
async switchStory(page, storyId, ctx) {
|
|
96
|
+
const outcome = await page
|
|
97
|
+
.evaluate(({ id, timeoutMs, ready, played, afterPlay }) => new Promise((resolve) => {
|
|
98
|
+
const w = window;
|
|
99
|
+
const preview = w.__STORYBOOK_PREVIEW__;
|
|
100
|
+
const channel = preview?.channel;
|
|
101
|
+
if (!channel)
|
|
102
|
+
return resolve('unsupported');
|
|
103
|
+
const isReady = (phase) => afterPlay
|
|
104
|
+
? !!phase && played.includes(phase)
|
|
105
|
+
: !!phase && ready.includes(phase);
|
|
106
|
+
// Check the phase we may already be in before subscribing —
|
|
107
|
+
// otherwise a story that renders faster than this evaluate
|
|
108
|
+
// deadlocks waiting for an event that already fired.
|
|
109
|
+
const current = preview?.storyRenders?.find((r) => r.id === id);
|
|
110
|
+
if (current && isReady(current.phase))
|
|
111
|
+
return resolve('switched');
|
|
112
|
+
let settled = false;
|
|
113
|
+
const finish = (result) => {
|
|
114
|
+
if (settled)
|
|
115
|
+
return;
|
|
116
|
+
settled = true;
|
|
117
|
+
clearTimeout(timer);
|
|
118
|
+
for (const ev of events)
|
|
119
|
+
channel.removeListener(ev, onEvent);
|
|
120
|
+
resolve(result);
|
|
121
|
+
};
|
|
122
|
+
const onEvent = (...args) => {
|
|
123
|
+
const payload = args[0];
|
|
124
|
+
if (typeof payload === 'string') {
|
|
125
|
+
if (payload === id)
|
|
126
|
+
finish('switched');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (payload?.storyId && payload.storyId !== id)
|
|
130
|
+
return;
|
|
131
|
+
if (payload?.newPhase !== undefined) {
|
|
132
|
+
if (isReady(payload.newPhase))
|
|
133
|
+
finish('switched');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
finish('switched');
|
|
137
|
+
};
|
|
138
|
+
const events = [
|
|
139
|
+
'storyRendered',
|
|
140
|
+
'storyUnchanged',
|
|
141
|
+
'storyRenderPhaseChanged',
|
|
142
|
+
'storyMissing',
|
|
143
|
+
'storyErrored',
|
|
144
|
+
'storyThrewException',
|
|
145
|
+
];
|
|
146
|
+
const timer = setTimeout(() => finish('timeout'), timeoutMs);
|
|
147
|
+
for (const ev of events)
|
|
148
|
+
channel.on(ev, onEvent);
|
|
149
|
+
channel.emit('setCurrentStory', { storyId: id, viewMode: 'story' });
|
|
150
|
+
}), {
|
|
151
|
+
id: storyId,
|
|
152
|
+
timeoutMs: ctx.timeoutMs,
|
|
153
|
+
ready: READY_PHASES,
|
|
154
|
+
played: PLAYED_PHASES,
|
|
155
|
+
afterPlay: ctx.params.captureAfterPlay === true,
|
|
156
|
+
})
|
|
157
|
+
.catch(() => 'unsupported');
|
|
158
|
+
// A timeout still switched the story — the render just ran long. Capture
|
|
159
|
+
// it rather than falling back to a navigation that would be slower and no
|
|
160
|
+
// more correct. A genuinely broken story shows up as a visible diff.
|
|
161
|
+
return outcome === 'switched' || outcome === 'timeout';
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Read parameters from the live preview.
|
|
165
|
+
*
|
|
166
|
+
* Necessary because Storybook only serializes a whitelist of parameters into
|
|
167
|
+
* index.json, so `parameters.juxtapose` is frequently absent there even when
|
|
168
|
+
* the story declares it. The original tool read the index in one code path
|
|
169
|
+
* and the live DOM in another, which meant per-story thresholds were silently
|
|
170
|
+
* ignored in the addon. Reading live everywhere keeps one source of truth.
|
|
171
|
+
*/
|
|
172
|
+
async readLiveParams(page, storyId) {
|
|
173
|
+
return page
|
|
174
|
+
.evaluate((id) => {
|
|
175
|
+
const w = window;
|
|
176
|
+
const render = w.__STORYBOOK_PREVIEW__?.storyRenders?.find((r) => r.id === id);
|
|
177
|
+
return (render?.story?.parameters?.juxtapose ?? undefined);
|
|
178
|
+
}, storyId)
|
|
179
|
+
.catch(() => undefined);
|
|
180
|
+
}
|
|
181
|
+
/** Directories whose changes invalidate every story. */
|
|
182
|
+
configDirs = ['.storybook'];
|
|
183
|
+
// .svelte is included for addon-svelte-csf, which is how most Svelte
|
|
184
|
+
// projects author stories; omitting it would silently under-detect changes
|
|
185
|
+
// for that ecosystem.
|
|
186
|
+
storyFileGlobs = [
|
|
187
|
+
'**/*.stories.@(ts|tsx|js|jsx|mjs|svelte)',
|
|
188
|
+
'**/*.story.@(ts|tsx|js|jsx|mjs|svelte)',
|
|
189
|
+
];
|
|
190
|
+
}
|
|
191
|
+
async function waitForRenderPhase(page, ctx) {
|
|
192
|
+
const afterPlay = ctx.params.captureAfterPlay === true;
|
|
193
|
+
await page
|
|
194
|
+
.waitForFunction(({ id, ready, played, wantPlayed }) => {
|
|
195
|
+
const w = window;
|
|
196
|
+
const render = w.__STORYBOOK_PREVIEW__?.storyRenders?.find((r) => r.id === id);
|
|
197
|
+
if (!render)
|
|
198
|
+
return false;
|
|
199
|
+
const phase = render.phase;
|
|
200
|
+
if (!phase)
|
|
201
|
+
return false;
|
|
202
|
+
return wantPlayed ? played.includes(phase) : ready.includes(phase);
|
|
203
|
+
}, {
|
|
204
|
+
id: ctx.story.storyId,
|
|
205
|
+
ready: READY_PHASES,
|
|
206
|
+
played: PLAYED_PHASES,
|
|
207
|
+
wantPlayed: afterPlay,
|
|
208
|
+
}, { timeout: ctx.timeoutMs })
|
|
209
|
+
// Timing out is not an error: screenshot what's on screen. A story that
|
|
210
|
+
// renders late should surface as a diff a human can judge, not as an
|
|
211
|
+
// exception that aborts the run.
|
|
212
|
+
.catch(() => { });
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Wait for Storybook's layout class, which proves the decorator chain applied.
|
|
216
|
+
*
|
|
217
|
+
* Without this, a story can be "rendered" per the phase machine but not yet
|
|
218
|
+
* laid out, and the screenshot catches it mid-flow.
|
|
219
|
+
*/
|
|
220
|
+
async function waitForLayoutClass(page) {
|
|
221
|
+
await page
|
|
222
|
+
.waitForFunction(() => {
|
|
223
|
+
const cls = document.body?.classList;
|
|
224
|
+
return (!!cls &&
|
|
225
|
+
(cls.contains('sb-main-padded') ||
|
|
226
|
+
cls.contains('sb-main-centered') ||
|
|
227
|
+
cls.contains('sb-main-fullscreen')));
|
|
228
|
+
}, undefined, { timeout: 2000 })
|
|
229
|
+
.catch(() => { });
|
|
230
|
+
}
|
|
231
|
+
async function readIndex(buildDir) {
|
|
232
|
+
for (const name of ['index.json', 'stories.json']) {
|
|
233
|
+
try {
|
|
234
|
+
const raw = await readFile(path.join(buildDir, name), 'utf8');
|
|
235
|
+
const parsed = JSON.parse(raw);
|
|
236
|
+
if (parsed?.entries)
|
|
237
|
+
return parsed;
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
// try the next candidate
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
async function fetchIndex(origin) {
|
|
246
|
+
try {
|
|
247
|
+
const res = await fetch(new URL('index.json', withSlash(origin)));
|
|
248
|
+
if (!res.ok)
|
|
249
|
+
return null;
|
|
250
|
+
const parsed = (await res.json());
|
|
251
|
+
return parsed?.entries ? parsed : null;
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const withSlash = (u) => (u.endsWith('/') ? u : u + '/');
|
|
258
|
+
const stripSlash = (u) => u.replace(/\/+$/, '');
|
|
259
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@juxtapose/adapter-storybook",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Storybook platform adapter for juxtapose visual testing.",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./dist/index.js",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@juxtapose/core": "0.2.0"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"playwright": "^1.48.0"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/juxtapose-dev/juxtapose.git",
|
|
28
|
+
"directory": "packages/adapter-storybook"
|
|
29
|
+
},
|
|
30
|
+
"peerDependenciesMeta": {
|
|
31
|
+
"playwright": {
|
|
32
|
+
"optional": true
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc -p tsconfig.json"
|
|
37
|
+
}
|
|
38
|
+
}
|