@fohte/storybook-addon 0.1.8 → 0.1.9

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 CHANGED
@@ -112,6 +112,17 @@ Screenshots for a project land in `<rootDir>/__screenshots__/<screenshotsSubdir>
112
112
 
113
113
  `storycapNetworkIdle` and `storycapFullPageStitch` are also exported on their own, for building a project without `createStorybookProject`. `storycapFullPageStitch` must be placed after storycap's own plugin in the `plugins` array — it works by overriding the `__storycap_takeScreenshot` command storycap registers, and Vite resolves conflicting plugin `config()` keys in plugin order, later wins.
114
114
 
115
+ `createStorybookProject` blocks non-`localhost` network requests in the browser by passing `BLOCK_EXTERNAL_REQUESTS_ARGS` to `playwright()`'s `launchOptions.args`, so a story can't depend on an external CDN request completing before the test's `afterEach` runs. It's a Chromium-only launch flag (matching `createStorybookProject`'s own `instances: [{ browser: 'chromium' }]`) — a `firefox`/`webkit` instance would silently get no blocking at all. If you build your `playwright()` call by hand instead of using `createStorybookProject`, spread this in yourself:
116
+
117
+ ```ts
118
+ import { BLOCK_EXTERNAL_REQUESTS_ARGS } from '@fohte/storybook-addon/vitest-plugin'
119
+ import { playwright } from '@vitest/browser-playwright'
120
+
121
+ playwright({
122
+ launchOptions: { args: [...BLOCK_EXTERNAL_REQUESTS_ARGS] },
123
+ })
124
+ ```
125
+
115
126
  Your `setupFiles` entry needs an `afterEach` that calls storycap's own `screenshot()` — see [`@storycap-testrun/browser`'s "Setup Screenshot Capture"](https://github.com/reg-viz/storycap-testrun/tree/main/packages/browser#2-setup-screenshot-capture) for the exact shape. Don't call `setProjectAnnotations()` there, and don't even mention that identifier in a comment: `@storybook/addon-vitest` decides whether to inject this package's checks by a plain substring search over the setup file's source text, so its mere presence silently disables every check in the project, with no error.
116
127
 
117
128
  ### Check failures don't block the screenshot
@@ -1,9 +1,9 @@
1
- import { assert } from 'vitest';
2
1
  export function throwIfNotEmpty(urls, message) {
3
2
  if (urls.length === 0)
4
3
  return;
5
4
  const list = urls.join('\n');
6
5
  urls.length = 0;
7
- assert.fail(`${message}:\n${list}`);
6
+ // eslint-disable-next-line no-restricted-syntax -- interop boundary: Storybook's afterEach (preview.ts) only reports a check as a story failure when assert() throws
7
+ throw new Error(`${message}:\n${list}`);
8
8
  }
9
9
  //# sourceMappingURL=check.js.map
@@ -13,9 +13,16 @@ function isExternalResourceUrl(url) {
13
13
  return ((protocol === 'http:' || protocol === 'https:') &&
14
14
  origin !== window.location.origin);
15
15
  }
16
+ function isPerformanceResourceTiming(entry) {
17
+ return entry.entryType === 'resource';
18
+ }
16
19
  new PerformanceObserver((list) => {
17
20
  for (const entry of list.getEntries()) {
18
- if (entry.startTime >= resetAt && isExternalResourceUrl(entry.name)) {
21
+ if (!isPerformanceResourceTiming(entry))
22
+ continue;
23
+ // Entries are queued at completion, so responseEnd (not startTime) is
24
+ // what must be compared against resetAt.
25
+ if (entry.responseEnd >= resetAt && isExternalResourceUrl(entry.name)) {
19
26
  externalResourceUrls.push(entry.name);
20
27
  }
21
28
  }
@@ -3,6 +3,7 @@ export declare const storycapNetworkIdle: {
3
3
  name: string;
4
4
  transform(code: string, id: string): string | null;
5
5
  };
6
+ export declare const BLOCK_EXTERNAL_REQUESTS_ARGS: string[];
6
7
  export interface CreateStorybookProjectOptions {
7
8
  /** Project name, as shown by `vitest --project <name>`. */
8
9
  name: string;
@@ -45,6 +45,12 @@ export const storycapNetworkIdle = {
45
45
  return patched;
46
46
  },
47
47
  };
48
+ // Blocks all requests except to localhost (Vitest's dev server), so a story
49
+ // can't depend on an external CDN request finishing before `afterEach`.
50
+ // Doesn't affect Playwright's own CDP connection, which uses a local pipe, not DNS.
51
+ export const BLOCK_EXTERNAL_REQUESTS_ARGS = [
52
+ '--host-resolver-rules=MAP * ~NOTFOUND, EXCLUDE localhost',
53
+ ];
48
54
  export function createStorybookProject({ name, rootDir, viewport, screenshotsSubdir, setupFiles, excludeTags = [], ciMaxWorkers = 8, }) {
49
55
  const configDir = path.join(rootDir, '.storybook');
50
56
  const screenshotsDir = path.join(rootDir, '__screenshots__', screenshotsSubdir);
@@ -116,6 +122,7 @@ export function createStorybookProject({ name, rootDir, viewport, screenshotsSub
116
122
  // silently truncates every fullPage tile's clip rect below it.
117
123
  provider: playwright({
118
124
  contextOptions: { timezoneId: 'Asia/Tokyo', viewport },
125
+ launchOptions: { args: [...BLOCK_EXTERNAL_REQUESTS_ARGS] },
119
126
  }),
120
127
  headless: true,
121
128
  instances: [{ browser: 'chromium' }],
package/package.json CHANGED
@@ -74,7 +74,7 @@
74
74
  "typescript": "6.0.3",
75
75
  "vitest": "4.1.11"
76
76
  },
77
- "version": "0.1.8",
77
+ "version": "0.1.9",
78
78
  "scripts": {
79
79
  "clean": "rimraf lib tsconfig.tsbuildinfo",
80
80
  "prebuild": "pnpm run clean",