storybook-addon-vis 2.1.5 → 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/dist/contants-DcocjING.mjs +7 -0
- package/dist/contants-DcocjING.mjs.map +1 -0
- package/dist/global_matcher_augment-CYxLwns2.d.ts +10 -0
- package/dist/global_matcher_augment-CYxLwns2.d.ts.map +1 -0
- package/dist/index.d.ts +26 -36
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -22
- package/dist/index.js.map +1 -1
- package/dist/manager.d.ts +1 -0
- package/dist/manager.js +85 -1
- package/dist/manager.js.map +1 -1
- package/dist/matcher.d.ts +1 -8
- package/dist/matcher.js +0 -3
- package/dist/node.d.mts +77 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +23 -0
- package/dist/node.mjs.map +1 -0
- package/dist/preset.d.mts +8 -0
- package/dist/preset.d.mts.map +1 -0
- package/dist/preset.mjs +72 -0
- package/dist/preset.mjs.map +1 -0
- package/dist/types-BG2k_RS_.d.mts +22 -0
- package/dist/types-BG2k_RS_.d.mts.map +1 -0
- package/dist/vis_annotation-Dpsgn_4P.js +74 -0
- package/dist/vis_annotation-Dpsgn_4P.js.map +1 -0
- package/dist/vitest-plugin.d.mts +9 -0
- package/dist/vitest-plugin.d.mts.map +1 -0
- package/dist/vitest-plugin.mjs +17 -0
- package/dist/vitest-plugin.mjs.map +1 -0
- package/dist/vitest-setup.d.ts +13 -11
- package/dist/vitest-setup.d.ts.map +1 -0
- package/dist/vitest-setup.js +7 -20
- package/dist/vitest-setup.js.map +1 -1
- package/package.json +40 -35
- package/preset.js +1 -1
- package/readme.md +3 -614
- package/src/client/storybook/tags.ts +6 -1
- package/src/client/vitest_proxy.ts +3 -3
- package/src/components/vis_panel.tsx +1 -1
- package/src/index.ts +10 -1
- package/src/manager.tsx +1 -1
- package/src/node/define_storybook_vis.mdx +211 -0
- package/src/node/define_storybook_vis.ts +68 -0
- package/src/node/define_storybook_vis_options.mdx +185 -0
- package/src/node/define_storybook_vis_options.ts +8 -0
- package/src/node/overview.mdx +10 -0
- package/src/node.ts +2 -0
- package/src/overview.mdx +587 -5
- package/src/preset.ts +1 -1
- package/src/preview/vis_annotation.ts +4 -4
- package/src/releases/migrate_to_1.0.mdx +55 -0
- package/src/releases/migrate_to_3.0.mdx +13 -0
- package/src/server/create_storybook_vis_server.ts +1 -1
- package/src/server/{vis_options.ts → types.ts} +0 -7
- package/dist/chunk-HQDMSJMI.cjs +0 -60
- package/dist/chunk-HQDMSJMI.cjs.map +0 -1
- package/dist/chunk-UOITZV6D.js +0 -55
- package/dist/chunk-UOITZV6D.js.map +0 -1
- package/dist/index.cjs +0 -50
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -48
- package/dist/matcher.cjs +0 -4
- package/dist/matcher.cjs.map +0 -1
- package/dist/matcher.d.cts +0 -8
- package/dist/matcher.js.map +0 -1
- package/dist/preset.cjs +0 -2
- package/dist/preset.cjs.map +0 -1
- package/dist/vitest-plugin.d.ts +0 -11
- package/dist/vitest-plugin.js +0 -22
- package/dist/vitest-plugin.js.map +0 -1
- package/dist/vitest-setup.cjs +0 -29
- package/dist/vitest-setup.cjs.map +0 -1
- package/dist/vitest-setup.d.cts +0 -15
- package/src/advance_setup.mdx +0 -191
- package/src/basic_setup.mdx +0 -121
- package/src/installation.mdx +0 -27
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contants-DcocjING.mjs","names":[],"sources":["../src/shared/contants.ts"],"sourcesContent":["export const NAME = 'storybook-addon-vis'\nexport const VIS_PANEL_ID = `${NAME}/vis_panel`\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,eAAe,GAAG,KAAK"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ImageSnapshotMatcher } from "vitest-plugin-vis/client-api";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/global_matcher_augment.d.ts
|
|
4
|
+
declare global {
|
|
5
|
+
namespace jest {
|
|
6
|
+
interface Matchers<R, T> extends ImageSnapshotMatcher {}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=global_matcher_augment.d.ts.map
|
|
10
|
+
//# sourceMappingURL=global_matcher_augment-CYxLwns2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global_matcher_augment-CYxLwns2.d.ts","names":[],"sources":["../src/shared/global_matcher_augment.ts"],"sourcesContent":[],"mappings":";;;;;IAEwE,UAAA,QAAA,CAAA,CAAA,EAAA,CAAA,CAAA,SAKrC,oBALqC,CAAA,CAAA;EAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,48 +1,38 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import "./global_matcher_augment-CYxLwns2.js";
|
|
2
|
+
import { ComparisonMethod, FailureThresholdOptions, ImageSnapshotCompareOptions, ImageSnapshotKeyOptions, ImageSnapshotKeyOptions as ImageSnapshotKeyOptions$1, ImageSnapshotSubjectOptions, ImageSnapshotTimeoutOptions, PixelComparisonOptions, SsimComparisonOptions, ToMatchImageSnapshotOptions } from "vitest-plugin-vis/client-api";
|
|
3
|
+
import { SetupVisOptions } from "vitest-plugin-vis/setup";
|
|
4
|
+
import { BrowserPage } from "vitest/browser";
|
|
5
|
+
import "vitest/suite";
|
|
6
|
+
import * as storybook_internal_csf0 from "storybook/internal/csf";
|
|
7
|
+
export * from "vitest-plugin-vis";
|
|
6
8
|
|
|
9
|
+
//#region src/client/vitest_proxy.d.ts
|
|
7
10
|
declare const page: BrowserPage;
|
|
8
|
-
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/client/has_image_snapshot.d.ts
|
|
9
13
|
/**
|
|
10
14
|
* Check if the snapshot image exists.
|
|
11
15
|
*/
|
|
12
|
-
declare function hasImageSnapshot(options?: ImageSnapshotKeyOptions | undefined): false | Promise<boolean>;
|
|
13
|
-
|
|
16
|
+
declare function hasImageSnapshot(options?: ImageSnapshotKeyOptions$1 | undefined): false | Promise<boolean>;
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/client/storybook/param.d.ts
|
|
14
19
|
/**
|
|
15
20
|
* Define snapshot parameter for auto snapshot.
|
|
16
21
|
*/
|
|
17
22
|
declare function defineAutoSnapshotParam<M extends ComparisonMethod>(snapshot: ToMatchImageSnapshotOptions<M> & ImageSnapshotSubjectOptions): {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
snapshot: ImageSnapshotTimeoutOptions & ImageSnapshotKeyOptions & (M extends "ssim" ? SsimComparisonOptions<M> : PixelComparisonOptions<M>) & FailureThresholdOptions & {
|
|
24
|
+
expectToFail?: boolean | undefined;
|
|
25
|
+
} & ImageSnapshotSubjectOptions;
|
|
21
26
|
};
|
|
22
|
-
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/client/storybook/tags.d.ts
|
|
23
29
|
declare function isSnapshotEnabled(tags: string[]): boolean;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* @param options.visProjects[].snapshotRootDir Root directory for storing snapshots. Can be a string path or a function that returns a path based on CI and platform context
|
|
30
|
-
* @param options.visProjects[].snapshotSubpath Optional function to customize the snapshot subdirectory path
|
|
31
|
-
*/
|
|
32
|
-
type StorybookVisOptions = {
|
|
33
|
-
visProjects: Array<{
|
|
34
|
-
snapshotRootDir: string | ((context: {
|
|
35
|
-
ci: boolean;
|
|
36
|
-
platform: string;
|
|
37
|
-
}) => string) | undefined;
|
|
38
|
-
snapshotSubpath?: ((options: {
|
|
39
|
-
subpath: string;
|
|
40
|
-
}) => string) | undefined;
|
|
41
|
-
}>;
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/index.d.ts
|
|
32
|
+
declare const _default: (options?: SetupVisOptions) => {
|
|
33
|
+
beforeEach(ctx: storybook_internal_csf0.StoryContext<any, storybook_internal_csf0.Args>): void;
|
|
34
|
+
tags: string[];
|
|
42
35
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
declare function defineStorybookVisOptions(options: StorybookVisOptions): StorybookVisOptions;
|
|
47
|
-
|
|
48
|
-
export { type StorybookVisOptions, defineAutoSnapshotParam, defineStorybookVisOptions, hasImageSnapshot, isSnapshotEnabled, page };
|
|
36
|
+
//#endregion
|
|
37
|
+
export { type ComparisonMethod, type FailureThresholdOptions, type ImageSnapshotCompareOptions, type ImageSnapshotKeyOptions, type ImageSnapshotSubjectOptions, type ImageSnapshotTimeoutOptions, type PixelComparisonOptions, type SsimComparisonOptions, type ToMatchImageSnapshotOptions, _default as default, defineAutoSnapshotParam, hasImageSnapshot, isSnapshotEnabled, page };
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/client/vitest_proxy.ts","../src/client/has_image_snapshot.ts","../src/client/storybook/param.ts","../src/client/storybook/tags.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;cAiBa,MAAI;;;;;;iBCVD,gBAAA,WAA2B,gDAAmC;;;;;;iBCqB9D,kCAAkC,4BACvC,4BAA4B,KAAK;;;;;;;iBC7B5B,iBAAA;;;cCaD,qBAEU;EJEZ,UAQX,CAAA,GAAA,sCAAA,CAAA,GAAA,EIV2C,uBAAA,CAAA,IAAA,CJU3C,CAAA,EAAA,IAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,33 +1,47 @@
|
|
|
1
|
-
import { getCurrentTest, commands } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { hasImageSnapshotAction, toTaskId } from 'vitest-plugin-vis/client-api';
|
|
1
|
+
import { a as page, i as getCurrentTest, n as isSnapshotEnabled, r as commands, t as visAnnotations } from "./vis_annotation-Dpsgn_4P.js";
|
|
2
|
+
import { hasImageSnapshotAction, toTaskId } from "vitest-plugin-vis/client-api";
|
|
3
|
+
import { vis } from "vitest-plugin-vis/setup";
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
export * from "vitest-plugin-vis"
|
|
6
|
+
|
|
7
|
+
//#region src/client/ctx.ts
|
|
8
|
+
const ctx = {
|
|
9
|
+
getCurrentTest,
|
|
10
|
+
__test__reset() {
|
|
11
|
+
ctx.getCurrentTest = getCurrentTest;
|
|
12
|
+
}
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/client/has_image_snapshot.ts
|
|
17
|
+
/**
|
|
18
|
+
* Check if the snapshot image exists.
|
|
19
|
+
*/
|
|
15
20
|
function hasImageSnapshot(options) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
const test = ctx.getCurrentTest();
|
|
22
|
+
if (!test) return false;
|
|
23
|
+
return hasImageSnapshotAction(commands, toTaskId(test), options);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/client/storybook/param.ts
|
|
28
|
+
/**
|
|
29
|
+
* Define snapshot parameter for auto snapshot.
|
|
30
|
+
*/
|
|
22
31
|
function defineAutoSnapshotParam(snapshot) {
|
|
23
|
-
|
|
32
|
+
return { snapshot };
|
|
24
33
|
}
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/index.ts
|
|
37
|
+
var src_default = (options = {}) => {
|
|
38
|
+
vis.setup(options);
|
|
39
|
+
return {
|
|
40
|
+
tags: options.auto ? ["snapshot"] : [],
|
|
41
|
+
...visAnnotations
|
|
42
|
+
};
|
|
43
|
+
};
|
|
30
44
|
|
|
31
|
-
|
|
32
|
-
|
|
45
|
+
//#endregion
|
|
46
|
+
export { src_default as default, defineAutoSnapshotParam, hasImageSnapshot, isSnapshotEnabled, page };
|
|
33
47
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/ctx.ts","../src/client/has_image_snapshot.ts","../src/client/storybook/param.ts","../src/
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/client/ctx.ts","../src/client/has_image_snapshot.ts","../src/client/storybook/param.ts","../src/index.ts"],"sourcesContent":["import { getCurrentTest } from './vitest_proxy.ts'\n\nexport const ctx = {\n\tgetCurrentTest,\n\t__test__reset() {\n\t\tctx.getCurrentTest = getCurrentTest\n\t},\n}\n","import { hasImageSnapshotAction, toTaskId, type ImageSnapshotKeyOptions } from 'vitest-plugin-vis/client-api'\nimport { ctx } from './ctx.ts'\nimport { commands } from './vitest_proxy.ts'\n\n/**\n * Check if the snapshot image exists.\n */\nexport function hasImageSnapshot(options?: ImageSnapshotKeyOptions | undefined) {\n\tconst test = ctx.getCurrentTest()\n\tif (!test) return false\n\n\treturn hasImageSnapshotAction(commands, toTaskId(test), options)\n}\n","import type {\n\tComparisonMethod,\n\tFailureThresholdOptions,\n\tImageSnapshotCompareOptions,\n\tImageSnapshotKeyOptions,\n\tImageSnapshotSubjectOptions,\n\tImageSnapshotTimeoutOptions,\n\tPixelComparisonOptions,\n\tSsimComparisonOptions,\n\tToMatchImageSnapshotOptions,\n} from 'vitest-plugin-vis/client-api'\n\n// This fix the inferred type cannot be named error\nexport type {\n\tComparisonMethod,\n\tFailureThresholdOptions,\n\tImageSnapshotCompareOptions,\n\tImageSnapshotKeyOptions,\n\tImageSnapshotSubjectOptions,\n\tImageSnapshotTimeoutOptions,\n\tPixelComparisonOptions,\n\tSsimComparisonOptions,\n\tToMatchImageSnapshotOptions,\n}\n\n/**\n * Define snapshot parameter for auto snapshot.\n */\nexport function defineAutoSnapshotParam<M extends ComparisonMethod>(\n\tsnapshot: ToMatchImageSnapshotOptions<M> & ImageSnapshotSubjectOptions,\n) {\n\treturn { snapshot }\n}\n","// `storybook-addon-vis` provides code that can be used in test files.\nimport './client/storybook/expect_extend.ts'\nimport './shared/global_matcher_augment.ts'\n\nimport { vis, type SetupVisOptions } from 'vitest-plugin-vis/setup'\nimport { page } from './client/vitest_proxy.ts'\nimport { visAnnotations } from './preview/vis_annotation.ts'\n\nexport * from 'vitest-plugin-vis'\nexport * from './client/has_image_snapshot.ts'\nexport * from './client/storybook/param.ts'\nexport * from './client/storybook/tags.ts'\n\nexport { page }\n\nexport default (options: SetupVisOptions = {}) => {\n\tvis.setup(options)\n\treturn {\n\t\ttags: options.auto ? ['snapshot'] : [],\n\t\t...visAnnotations,\n\t}\n}\n"],"mappings":";;;;;;;AAEA,MAAa,MAAM;CAClB;CACA,gBAAgB;AACf,MAAI,iBAAiB;;CAEtB;;;;;;;ACAD,SAAgB,iBAAiB,SAA+C;CAC/E,MAAM,OAAO,IAAI,gBAAgB;AACjC,KAAI,CAAC,KAAM,QAAO;AAElB,QAAO,uBAAuB,UAAU,SAAS,KAAK,EAAE,QAAQ;;;;;;;;ACiBjE,SAAgB,wBACf,UACC;AACD,QAAO,EAAE,UAAU;;;;;AChBpB,mBAAgB,UAA2B,EAAE,KAAK;AACjD,KAAI,MAAM,QAAQ;AAClB,QAAO;EACN,MAAM,QAAQ,OAAO,CAAC,WAAW,GAAG,EAAE;EACtC,GAAG;EACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/manager.js
CHANGED
|
@@ -1,2 +1,86 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React, { memo, useEffect, useState } from "react";
|
|
2
|
+
import { addons, types } from "storybook/manager-api";
|
|
3
|
+
import { RefreshIcon } from "@storybook/icons";
|
|
4
|
+
import { AddonPanel, IconButton, Placeholder, ScrollArea } from "storybook/internal/components";
|
|
5
|
+
import { styled } from "storybook/theming";
|
|
6
|
+
import { SNAPSHOT_ROOT_DIR } from "vitest-plugin-vis/client-api";
|
|
7
|
+
|
|
8
|
+
//#region src/components/vis_panel.tsx
|
|
9
|
+
const VisPanel = memo(function VisPanel$1({ active, snapshotResults = [], onRefresh }) {
|
|
10
|
+
const groupedResults = snapshotResults.reduce((acc, result) => {
|
|
11
|
+
const key = `(${result.snapshotRootDir.slice(SNAPSHOT_ROOT_DIR.length + 1)}) ${result.fileName}`;
|
|
12
|
+
acc[key] = [...acc[key] ?? [], result];
|
|
13
|
+
return acc;
|
|
14
|
+
}, {});
|
|
15
|
+
return /* @__PURE__ */ React.createElement(AddonPanel, { active }, snapshotResults.length > 0 ? /* @__PURE__ */ React.createElement(ScrollArea, { vertical: true }, Object.entries(groupedResults).map(([key, results]) => /* @__PURE__ */ React.createElement("div", { key }, results.some((result) => result.type === "diff") ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(SnapshotRow, { failed: true }, key), results.map((result) => /* @__PURE__ */ React.createElement("img", {
|
|
16
|
+
key: result.filePath,
|
|
17
|
+
src: `data:image/png;base64,${result.base64}`,
|
|
18
|
+
alt: result.fileName
|
|
19
|
+
}))) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(SnapshotRow, null, /* @__PURE__ */ React.createElement("span", null, key), /* @__PURE__ */ React.createElement(IconButton, { onClick: () => onRefresh() }, /* @__PURE__ */ React.createElement(RefreshIcon, null))), /* @__PURE__ */ React.createElement("img", {
|
|
20
|
+
key: results[0].filePath,
|
|
21
|
+
src: `data:image/png;base64,${results[0].base64}`,
|
|
22
|
+
alt: results[0].fileName
|
|
23
|
+
}))))) : /* @__PURE__ */ React.createElement(Placeholder, null, "There is no snapshots for this story"));
|
|
24
|
+
});
|
|
25
|
+
const SnapshotRow = styled.div(({ theme, failed }) => ({
|
|
26
|
+
display: "flex",
|
|
27
|
+
alignItems: "center",
|
|
28
|
+
gap: "0.5rem",
|
|
29
|
+
paddingBlock: "0.5rem",
|
|
30
|
+
paddingInline: "0.2rem",
|
|
31
|
+
backgroundColor: failed ? theme.background.negative : theme.background.positive,
|
|
32
|
+
color: theme.barTextColor
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/shared/contants.ts
|
|
37
|
+
const NAME = "storybook-addon-vis";
|
|
38
|
+
const VIS_PANEL_ID = `${NAME}/vis_panel`;
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/shared/events.ts
|
|
42
|
+
const IMAGE_SNAPSHOT_RESULTS_REQUEST = "IMAGE_SNAPSHOT_RESULTS_REQUEST";
|
|
43
|
+
const IMAGE_SNAPSHOT_RESULTS_RESPONSE = "IMAGE_SNAPSHOT_RESULTS_RESPONSE";
|
|
44
|
+
function requestImageSnapshotResults({ name, importPath }) {
|
|
45
|
+
return {
|
|
46
|
+
type: IMAGE_SNAPSHOT_RESULTS_REQUEST,
|
|
47
|
+
name,
|
|
48
|
+
importPath
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/manager.tsx
|
|
54
|
+
addons.register(NAME, (api) => {
|
|
55
|
+
if (globalThis.CONFIG_TYPE === "DEVELOPMENT") addons.add(VIS_PANEL_ID, {
|
|
56
|
+
type: types.PANEL,
|
|
57
|
+
title: "Vis",
|
|
58
|
+
match: ({ tabId, viewMode }) => !tabId && viewMode === "story",
|
|
59
|
+
render({ active }) {
|
|
60
|
+
const [snapshotResults, setSnapshotResults] = useState([]);
|
|
61
|
+
const storyData = api.getCurrentStoryData();
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const disposes = [api.on(NAME, (event) => {
|
|
64
|
+
if (event.name !== storyData.name) return;
|
|
65
|
+
if (event.importPath !== storyData.importPath) return;
|
|
66
|
+
if (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) setSnapshotResults(event.results);
|
|
67
|
+
})];
|
|
68
|
+
api.emit(NAME, requestImageSnapshotResults(storyData));
|
|
69
|
+
return () => disposes.forEach((dispose) => {
|
|
70
|
+
dispose();
|
|
71
|
+
});
|
|
72
|
+
}, [storyData]);
|
|
73
|
+
if (!active) return null;
|
|
74
|
+
return /* @__PURE__ */ React.createElement(VisPanel, {
|
|
75
|
+
active,
|
|
76
|
+
snapshotResults,
|
|
77
|
+
onRefresh: () => {
|
|
78
|
+
api.emit(NAME, requestImageSnapshotResults(storyData));
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
2
86
|
//# sourceMappingURL=manager.js.map
|
package/dist/manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/vis_panel.tsx","../src/shared/contants.ts","../src/shared/events.ts","../src/manager.tsx"],"
|
|
1
|
+
{"version":3,"file":"manager.js","names":["VisPanel"],"sources":["../src/components/vis_panel.tsx","../src/shared/contants.ts","../src/shared/events.ts","../src/manager.tsx"],"sourcesContent":["import { RefreshIcon } from '@storybook/icons'\nimport React, { memo } from 'react'\nimport { AddonPanel, IconButton, Placeholder, ScrollArea } from 'storybook/internal/components'\nimport { styled } from 'storybook/theming'\nimport { SNAPSHOT_ROOT_DIR } from 'vitest-plugin-vis/client-api'\nimport type { ImageSnapshotResults } from '../shared/events.ts'\n\ninterface PanelProps {\n\tactive: boolean\n\tsnapshotResults: ImageSnapshotResults[]\n\tonRefresh: () => void\n}\n\nexport const VisPanel = memo(function VisPanel({ active, snapshotResults = [], onRefresh }: PanelProps) {\n\tconst groupedResults = snapshotResults.reduce(\n\t\t(acc, result) => {\n\t\t\tconst suiteName = result.snapshotRootDir.slice(SNAPSHOT_ROOT_DIR.length + 1)\n\t\t\tconst key = `(${suiteName}) ${result.fileName}`\n\t\t\tacc[key] = [...(acc[key] ?? []), result]\n\t\t\treturn acc\n\t\t},\n\t\t{} as Record<string, ImageSnapshotResults[]>,\n\t)\n\treturn (\n\t\t<AddonPanel active={active}>\n\t\t\t{snapshotResults.length > 0 ? (\n\t\t\t\t<ScrollArea vertical>\n\t\t\t\t\t{Object.entries(groupedResults).map(([key, results]) => (\n\t\t\t\t\t\t<div key={key}>\n\t\t\t\t\t\t\t{results.some((result) => result.type === 'diff') ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<SnapshotRow failed>{key}</SnapshotRow>\n\t\t\t\t\t\t\t\t\t{results.map((result) => (\n\t\t\t\t\t\t\t\t\t\t<img key={result.filePath} src={`data:image/png;base64,${result.base64}`} alt={result.fileName} />\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<SnapshotRow>\n\t\t\t\t\t\t\t\t\t\t<span>{key}</span>\n\t\t\t\t\t\t\t\t\t\t<IconButton onClick={() => onRefresh()}>\n\t\t\t\t\t\t\t\t\t\t\t<RefreshIcon />\n\t\t\t\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t\t\t\t</SnapshotRow>\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tkey={results[0].filePath}\n\t\t\t\t\t\t\t\t\t\tsrc={`data:image/png;base64,${results[0].base64}`}\n\t\t\t\t\t\t\t\t\t\talt={results[0].fileName}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</ScrollArea>\n\t\t\t) : (\n\t\t\t\t<Placeholder>There is no snapshots for this story</Placeholder>\n\t\t\t)}\n\t\t</AddonPanel>\n\t)\n})\n\nconst SnapshotRow = styled.div<{ failed?: boolean }>(({ theme, failed }) => ({\n\tdisplay: 'flex',\n\talignItems: 'center',\n\tgap: '0.5rem',\n\tpaddingBlock: '0.5rem',\n\tpaddingInline: '0.2rem',\n\tbackgroundColor: failed ? theme.background.negative : theme.background.positive,\n\tcolor: theme.barTextColor,\n}))\n","export const NAME = 'storybook-addon-vis'\nexport const VIS_PANEL_ID = `${NAME}/vis_panel`\n","export type VisEvent = ImageSnapshotResultsRequest | ImageSnapshotResultsResponse\n\nexport const IMAGE_SNAPSHOT_RESULTS_REQUEST = 'IMAGE_SNAPSHOT_RESULTS_REQUEST'\nexport const IMAGE_SNAPSHOT_RESULTS_RESPONSE = 'IMAGE_SNAPSHOT_RESULTS_RESPONSE'\n\nexport function requestImageSnapshotResults({ name, importPath }: { name: string; importPath: string }) {\n\treturn {\n\t\ttype: IMAGE_SNAPSHOT_RESULTS_REQUEST,\n\t\tname,\n\t\timportPath,\n\t}\n}\n\nexport type ImageSnapshotResultsRequest = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_REQUEST\n\tname: string\n\timportPath: string\n}\n\nexport type ImageSnapshotResultsResponse = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_RESPONSE\n\tname: string\n\timportPath: string\n\tresults: ImageSnapshotResults[]\n}\n\nexport type ImageSnapshotResults = {\n\tfilePath: string\n\tfileName: string\n\tsnapshotRootDir: string\n\ttype: 'baseline' | 'diff' | 'result'\n\tbase64: string\n}\n","import React, { useEffect, useState } from 'react'\nimport { addons, types } from 'storybook/manager-api'\nimport { VisPanel } from './components/vis_panel.tsx'\nimport { NAME, VIS_PANEL_ID } from './shared/contants.ts'\nimport {\n\tIMAGE_SNAPSHOT_RESULTS_RESPONSE,\n\trequestImageSnapshotResults,\n\ttype ImageSnapshotResults,\n\ttype VisEvent,\n} from './shared/events.ts'\n\n// Register the addon\naddons.register(NAME, (api) => {\n\t// Register the tool\n\tif ((globalThis as any).CONFIG_TYPE === 'DEVELOPMENT') {\n\t\taddons.add(VIS_PANEL_ID, {\n\t\t\ttype: types.PANEL,\n\t\t\ttitle: 'Vis',\n\t\t\tmatch: ({ tabId, viewMode }) => !tabId && viewMode === 'story',\n\t\t\trender({ active }) {\n\t\t\t\tconst [snapshotResults, setSnapshotResults] = useState<ImageSnapshotResults[]>([])\n\n\t\t\t\tconst storyData = api.getCurrentStoryData()\n\n\t\t\t\tuseEffect(() => {\n\t\t\t\t\tconst disposes = [\n\t\t\t\t\t\tapi.on(NAME, (event: VisEvent) => {\n\t\t\t\t\t\t\tif (event.name !== storyData.name) return\n\t\t\t\t\t\t\tif (event.importPath !== storyData.importPath) return\n\n\t\t\t\t\t\t\tif (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) {\n\t\t\t\t\t\t\t\tsetSnapshotResults(event.results)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t// api.on('UNIVERSAL_STORE:storybook/test', (event) => {\n\t\t\t\t\t\t// \tconsole.log('storybook/test', event)\n\t\t\t\t\t\t// }),\n\t\t\t\t\t]\n\t\t\t\t\tapi.emit(NAME, requestImageSnapshotResults(storyData))\n\t\t\t\t\treturn () =>\n\t\t\t\t\t\tdisposes.forEach((dispose) => {\n\t\t\t\t\t\t\tdispose()\n\t\t\t\t\t\t})\n\t\t\t\t}, [storyData])\n\n\t\t\t\tif (!active) return null\n\n\t\t\t\treturn (\n\t\t\t\t\t<VisPanel\n\t\t\t\t\t\tactive={active}\n\t\t\t\t\t\tsnapshotResults={snapshotResults}\n\t\t\t\t\t\tonRefresh={() => {\n\t\t\t\t\t\t\tapi.emit(NAME, requestImageSnapshotResults(storyData))\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t},\n\t\t})\n\t}\n})\n"],"mappings":";;;;;;;;AAaA,MAAa,WAAW,KAAK,SAASA,WAAS,EAAE,QAAQ,kBAAkB,EAAE,EAAE,aAAyB;CACvG,MAAM,iBAAiB,gBAAgB,QACrC,KAAK,WAAW;EAEhB,MAAM,MAAM,IADM,OAAO,gBAAgB,MAAM,kBAAkB,SAAS,EAAE,CAClD,IAAI,OAAO;AACrC,MAAI,OAAO,CAAC,GAAI,IAAI,QAAQ,EAAE,EAAG,OAAO;AACxC,SAAO;IAER,EAAE,CACF;AACD,QACC,oCAAC,cAAmB,UAClB,gBAAgB,SAAS,IACzB,oCAAC,cAAW,kBACV,OAAO,QAAQ,eAAe,CAAC,KAAK,CAAC,KAAK,aAC1C,oCAAC,SAAS,OACR,QAAQ,MAAM,WAAW,OAAO,SAAS,OAAO,GAChD,0DACC,oCAAC,eAAY,gBAAQ,IAAkB,EACtC,QAAQ,KAAK,WACb,oCAAC;EAAI,KAAK,OAAO;EAAU,KAAK,yBAAyB,OAAO;EAAU,KAAK,OAAO;GAAY,CACjG,CACA,GAEH,0DACC,oCAAC,mBACA,oCAAC,cAAM,IAAW,EAClB,oCAAC,cAAW,eAAe,WAAW,IACrC,oCAAC,kBAAc,CACH,CACA,EACd,oCAAC;EACA,KAAK,QAAQ,GAAG;EAChB,KAAK,yBAAyB,QAAQ,GAAG;EACzC,KAAK,QAAQ,GAAG;GACf,CACA,CAEC,CACL,CACU,GAEb,oCAAC,mBAAY,uCAAkD,CAEpD;EAEb;AAEF,MAAM,cAAc,OAAO,KAA2B,EAAE,OAAO,cAAc;CAC5E,SAAS;CACT,YAAY;CACZ,KAAK;CACL,cAAc;CACd,eAAe;CACf,iBAAiB,SAAS,MAAM,WAAW,WAAW,MAAM,WAAW;CACvE,OAAO,MAAM;CACb,EAAE;;;;ACrEH,MAAa,OAAO;AACpB,MAAa,eAAe,GAAG,KAAK;;;;ACCpC,MAAa,iCAAiC;AAC9C,MAAa,kCAAkC;AAE/C,SAAgB,4BAA4B,EAAE,MAAM,cAAoD;AACvG,QAAO;EACN,MAAM;EACN;EACA;EACA;;;;;ACEF,OAAO,SAAS,OAAO,QAAQ;AAE9B,KAAK,WAAmB,gBAAgB,cACvC,QAAO,IAAI,cAAc;EACxB,MAAM,MAAM;EACZ,OAAO;EACP,QAAQ,EAAE,OAAO,eAAe,CAAC,SAAS,aAAa;EACvD,OAAO,EAAE,UAAU;GAClB,MAAM,CAAC,iBAAiB,sBAAsB,SAAiC,EAAE,CAAC;GAElF,MAAM,YAAY,IAAI,qBAAqB;AAE3C,mBAAgB;IACf,MAAM,WAAW,CAChB,IAAI,GAAG,OAAO,UAAoB;AACjC,SAAI,MAAM,SAAS,UAAU,KAAM;AACnC,SAAI,MAAM,eAAe,UAAU,WAAY;AAE/C,SAAI,MAAM,SAAS,gCAClB,oBAAmB,MAAM,QAAQ;MAEjC,CAIF;AACD,QAAI,KAAK,MAAM,4BAA4B,UAAU,CAAC;AACtD,iBACC,SAAS,SAAS,YAAY;AAC7B,cAAS;MACR;MACD,CAAC,UAAU,CAAC;AAEf,OAAI,CAAC,OAAQ,QAAO;AAEpB,UACC,oCAAC;IACQ;IACS;IACjB,iBAAiB;AAChB,SAAI,KAAK,MAAM,4BAA4B,UAAU,CAAC;;KAEtD;;EAGJ,CAAC;EAEF"}
|
package/dist/matcher.d.ts
CHANGED
package/dist/matcher.js
CHANGED
package/dist/node.d.mts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { t as StorybookVisOptions } from "./types-BG2k_RS_.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/node/define_storybook_vis.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Defines the Storybook Visual Testing addon configuration.
|
|
7
|
+
*
|
|
8
|
+
* When called without options, returns the package directory name as a string.
|
|
9
|
+
* When called with options, returns an object containing both the package name and the provided options.
|
|
10
|
+
*
|
|
11
|
+
* @returns When called without options, returns the package directory path as a string.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* // Without options - returns just the package name
|
|
16
|
+
* const addonName = defineStorybookVis()
|
|
17
|
+
* // Returns: string (package directory path)
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // With options - returns object with name and options
|
|
23
|
+
* const addonConfig = defineStorybookVis({
|
|
24
|
+
* visProjects: [
|
|
25
|
+
* {
|
|
26
|
+
* snapshotRootDir: '__vis__/linux',
|
|
27
|
+
* },
|
|
28
|
+
* ],
|
|
29
|
+
* })
|
|
30
|
+
* // Returns: { name: string, options: StorybookVisOptions }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare function defineStorybookVis(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Defines the Storybook Visual Testing addon configuration with options.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Configuration options for visual testing suites in Storybook.
|
|
38
|
+
* @param options.visProjects - Array of visual testing project configurations.
|
|
39
|
+
* @param options.visProjects[].snapshotRootDir - Root directory for storing snapshots. Can be a string path or a function that returns a path based on CI and platform context.
|
|
40
|
+
* @param options.visProjects[].snapshotSubpath - Optional function to customize the snapshot subdirectory path.
|
|
41
|
+
*
|
|
42
|
+
* @returns An object containing the package name and the provided options.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // In .storybook/main.ts
|
|
47
|
+
* import { defineStorybookVis } from 'storybook-addon-vis/node'
|
|
48
|
+
*
|
|
49
|
+
* export default {
|
|
50
|
+
* addons: [
|
|
51
|
+
* defineStorybookVis({
|
|
52
|
+
* visProjects: [
|
|
53
|
+
* {
|
|
54
|
+
* snapshotRootDir: '__vis__/linux',
|
|
55
|
+
* },
|
|
56
|
+
* {
|
|
57
|
+
* snapshotRootDir: '__vis__/local',
|
|
58
|
+
* },
|
|
59
|
+
* ],
|
|
60
|
+
* }),
|
|
61
|
+
* ],
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
declare function defineStorybookVis(options: StorybookVisOptions): {
|
|
66
|
+
name: string;
|
|
67
|
+
options: StorybookVisOptions;
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/node/define_storybook_vis_options.d.ts
|
|
71
|
+
/**
|
|
72
|
+
* Define options for Storybook Visual Testing addon.
|
|
73
|
+
*/
|
|
74
|
+
declare function defineStorybookVisOptions(options: StorybookVisOptions): StorybookVisOptions;
|
|
75
|
+
//#endregion
|
|
76
|
+
export { defineStorybookVis, defineStorybookVisOptions };
|
|
77
|
+
//# sourceMappingURL=node.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.mts","names":[],"sources":["../src/node/define_storybook_vis.ts","../src/node/define_storybook_vis_options.ts"],"sourcesContent":[],"mappings":";;;;;;AA+BA;AAgCA;;;;AC1DA;;;;;;;;;;;;;;;;;;;;;iBD0BgB,kBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCA,kBAAA,UAA4B;;WAA+C;;;;;;AAhC3F;AAgCgB,iBC1DA,yBAAA,CD0D4B,OAA+C,EC1DxC,mBD0D2D,CAAA,EC1DxC,mBD0DwC"}
|
package/dist/node.mjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { dirname } from "node:path";
|
|
2
|
+
|
|
3
|
+
//#region src/node/define_storybook_vis.ts
|
|
4
|
+
function defineStorybookVis(options) {
|
|
5
|
+
const name = dirname(import.meta.resolve("storybook-addon-vis", "package.json"));
|
|
6
|
+
return !options ? name : {
|
|
7
|
+
name,
|
|
8
|
+
options
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/node/define_storybook_vis_options.ts
|
|
14
|
+
/**
|
|
15
|
+
* Define options for Storybook Visual Testing addon.
|
|
16
|
+
*/
|
|
17
|
+
function defineStorybookVisOptions(options) {
|
|
18
|
+
return options;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { defineStorybookVis, defineStorybookVisOptions };
|
|
23
|
+
//# sourceMappingURL=node.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.mjs","names":[],"sources":["../src/node/define_storybook_vis.ts","../src/node/define_storybook_vis_options.ts"],"sourcesContent":["import { dirname } from 'node:path'\nimport type { StorybookVisOptions } from '../server/types.ts'\n\n/**\n * Defines the Storybook Visual Testing addon configuration.\n *\n * When called without options, returns the package directory name as a string.\n * When called with options, returns an object containing both the package name and the provided options.\n *\n * @returns When called without options, returns the package directory path as a string.\n *\n * @example\n * ```ts\n * // Without options - returns just the package name\n * const addonName = defineStorybookVis()\n * // Returns: string (package directory path)\n * ```\n *\n * @example\n * ```ts\n * // With options - returns object with name and options\n * const addonConfig = defineStorybookVis({\n * visProjects: [\n * {\n * snapshotRootDir: '__vis__/linux',\n * },\n * ],\n * })\n * // Returns: { name: string, options: StorybookVisOptions }\n * ```\n */\nexport function defineStorybookVis(): string\n/**\n * Defines the Storybook Visual Testing addon configuration with options.\n *\n * @param options - Configuration options for visual testing suites in Storybook.\n * @param options.visProjects - Array of visual testing project configurations.\n * @param options.visProjects[].snapshotRootDir - Root directory for storing snapshots. Can be a string path or a function that returns a path based on CI and platform context.\n * @param options.visProjects[].snapshotSubpath - Optional function to customize the snapshot subdirectory path.\n *\n * @returns An object containing the package name and the provided options.\n *\n * @example\n * ```ts\n * // In .storybook/main.ts\n * import { defineStorybookVis } from 'storybook-addon-vis/node'\n *\n * export default {\n * addons: [\n * defineStorybookVis({\n * visProjects: [\n * {\n * snapshotRootDir: '__vis__/linux',\n * },\n * {\n * snapshotRootDir: '__vis__/local',\n * },\n * ],\n * }),\n * ],\n * }\n * ```\n */\nexport function defineStorybookVis(options: StorybookVisOptions): { name: string; options: StorybookVisOptions }\nexport function defineStorybookVis(options?: StorybookVisOptions | undefined) {\n\tconst name = dirname(import.meta.resolve('storybook-addon-vis', 'package.json'))\n\treturn !options ? name : { name, options }\n}\n","import type { StorybookVisOptions } from '../server/types.ts'\n\n/**\n * Define options for Storybook Visual Testing addon.\n */\nexport function defineStorybookVisOptions(options: StorybookVisOptions) {\n\treturn options\n}\n"],"mappings":";;;AAgEA,SAAgB,mBAAmB,SAA2C;CAC7E,MAAM,OAAO,QAAQ,OAAO,KAAK,QAAQ,uBAAuB,eAAe,CAAC;AAChF,QAAO,CAAC,UAAU,OAAO;EAAE;EAAM;EAAS;;;;;;;;AC7D3C,SAAgB,0BAA0B,SAA8B;AACvE,QAAO"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { t as StorybookVisOptions } from "./types-BG2k_RS_.mjs";
|
|
2
|
+
import { Channel } from "storybook/internal/channels";
|
|
3
|
+
|
|
4
|
+
//#region src/preset.d.ts
|
|
5
|
+
declare const experimental_serverChannel: (channel: Channel, options: StorybookVisOptions) => Promise<Channel>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { experimental_serverChannel };
|
|
8
|
+
//# sourceMappingURL=preset.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.d.mts","names":[],"sources":["../src/preset.ts"],"sourcesContent":[],"mappings":";;;;cAMa,sCAA6C,kBAAkB,wBAAmB,QAAA"}
|
package/dist/preset.mjs
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { t as NAME } from "./contants-DcocjING.mjs";
|
|
2
|
+
import { globSync } from "glob";
|
|
3
|
+
import ci from "is-ci";
|
|
4
|
+
import memoize from "memoize";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { platform } from "node:process";
|
|
7
|
+
import { basename, resolve } from "pathe";
|
|
8
|
+
import { BASELINE_DIR, DIFF_DIR, SNAPSHOT_ROOT_DIR, getSnapshotRootDir, trimCommonFolder } from "vitest-plugin-vis/server-utils";
|
|
9
|
+
|
|
10
|
+
//#region src/server/create_storybook_vis_server.ts
|
|
11
|
+
function createStorybookVisServer(options) {
|
|
12
|
+
const visSuites = options.visProjects ?? [{}];
|
|
13
|
+
return {
|
|
14
|
+
options,
|
|
15
|
+
async getImageSnapshotResults(name, importPath) {
|
|
16
|
+
return visSuites.map((suite) => {
|
|
17
|
+
return {
|
|
18
|
+
snapshotRootDir: typeof suite.snapshotRootDir === "string" ? suite.snapshotRootDir : typeof suite.snapshotRootDir === "function" ? memoize(suite.snapshotRootDir)({
|
|
19
|
+
ci,
|
|
20
|
+
platform
|
|
21
|
+
}) : memoize(getSnapshotRootDir)(SNAPSHOT_ROOT_DIR),
|
|
22
|
+
snapshotSubpath: (typeof suite.snapshotSubpath === "function" ? memoize(suite.snapshotSubpath) : memoize(({ subpath }) => trimCommonFolder(subpath.startsWith("./") ? subpath.slice(2) : subpath)))({ subpath: importPath })
|
|
23
|
+
};
|
|
24
|
+
}).flatMap(({ snapshotRootDir, snapshotSubpath }) => {
|
|
25
|
+
const taskId = name.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
26
|
+
const taskGlob = `${taskId}-*.png`;
|
|
27
|
+
const baselineGlob = resolve(snapshotRootDir, BASELINE_DIR, snapshotSubpath, taskGlob);
|
|
28
|
+
const diffGlob = resolve(snapshotRootDir, DIFF_DIR, snapshotSubpath, taskGlob);
|
|
29
|
+
const taskIdRegex = /* @__PURE__ */ new RegExp(`${taskId}-[^-]*.png$`);
|
|
30
|
+
const baselineFiles = globSync(baselineGlob).filter((filePath) => taskIdRegex.test(filePath));
|
|
31
|
+
const diffFiles = globSync(diffGlob).filter((filePath) => taskIdRegex.test(filePath));
|
|
32
|
+
return [...baselineFiles.map((filePath) => mapFileToResult(filePath, snapshotRootDir, "baseline")), ...diffFiles.map((filePath) => mapFileToResult(filePath, snapshotRootDir, "diff"))];
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function mapFileToResult(filePath, snapshotRootDir, type) {
|
|
38
|
+
return {
|
|
39
|
+
filePath,
|
|
40
|
+
fileName: basename(filePath),
|
|
41
|
+
snapshotRootDir,
|
|
42
|
+
type,
|
|
43
|
+
base64: readFileSync(filePath, "base64")
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/shared/events.ts
|
|
49
|
+
const IMAGE_SNAPSHOT_RESULTS_REQUEST = "IMAGE_SNAPSHOT_RESULTS_REQUEST";
|
|
50
|
+
const IMAGE_SNAPSHOT_RESULTS_RESPONSE = "IMAGE_SNAPSHOT_RESULTS_RESPONSE";
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/preset.ts
|
|
54
|
+
const experimental_serverChannel = async (channel, options) => {
|
|
55
|
+
const server = createStorybookVisServer(options);
|
|
56
|
+
channel.on(NAME, async (event) => {
|
|
57
|
+
if (event.type === IMAGE_SNAPSHOT_RESULTS_REQUEST) {
|
|
58
|
+
const results = await server.getImageSnapshotResults(event.name, event.importPath);
|
|
59
|
+
channel.emit(NAME, {
|
|
60
|
+
type: IMAGE_SNAPSHOT_RESULTS_RESPONSE,
|
|
61
|
+
name: event.name,
|
|
62
|
+
importPath: event.importPath,
|
|
63
|
+
results
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return channel;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
export { experimental_serverChannel };
|
|
72
|
+
//# sourceMappingURL=preset.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.mjs","names":[],"sources":["../src/server/create_storybook_vis_server.ts","../src/shared/events.ts","../src/preset.ts"],"sourcesContent":["import { globSync } from 'glob'\nimport ci from 'is-ci'\nimport memoize from 'memoize'\nimport { readFileSync } from 'node:fs'\nimport { platform } from 'node:process'\nimport { basename, resolve } from 'pathe'\nimport {\n\tBASELINE_DIR,\n\tDIFF_DIR,\n\tgetSnapshotRootDir,\n\tSNAPSHOT_ROOT_DIR,\n\ttrimCommonFolder,\n} from 'vitest-plugin-vis/server-utils'\nimport type { StorybookVisOptions } from './types.ts'\n\nexport function createStorybookVisServer(options: StorybookVisOptions) {\n\tconst visSuites = options.visProjects ?? [{}]\n\treturn {\n\t\toptions,\n\t\tasync getImageSnapshotResults(name: string, importPath: string) {\n\t\t\treturn visSuites\n\t\t\t\t.map((suite) => {\n\t\t\t\t\tconst snapshotRootDir =\n\t\t\t\t\t\ttypeof suite.snapshotRootDir === 'string'\n\t\t\t\t\t\t\t? suite.snapshotRootDir\n\t\t\t\t\t\t\t: typeof suite.snapshotRootDir === 'function'\n\t\t\t\t\t\t\t\t? memoize(suite.snapshotRootDir)({\n\t\t\t\t\t\t\t\t\t\tci,\n\t\t\t\t\t\t\t\t\t\tplatform,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t: memoize(getSnapshotRootDir)(SNAPSHOT_ROOT_DIR)\n\n\t\t\t\t\tconst snapshotSubpathFn =\n\t\t\t\t\t\ttypeof suite.snapshotSubpath === 'function'\n\t\t\t\t\t\t\t? memoize(suite.snapshotSubpath)\n\t\t\t\t\t\t\t: memoize(({ subpath }: { subpath: string }) =>\n\t\t\t\t\t\t\t\t\ttrimCommonFolder(subpath.startsWith('./') ? subpath.slice(2) : subpath),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\tconst snapshotSubpath = snapshotSubpathFn({ subpath: importPath })\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsnapshotRootDir,\n\t\t\t\t\t\tsnapshotSubpath,\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.flatMap(({ snapshotRootDir, snapshotSubpath }) => {\n\t\t\t\t\tconst taskId = name.replace(/[^a-z0-9]/gi, '-').toLowerCase()\n\t\t\t\t\tconst taskGlob = `${taskId}-*.png`\n\t\t\t\t\tconst baselineGlob = resolve(snapshotRootDir, BASELINE_DIR, snapshotSubpath, taskGlob)\n\t\t\t\t\tconst diffGlob = resolve(snapshotRootDir, DIFF_DIR, snapshotSubpath, taskGlob)\n\n\t\t\t\t\tconst taskIdRegex = new RegExp(`${taskId}-[^-]*.png$`)\n\t\t\t\t\tconst baselineFiles = globSync(baselineGlob).filter((filePath) => taskIdRegex.test(filePath))\n\t\t\t\t\tconst diffFiles = globSync(diffGlob).filter((filePath) => taskIdRegex.test(filePath))\n\t\t\t\t\treturn [\n\t\t\t\t\t\t...baselineFiles.map((filePath) => mapFileToResult(filePath, snapshotRootDir, 'baseline')),\n\t\t\t\t\t\t...diffFiles.map((filePath) => mapFileToResult(filePath, snapshotRootDir, 'diff')),\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t},\n\t}\n}\n\nfunction mapFileToResult(filePath: string, snapshotRootDir: string, type: 'baseline' | 'diff') {\n\treturn {\n\t\tfilePath,\n\t\tfileName: basename(filePath),\n\t\tsnapshotRootDir,\n\t\ttype,\n\t\tbase64: readFileSync(filePath, 'base64'),\n\t}\n}\n","export type VisEvent = ImageSnapshotResultsRequest | ImageSnapshotResultsResponse\n\nexport const IMAGE_SNAPSHOT_RESULTS_REQUEST = 'IMAGE_SNAPSHOT_RESULTS_REQUEST'\nexport const IMAGE_SNAPSHOT_RESULTS_RESPONSE = 'IMAGE_SNAPSHOT_RESULTS_RESPONSE'\n\nexport function requestImageSnapshotResults({ name, importPath }: { name: string; importPath: string }) {\n\treturn {\n\t\ttype: IMAGE_SNAPSHOT_RESULTS_REQUEST,\n\t\tname,\n\t\timportPath,\n\t}\n}\n\nexport type ImageSnapshotResultsRequest = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_REQUEST\n\tname: string\n\timportPath: string\n}\n\nexport type ImageSnapshotResultsResponse = {\n\ttype: typeof IMAGE_SNAPSHOT_RESULTS_RESPONSE\n\tname: string\n\timportPath: string\n\tresults: ImageSnapshotResults[]\n}\n\nexport type ImageSnapshotResults = {\n\tfilePath: string\n\tfileName: string\n\tsnapshotRootDir: string\n\ttype: 'baseline' | 'diff' | 'result'\n\tbase64: string\n}\n","import type { Channel } from 'storybook/internal/channels'\nimport { createStorybookVisServer } from './server/create_storybook_vis_server.ts'\nimport type { StorybookVisOptions } from './server/types.ts'\nimport { NAME } from './shared/contants.ts'\nimport { IMAGE_SNAPSHOT_RESULTS_REQUEST, IMAGE_SNAPSHOT_RESULTS_RESPONSE, type VisEvent } from './shared/events.ts'\n\nexport const experimental_serverChannel = async (channel: Channel, options: StorybookVisOptions) => {\n\tconst server = createStorybookVisServer(options)\n\n\tchannel.on(NAME, async (event: VisEvent) => {\n\t\tif (event.type === IMAGE_SNAPSHOT_RESULTS_REQUEST) {\n\t\t\tconst results = await server.getImageSnapshotResults(event.name, event.importPath)\n\t\t\tchannel.emit(NAME, {\n\t\t\t\ttype: IMAGE_SNAPSHOT_RESULTS_RESPONSE,\n\t\t\t\tname: event.name,\n\t\t\t\timportPath: event.importPath,\n\t\t\t\tresults,\n\t\t\t})\n\t\t}\n\t})\n\n\treturn channel\n}\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,yBAAyB,SAA8B;CACtE,MAAM,YAAY,QAAQ,eAAe,CAAC,EAAE,CAAC;AAC7C,QAAO;EACN;EACA,MAAM,wBAAwB,MAAc,YAAoB;AAC/D,UAAO,UACL,KAAK,UAAU;AAkBf,WAAO;KACN,iBAjBA,OAAO,MAAM,oBAAoB,WAC9B,MAAM,kBACN,OAAO,MAAM,oBAAoB,aAChC,QAAQ,MAAM,gBAAgB,CAAC;MAC/B;MACA;MACA,CAAC,GACD,QAAQ,mBAAmB,CAAC,kBAAkB;KAWlD,kBARA,OAAO,MAAM,oBAAoB,aAC9B,QAAQ,MAAM,gBAAgB,GAC9B,SAAS,EAAE,cACX,iBAAiB,QAAQ,WAAW,KAAK,GAAG,QAAQ,MAAM,EAAE,GAAG,QAAQ,CACvE,EACsC,EAAE,SAAS,YAAY,CAAC;KAIjE;KACA,CACD,SAAS,EAAE,iBAAiB,sBAAsB;IAClD,MAAM,SAAS,KAAK,QAAQ,eAAe,IAAI,CAAC,aAAa;IAC7D,MAAM,WAAW,GAAG,OAAO;IAC3B,MAAM,eAAe,QAAQ,iBAAiB,cAAc,iBAAiB,SAAS;IACtF,MAAM,WAAW,QAAQ,iBAAiB,UAAU,iBAAiB,SAAS;IAE9E,MAAM,8BAAc,IAAI,OAAO,GAAG,OAAO,aAAa;IACtD,MAAM,gBAAgB,SAAS,aAAa,CAAC,QAAQ,aAAa,YAAY,KAAK,SAAS,CAAC;IAC7F,MAAM,YAAY,SAAS,SAAS,CAAC,QAAQ,aAAa,YAAY,KAAK,SAAS,CAAC;AACrF,WAAO,CACN,GAAG,cAAc,KAAK,aAAa,gBAAgB,UAAU,iBAAiB,WAAW,CAAC,EAC1F,GAAG,UAAU,KAAK,aAAa,gBAAgB,UAAU,iBAAiB,OAAO,CAAC,CAClF;KACA;;EAEJ;;AAGF,SAAS,gBAAgB,UAAkB,iBAAyB,MAA2B;AAC9F,QAAO;EACN;EACA,UAAU,SAAS,SAAS;EAC5B;EACA;EACA,QAAQ,aAAa,UAAU,SAAS;EACxC;;;;;ACnEF,MAAa,iCAAiC;AAC9C,MAAa,kCAAkC;;;;ACG/C,MAAa,6BAA6B,OAAO,SAAkB,YAAiC;CACnG,MAAM,SAAS,yBAAyB,QAAQ;AAEhD,SAAQ,GAAG,MAAM,OAAO,UAAoB;AAC3C,MAAI,MAAM,SAAS,gCAAgC;GAClD,MAAM,UAAU,MAAM,OAAO,wBAAwB,MAAM,MAAM,MAAM,WAAW;AAClF,WAAQ,KAAK,MAAM;IAClB,MAAM;IACN,MAAM,MAAM;IACZ,YAAY,MAAM;IAClB;IACA,CAAC;;GAEF;AAEF,QAAO"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/server/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for visual testing suites in Storybook.
|
|
4
|
+
*
|
|
5
|
+
* @param options.visProjects Array of visual testing project configurations
|
|
6
|
+
* @param options.visProjects[].snapshotRootDir Root directory for storing snapshots. Can be a string path or a function that returns a path based on CI and platform context
|
|
7
|
+
* @param options.visProjects[].snapshotSubpath Optional function to customize the snapshot subdirectory path
|
|
8
|
+
*/
|
|
9
|
+
type StorybookVisOptions = {
|
|
10
|
+
visProjects: Array<{
|
|
11
|
+
snapshotRootDir: string | ((context: {
|
|
12
|
+
ci: boolean;
|
|
13
|
+
platform: string;
|
|
14
|
+
}) => string) | undefined;
|
|
15
|
+
snapshotSubpath?: ((options: {
|
|
16
|
+
subpath: string;
|
|
17
|
+
}) => string) | undefined;
|
|
18
|
+
}>;
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
export { StorybookVisOptions as t };
|
|
22
|
+
//# sourceMappingURL=types-BG2k_RS_.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-BG2k_RS_.d.mts","names":[],"sources":["../src/server/types.ts"],"sourcesContent":[],"mappings":";;AAOA;;;;;;KAAY,mBAAA;eACE"}
|