@fohte/storybook-addon 0.1.5 → 0.1.6
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 +2 -0
- package/lib/vitest-plugin.d.ts +6 -0
- package/lib/vitest-plugin.js +24 -1
- package/lib/vitest-viewport-setup.d.ts +10 -0
- package/lib/vitest-viewport-setup.js +50 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -78,6 +78,8 @@ initialize({
|
|
|
78
78
|
|
|
79
79
|
Builds a Vitest browser-mode project that runs Storybook stories through [`@storybook/addon-vitest`](https://storybook.js.org/docs/writing-tests/integrations/vitest-addon) and captures a screenshot of each with [`@storycap-testrun/browser`](https://github.com/reg-viz/storycap-testrun), patched to shorten storycap's hardcoded 500ms network-idle wait to 100ms and to fix a tiling bug in its fullPage capture (`clip` staying anchored to the top of the viewport instead of following the browser's clamped scroll position, which duplicated content and cut off the bottom of any story taller than the viewport).
|
|
80
80
|
|
|
81
|
+
`viewport` applies for the whole test, not just the screenshot: mount and `play()` render at it too. `@storybook/addon-vitest` would otherwise silently mount/run every story at its own fixed 1200x900 default instead.
|
|
82
|
+
|
|
81
83
|
```ts
|
|
82
84
|
import path from 'node:path'
|
|
83
85
|
import { fileURLToPath } from 'node:url'
|
package/lib/vitest-plugin.d.ts
CHANGED
|
@@ -48,6 +48,12 @@ export declare function createStorybookProject({ name, rootDir, viewport, screen
|
|
|
48
48
|
}[];
|
|
49
49
|
};
|
|
50
50
|
setupFiles: string[];
|
|
51
|
+
provide: {
|
|
52
|
+
fohteStorybookAddonViewport: {
|
|
53
|
+
width: number;
|
|
54
|
+
height: number;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
51
57
|
maxWorkers?: number;
|
|
52
58
|
sequence?: {
|
|
53
59
|
groupOrder: number;
|
package/lib/vitest-plugin.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
1
2
|
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
2
4
|
import { storybookTest } from '@storybook/addon-vitest/vitest-plugin';
|
|
3
5
|
import storycap from '@storycap-testrun/browser/vitest-plugin';
|
|
4
6
|
import { playwright } from '@vitest/browser-playwright';
|
|
@@ -47,6 +49,17 @@ export function createStorybookProject({ name, rootDir, viewport, screenshotsSub
|
|
|
47
49
|
const configDir = path.join(rootDir, '.storybook');
|
|
48
50
|
const screenshotsDir = path.join(rootDir, '__screenshots__', screenshotsSubdir);
|
|
49
51
|
const maxWorkers = process.env['CI'] != null ? ciMaxWorkers : undefined;
|
|
52
|
+
const viewportSetupFile = fileURLToPath(import.meta.resolve('#vitest-viewport-setup.js'));
|
|
53
|
+
// `import.meta.resolve` maps `#*.js` straight to `./lib/*.js` (this
|
|
54
|
+
// package's own build output) without checking the file exists — running
|
|
55
|
+
// against a fresh clone or a stale `lib/` (before `pnpm run build`, or
|
|
56
|
+
// after editing vitest-viewport-setup.ts without rebuilding) would
|
|
57
|
+
// otherwise leave Vitest to fail on a missing/stale setupFile with no clue
|
|
58
|
+
// this is why.
|
|
59
|
+
if (!existsSync(viewportSetupFile)) {
|
|
60
|
+
// eslint-disable-next-line no-restricted-syntax -- config-load-time invariant check, mirrors storycapNetworkIdle's fail-fast pattern above
|
|
61
|
+
throw new Error(`createStorybookProject: ${viewportSetupFile} not found. Run \`pnpm run build\` first.`);
|
|
62
|
+
}
|
|
50
63
|
const plugins = [
|
|
51
64
|
storycapNetworkIdle,
|
|
52
65
|
storybookTest({
|
|
@@ -107,7 +120,17 @@ export function createStorybookProject({ name, rootDir, viewport, screenshotsSub
|
|
|
107
120
|
headless: true,
|
|
108
121
|
instances: [{ browser: 'chromium' }],
|
|
109
122
|
},
|
|
110
|
-
|
|
123
|
+
// @storybook/addon-vitest overrides the story viewport to its own
|
|
124
|
+
// 1200x900 default right before mount/play() unless
|
|
125
|
+
// parameters.viewport/globals.viewport are set — vitest-viewport-setup.ts
|
|
126
|
+
// sets them via setProjectAnnotations() so mount/play() see the same
|
|
127
|
+
// `viewport` as the Playwright page and the screenshot above. It must
|
|
128
|
+
// run after the consumer's own setupFiles in case any of them also
|
|
129
|
+
// call setProjectAnnotations().
|
|
130
|
+
setupFiles: [...setupFiles, viewportSetupFile],
|
|
131
|
+
provide: {
|
|
132
|
+
fohteStorybookAddonViewport: viewport,
|
|
133
|
+
},
|
|
111
134
|
},
|
|
112
135
|
};
|
|
113
136
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { setProjectAnnotations } from 'storybook/preview-api';
|
|
2
|
+
import { getProjectAnnotations } from 'virtual:/@storybook/builder-vite/project-annotations.js';
|
|
3
|
+
import { beforeEach, inject } from 'vitest';
|
|
4
|
+
const VIEWPORT_NAME = '__fohteStorybookAddonViewport';
|
|
5
|
+
const { width, height } = inject('fohteStorybookAddonViewport');
|
|
6
|
+
// setProjectAnnotations() replaces the project annotations wholesale rather
|
|
7
|
+
// than merging into them, so composing in the consumer's own
|
|
8
|
+
// getProjectAnnotations() first is required — passing only the viewport
|
|
9
|
+
// override below would drop the consumer's own preview.ts
|
|
10
|
+
// renderer/decorators/loaders. Both are static per test file (the consumer's
|
|
11
|
+
// preview.ts and this project's `viewport` don't change mid-run), so this is
|
|
12
|
+
// computed once at setup-file top level rather than inside beforeEach below.
|
|
13
|
+
const projectAnnotations = getProjectAnnotations();
|
|
14
|
+
const viewportOverride = {
|
|
15
|
+
parameters: {
|
|
16
|
+
viewport: {
|
|
17
|
+
defaultViewport: VIEWPORT_NAME,
|
|
18
|
+
viewports: {
|
|
19
|
+
[VIEWPORT_NAME]: {
|
|
20
|
+
name: 'createStorybookProject viewport',
|
|
21
|
+
styles: {
|
|
22
|
+
width: `${String(width)}px`,
|
|
23
|
+
height: `${String(height)}px`,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
initialGlobals: { viewport: { value: VIEWPORT_NAME } },
|
|
30
|
+
};
|
|
31
|
+
// @storybook/addon-vitest's own testStory() calls setViewport() right before
|
|
32
|
+
// mount/play(), falling back to its built-in 1200x900 default whenever
|
|
33
|
+
// parameters.viewport/globals.viewport aren't set — silently overriding the
|
|
34
|
+
// `viewport` createStorybookProject() was given for the screenshot capture
|
|
35
|
+
// itself. setProjectAnnotations() is the public integration point Storybook
|
|
36
|
+
// added for exactly this in 10.3.
|
|
37
|
+
//
|
|
38
|
+
// The call itself runs in beforeEach, not at setup-file top level:
|
|
39
|
+
// @storybook/addon-vitest always injects its own
|
|
40
|
+
// internal/setup-file-with-project-annotations alongside consumer
|
|
41
|
+
// setupFiles — its "already provisioned" detection only looks inside the
|
|
42
|
+
// consumer's `.storybook` dir, which this file isn't in. That file's
|
|
43
|
+
// top-level setProjectAnnotations(getProjectAnnotations()) call would run
|
|
44
|
+
// after this file's own top level and silently wipe this override.
|
|
45
|
+
// beforeEach always runs after every setupFile finishes loading, so calling
|
|
46
|
+
// setProjectAnnotations() here instead wins regardless of setupFiles order.
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
setProjectAnnotations([projectAnnotations, viewportOverride]);
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=vitest-viewport-setup.js.map
|
package/package.json
CHANGED
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
"@storybook/addon-vitest": "10.5.8",
|
|
60
60
|
"@storybook/html-vite": "10.5.8",
|
|
61
61
|
"@storycap-testrun/browser": "2.1.1",
|
|
62
|
-
"@tsconfig/node-lts": "24.0.
|
|
62
|
+
"@tsconfig/node-lts": "24.0.1",
|
|
63
63
|
"@tsconfig/strictest": "2.0.8",
|
|
64
64
|
"@types/jsdom": "30.0.0",
|
|
65
65
|
"@types/node": "24.13.3",
|
|
66
66
|
"@vitest/browser-playwright": "4.1.10",
|
|
67
|
-
"concurrently": "10.0.
|
|
67
|
+
"concurrently": "10.0.5",
|
|
68
68
|
"eslint": "10.6.0",
|
|
69
69
|
"jsdom": "30.0.1",
|
|
70
70
|
"playwright": "1.62.1",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"typescript": "6.0.3",
|
|
75
75
|
"vitest": "4.1.10"
|
|
76
76
|
},
|
|
77
|
-
"version": "0.1.
|
|
77
|
+
"version": "0.1.6",
|
|
78
78
|
"scripts": {
|
|
79
79
|
"clean": "rimraf lib tsconfig.tsbuildinfo",
|
|
80
80
|
"prebuild": "pnpm run clean",
|