storybook-addon-vis 3.0.0 → 3.1.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/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -7
- package/dist/index.js.map +1 -1
- package/dist/manager.js +2 -2
- package/dist/manager.js.map +1 -1
- package/dist/{vis_annotation-Dpsgn_4P.js → vis_annotation-DqZTkmEN.js} +3 -3
- package/dist/{vis_annotation-Dpsgn_4P.js.map → vis_annotation-DqZTkmEN.js.map} +1 -1
- package/dist/vitest-setup.d.ts +2 -2
- package/dist/vitest-setup.d.ts.map +1 -1
- package/dist/vitest-setup.js +2 -2
- package/dist/vitest-setup.js.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +28 -6
- package/src/manager.tsx +2 -2
- package/src/overview.mdx +39 -46
- package/src/vitest-setup.ts +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "./global_matcher_augment-CYxLwns2.js";
|
|
2
2
|
import { ComparisonMethod, FailureThresholdOptions, ImageSnapshotCompareOptions, ImageSnapshotKeyOptions, ImageSnapshotKeyOptions as ImageSnapshotKeyOptions$1, ImageSnapshotSubjectOptions, ImageSnapshotTimeoutOptions, PixelComparisonOptions, SsimComparisonOptions, ToMatchImageSnapshotOptions } from "vitest-plugin-vis/client-api";
|
|
3
|
-
import
|
|
3
|
+
import * as storybook_internal_csf0 from "storybook/internal/csf";
|
|
4
|
+
import { SetupVisOptions } from "vitest-plugin-vis";
|
|
4
5
|
import { BrowserPage } from "vitest/browser";
|
|
5
6
|
import "vitest/suite";
|
|
6
|
-
import * as storybook_internal_csf0 from "storybook/internal/csf";
|
|
7
7
|
export * from "vitest-plugin-vis";
|
|
8
8
|
|
|
9
9
|
//#region src/client/vitest_proxy.d.ts
|
|
@@ -29,10 +29,7 @@ declare function defineAutoSnapshotParam<M extends ComparisonMethod>(snapshot: T
|
|
|
29
29
|
declare function isSnapshotEnabled(tags: string[]): boolean;
|
|
30
30
|
//#endregion
|
|
31
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[];
|
|
35
|
-
};
|
|
32
|
+
declare const _default: (options?: SetupVisOptions) => storybook_internal_csf0.PreviewAddon<storybook_internal_csf0.AddonTypes>;
|
|
36
33
|
//#endregion
|
|
37
34
|
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
35
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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;;;
|
|
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;;;cCgBD,qBAEU,oBAAiC,uBAAA,CAAA,aAAA,uBAAA,CAAA,UAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { a as page, i as getCurrentTest, n as isSnapshotEnabled, r as commands, t as visAnnotations } from "./vis_annotation-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { a as page, i as getCurrentTest, n as isSnapshotEnabled, r as commands, t as visAnnotations } from "./vis_annotation-DqZTkmEN.js";
|
|
2
|
+
import { expect } from "storybook/test";
|
|
3
|
+
import { autoSnapshotMatcher, hasImageSnapshotAction, setAutoSnapshotOptions, toTaskId } from "vitest-plugin-vis/client-api";
|
|
4
|
+
import { definePreviewAddon } from "storybook/internal/csf";
|
|
4
5
|
|
|
5
6
|
export * from "vitest-plugin-vis"
|
|
6
7
|
|
|
@@ -34,12 +35,24 @@ function defineAutoSnapshotParam(snapshot) {
|
|
|
34
35
|
|
|
35
36
|
//#endregion
|
|
36
37
|
//#region src/index.ts
|
|
37
|
-
var src_default = (options = {}) => {
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
var src_default = (options = { auto: false }) => {
|
|
39
|
+
let matcher;
|
|
40
|
+
let matcherFn;
|
|
41
|
+
return definePreviewAddon({
|
|
40
42
|
tags: options.auto ? ["snapshot"] : [],
|
|
43
|
+
async beforeAll() {
|
|
44
|
+
matcher = autoSnapshotMatcher(commands, expect);
|
|
45
|
+
if (typeof options?.auto === "function") matcherFn = matcher.createMatcher({ auto: options.auto });
|
|
46
|
+
else if (typeof options?.auto === "object") matcherFn = matcher.createMatcher(options.auto);
|
|
47
|
+
else matcherFn = matcher.createMatcher({ async auto() {} });
|
|
48
|
+
await matcher.setup();
|
|
49
|
+
await setAutoSnapshotOptions(true);
|
|
50
|
+
},
|
|
51
|
+
afterEach() {
|
|
52
|
+
if (matcherFn) return matcherFn();
|
|
53
|
+
},
|
|
41
54
|
...visAnnotations
|
|
42
|
-
};
|
|
55
|
+
});
|
|
43
56
|
};
|
|
44
57
|
|
|
45
58
|
//#endregion
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 {
|
|
1
|
+
{"version":3,"file":"index.js","names":["matcher: ReturnType<typeof autoSnapshotMatcher>","matcherFn: () => Promise<void>"],"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 { definePreviewAddon } from 'storybook/internal/csf'\nimport { expect } from 'storybook/test'\nimport type { SetupVisOptions } from 'vitest-plugin-vis'\nimport { autoSnapshotMatcher, setAutoSnapshotOptions } from 'vitest-plugin-vis/client-api'\nimport { commands, 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 = { auto: false }) => {\n\tlet matcher: ReturnType<typeof autoSnapshotMatcher>\n\tlet matcherFn: () => Promise<void>\n\treturn definePreviewAddon({\n\t\ttags: options.auto ? ['snapshot'] : [],\n\t\tasync beforeAll() {\n\t\t\tmatcher = autoSnapshotMatcher(commands, expect)\n\t\t\tif (typeof options?.auto === 'function') {\n\t\t\t\tmatcherFn = matcher.createMatcher({\n\t\t\t\t\tauto: options.auto,\n\t\t\t\t})\n\t\t\t} else if (typeof options?.auto === 'object') {\n\t\t\t\tmatcherFn = matcher.createMatcher(options.auto)\n\t\t\t} else matcherFn = matcher.createMatcher({ async auto() {} })\n\n\t\t\tawait matcher.setup()\n\t\t\tawait setAutoSnapshotOptions(true)\n\t\t},\n\t\tafterEach() {\n\t\t\tif (matcherFn) {\n\t\t\t\treturn matcherFn()\n\t\t\t}\n\t\t},\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;;;;;ACbpB,mBAAgB,UAA2B,EAAE,MAAM,OAAO,KAAK;CAC9D,IAAIA;CACJ,IAAIC;AACJ,QAAO,mBAAmB;EACzB,MAAM,QAAQ,OAAO,CAAC,WAAW,GAAG,EAAE;EACtC,MAAM,YAAY;AACjB,aAAU,oBAAoB,UAAU,OAAO;AAC/C,OAAI,OAAO,SAAS,SAAS,WAC5B,aAAY,QAAQ,cAAc,EACjC,MAAM,QAAQ,MACd,CAAC;YACQ,OAAO,SAAS,SAAS,SACnC,aAAY,QAAQ,cAAc,QAAQ,KAAK;OACzC,aAAY,QAAQ,cAAc,EAAE,MAAM,OAAO,IAAI,CAAC;AAE7D,SAAM,QAAQ,OAAO;AACrB,SAAM,uBAAuB,KAAK;;EAEnC,YAAY;AACX,OAAI,UACH,QAAO,WAAW;;EAGpB,GAAG;EACH,CAAC"}
|
package/dist/manager.js
CHANGED
|
@@ -65,7 +65,7 @@ addons.register(NAME, (api) => {
|
|
|
65
65
|
if (event.importPath !== storyData.importPath) return;
|
|
66
66
|
if (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) setSnapshotResults(event.results);
|
|
67
67
|
})];
|
|
68
|
-
api.emit(NAME, requestImageSnapshotResults(storyData));
|
|
68
|
+
if (storyData) api.emit(NAME, requestImageSnapshotResults(storyData));
|
|
69
69
|
return () => disposes.forEach((dispose) => {
|
|
70
70
|
dispose();
|
|
71
71
|
});
|
|
@@ -75,7 +75,7 @@ addons.register(NAME, (api) => {
|
|
|
75
75
|
active,
|
|
76
76
|
snapshotResults,
|
|
77
77
|
onRefresh: () => {
|
|
78
|
-
api.emit(NAME, requestImageSnapshotResults(storyData));
|
|
78
|
+
if (storyData) api.emit(NAME, requestImageSnapshotResults(storyData));
|
|
79
79
|
}
|
|
80
80
|
});
|
|
81
81
|
}
|
package/dist/manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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\
|
|
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\tif (storyData) api.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\tif (storyData) api.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,UAAW,KAAI,KAAK,MAAM,4BAA4B,UAAU,CAAC;AACrE,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,UAAW,KAAI,KAAK,MAAM,4BAA4B,UAAU,CAAC;;KAErE;;EAGJ,CAAC;EAEF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expect } from "storybook/test";
|
|
2
2
|
import { matchImageSnapshotAction, matchPageImageSnapshotAction, success, toTaskId } from "vitest-plugin-vis/client-api";
|
|
3
|
-
import { setAutoSnapshotOptions } from "vitest-plugin-vis";
|
|
3
|
+
import { setAutoSnapshotOptions as setAutoSnapshotOptions$1 } from "vitest-plugin-vis";
|
|
4
4
|
|
|
5
5
|
//#region src/client/page/to_match_image_snapshot.ts
|
|
6
6
|
function toMatchImageSnapshot$1(options) {
|
|
@@ -61,7 +61,7 @@ function isSnapshotEnabled(tags) {
|
|
|
61
61
|
//#region src/preview/vis_annotation.ts
|
|
62
62
|
const visAnnotations = { beforeEach(ctx) {
|
|
63
63
|
const test = getCurrentTest();
|
|
64
|
-
setAutoSnapshotOptions({
|
|
64
|
+
setAutoSnapshotOptions$1({
|
|
65
65
|
enable: isSnapshotEnabled(ctx.tags),
|
|
66
66
|
...ctx.parameters?.snapshot,
|
|
67
67
|
tags: ctx.tags,
|
|
@@ -71,4 +71,4 @@ const visAnnotations = { beforeEach(ctx) {
|
|
|
71
71
|
|
|
72
72
|
//#endregion
|
|
73
73
|
export { page as a, getCurrentTest as i, isSnapshotEnabled as n, commands as r, visAnnotations as t };
|
|
74
|
-
//# sourceMappingURL=vis_annotation-
|
|
74
|
+
//# sourceMappingURL=vis_annotation-DqZTkmEN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vis_annotation-
|
|
1
|
+
{"version":3,"file":"vis_annotation-DqZTkmEN.js","names":["toMatchImageSnapshot","browserContext: Awaited<typeof import('vitest/browser')>","vitestSuite: Awaited<typeof import('vitest/suite')>"],"sources":["../src/client/page/to_match_image_snapshot.ts","../src/client/vitest_proxy.ts","../src/client/expect/to_match_image_snapshot.ts","../src/client/storybook/expect_extend.ts","../src/client/storybook/tags.ts","../src/preview/vis_annotation.ts"],"sourcesContent":["import {\n\ttype ComparisonMethod,\n\ttype ToMatchPageImageSnapshotOptions,\n\tmatchPageImageSnapshotAction,\n\ttoTaskId,\n} from 'vitest-plugin-vis/client-api'\nimport { commands, getCurrentTest } from '../vitest_proxy.ts'\n\nexport function toMatchImageSnapshot<M extends ComparisonMethod = 'pixel'>(\n\toptions?: ToMatchPageImageSnapshotOptions<M> | undefined,\n) {\n\tconst test = getCurrentTest()\n\n\t/* v8 ignore start: stub as success when not in a test (e.g. in a story) */\n\tif (!test) return Promise.resolve()\n\t/* v8 ignore end */\n\n\treturn matchPageImageSnapshotAction(commands, toTaskId(test), options)\n}\n","import type { SnapshotTestMeta } from 'vitest-plugin-vis/client-api'\nimport type { BrowserCommands, BrowserPage } from 'vitest/browser'\nimport { toMatchImageSnapshot } from './page/to_match_image_snapshot.ts'\n\nlet browserContext: Awaited<typeof import('vitest/browser')>\nlet vitestSuite: Awaited<typeof import('vitest/suite')>\n\nif ((globalThis as any).__vitest_browser__) {\n\timport('vitest/browser').then((m) => {\n\t\tm.page.extend({ toMatchImageSnapshot })\n\t\tbrowserContext = m\n\t})\n\timport('vitest/suite').then((m) => {\n\t\tvitestSuite = m\n\t})\n}\n\nexport const page = new Proxy<BrowserPage>({} as any, {\n\tget(_target, prop) {\n\t\tconst r = (browserContext?.page as any)?.[prop]\n\t\tif (prop === 'toMatchImageSnapshot' && r === undefined) {\n\t\t\treturn () => {}\n\t\t}\n\t\treturn r\n\t},\n})\n\nexport const commands = new Proxy<BrowserCommands>({} as any, {\n\tget(_target, prop) {\n\t\treturn (browserContext?.commands as any)?.[prop]\n\t},\n})\n\nexport const getCurrentTest = () =>\n\tvitestSuite?.getCurrentTest() as (ReturnType<typeof vitestSuite.getCurrentTest> & SnapshotTestMeta) | undefined\n","import type { AsyncExpectationResult } from '@vitest/expect'\nimport {\n\ttype ComparisonMethod,\n\ttype ToMatchImageSnapshotOptions,\n\tmatchImageSnapshotAction,\n\tsuccess,\n\ttoTaskId,\n} from 'vitest-plugin-vis/client-api'\nimport { commands, getCurrentTest } from '../vitest_proxy.ts'\n\nexport function toMatchImageSnapshot<M extends ComparisonMethod>(\n\t/**\n\t * The element or locator to take the snapshot of,\n\t * or the base64 value of the image to compare against.\n\t */\n\tsubject: any,\n\toptions?: ToMatchImageSnapshotOptions<M> | undefined,\n): AsyncExpectationResult {\n\tconst test = getCurrentTest()\n\n\t/* v8 ignore start: stub as success when not in a test (e.g. in a story) */\n\tif (!test) return Promise.resolve(success)\n\t/* v8 ignore end */\n\n\treturn matchImageSnapshotAction(commands, toTaskId(test), subject, options).then(() => success)\n}\n","import { expect } from 'storybook/test'\nimport { toMatchImageSnapshot } from '../expect/to_match_image_snapshot.ts'\n\nexpect.extend({ toMatchImageSnapshot })\n","export function isSnapshotEnabled(tags: string[]) {\n\tconst noSnapshotIndex = tags.lastIndexOf('!snapshot')\n\tconst snapshotIndex = tags.lastIndexOf('snapshot')\n\n\tif (noSnapshotIndex < 0 && snapshotIndex < 0) return false\n\n\treturn noSnapshotIndex < snapshotIndex\n}\n","import type { NamedOrDefaultProjectAnnotations } from 'storybook/internal/types'\nimport { setAutoSnapshotOptions } from 'vitest-plugin-vis'\nimport { isSnapshotEnabled } from '../client/storybook/tags.ts'\nimport { getCurrentTest } from '../client/vitest_proxy.ts'\n\nexport const visAnnotations = {\n\tbeforeEach(ctx) {\n\t\tconst test = getCurrentTest()\n\n\t\tsetAutoSnapshotOptions({\n\t\t\tenable: isSnapshotEnabled(ctx.tags),\n\t\t\t...ctx.parameters?.snapshot,\n\t\t\ttags: ctx.tags,\n\t\t\t...test?.meta.vis,\n\t\t})\n\t},\n} satisfies NamedOrDefaultProjectAnnotations<any>\n"],"mappings":";;;;;AAQA,SAAgBA,uBACf,SACC;CACD,MAAM,OAAO,gBAAgB;;AAG7B,KAAI,CAAC,KAAM,QAAO,QAAQ,SAAS;;AAGnC,QAAO,6BAA6B,UAAU,SAAS,KAAK,EAAE,QAAQ;;;;;ACbvE,IAAIC;AACJ,IAAIC;AAEJ,IAAK,WAAmB,oBAAoB;AAC3C,QAAO,kBAAkB,MAAM,MAAM;AACpC,IAAE,KAAK,OAAO,EAAE,8CAAsB,CAAC;AACvC,mBAAiB;GAChB;AACF,QAAO,gBAAgB,MAAM,MAAM;AAClC,gBAAc;GACb;;AAGH,MAAa,OAAO,IAAI,MAAmB,EAAE,EAAS,EACrD,IAAI,SAAS,MAAM;CAClB,MAAM,KAAK,gBAAgB,QAAe;AAC1C,KAAI,SAAS,0BAA0B,MAAM,OAC5C,cAAa;AAEd,QAAO;GAER,CAAC;AAEF,MAAa,WAAW,IAAI,MAAuB,EAAE,EAAS,EAC7D,IAAI,SAAS,MAAM;AAClB,SAAQ,gBAAgB,YAAmB;GAE5C,CAAC;AAEF,MAAa,uBACZ,aAAa,gBAAgB;;;;ACxB9B,SAAgB,qBAKf,SACA,SACyB;CACzB,MAAM,OAAO,gBAAgB;;AAG7B,KAAI,CAAC,KAAM,QAAO,QAAQ,QAAQ,QAAQ;;AAG1C,QAAO,yBAAyB,UAAU,SAAS,KAAK,EAAE,SAAS,QAAQ,CAAC,WAAW,QAAQ;;;;;ACrBhG,OAAO,OAAO,EAAE,sBAAsB,CAAC;;;;ACHvC,SAAgB,kBAAkB,MAAgB;CACjD,MAAM,kBAAkB,KAAK,YAAY,YAAY;CACrD,MAAM,gBAAgB,KAAK,YAAY,WAAW;AAElD,KAAI,kBAAkB,KAAK,gBAAgB,EAAG,QAAO;AAErD,QAAO,kBAAkB;;;;;ACD1B,MAAa,iBAAiB,EAC7B,WAAW,KAAK;CACf,MAAM,OAAO,gBAAgB;AAE7B,0BAAuB;EACtB,QAAQ,kBAAkB,IAAI,KAAK;EACnC,GAAG,IAAI,YAAY;EACnB,MAAM,IAAI;EACV,GAAG,MAAM,KAAK;EACd,CAAC;GAEH"}
|
package/dist/vitest-setup.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./global_matcher_augment-CYxLwns2.js";
|
|
2
|
-
import * as vitest_plugin_vis_setup0 from "vitest-plugin-vis/setup";
|
|
3
|
-
import { setAutoSnapshotOptions } from "vitest-plugin-vis";
|
|
4
2
|
import * as storybook_internal_csf1 from "storybook/internal/csf";
|
|
3
|
+
import { setAutoSnapshotOptions } from "vitest-plugin-vis";
|
|
4
|
+
import * as vitest_plugin_vis_setup0 from "vitest-plugin-vis/setup";
|
|
5
5
|
|
|
6
6
|
//#region src/preview/vis_annotation.d.ts
|
|
7
7
|
declare const visAnnotations: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-setup.d.ts","names":[],"sources":["../src/preview/vis_annotation.ts","../src/vitest-setup.ts"],"sourcesContent":[],"mappings":";;;;;;cAKa;kBAWoC,uBAAA,CAAA,kBAAA,uBAAA,CAAA,IAAA;;;;
|
|
1
|
+
{"version":3,"file":"vitest-setup.d.ts","names":[],"sources":["../src/preview/vis_annotation.ts","../src/vitest-setup.ts"],"sourcesContent":[],"mappings":";;;;;;cAKa;kBAWoC,uBAAA,CAAA,kBAAA,uBAAA,CAAA,IAAA;;;;cCTpC,KAA6C,wBAAA,CAA1C"}
|
package/dist/vitest-setup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as commands, t as visAnnotations } from "./vis_annotation-
|
|
2
|
-
import { createVis } from "vitest-plugin-vis/setup";
|
|
1
|
+
import { r as commands, t as visAnnotations } from "./vis_annotation-DqZTkmEN.js";
|
|
3
2
|
import { setAutoSnapshotOptions } from "vitest-plugin-vis";
|
|
3
|
+
import { createVis } from "vitest-plugin-vis/setup";
|
|
4
4
|
|
|
5
5
|
//#region src/vitest-setup.ts
|
|
6
6
|
const vis = createVis(commands);
|
package/dist/vitest-setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-setup.js","names":[],"sources":["../src/vitest-setup.ts"],"sourcesContent":["// `storybook-addon-vis/vitest-setup` provides code needed in `vitest.setup.ts`.\nimport './client/storybook/expect_extend.ts'\nimport './shared/global_matcher_augment.ts'\n\nimport
|
|
1
|
+
{"version":3,"file":"vitest-setup.js","names":[],"sources":["../src/vitest-setup.ts"],"sourcesContent":["// `storybook-addon-vis/vitest-setup` provides code needed in `vitest.setup.ts`.\nimport './client/storybook/expect_extend.ts'\nimport './shared/global_matcher_augment.ts'\n\nimport { createVis } from 'vitest-plugin-vis/setup'\nimport { commands } from './client/vitest_proxy.ts'\n\nexport const vis = createVis<{ tags: string[] }>(commands)\nexport { setAutoSnapshotOptions } from 'vitest-plugin-vis'\nexport { visAnnotations } from './preview/vis_annotation.ts'\n"],"mappings":";;;;;AAOA,MAAa,MAAM,UAA8B,SAAS"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "storybook-addon-vis",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Storybook Vitest visual testing addon",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"image-snapshot",
|
|
@@ -67,16 +67,16 @@
|
|
|
67
67
|
"memoize": "^10.1.0",
|
|
68
68
|
"pathe": "^2.0.3",
|
|
69
69
|
"type-plus": "8.0.0-beta.7",
|
|
70
|
-
"vitest-plugin-vis": "^4.
|
|
70
|
+
"vitest-plugin-vis": "^4.1.0"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@repobuddy/storybook": "^2.1.2",
|
|
74
74
|
"@storybook-community/storybook-dark-mode": "^7.0.3",
|
|
75
|
-
"@storybook/addon-docs": "^10.1
|
|
76
|
-
"@storybook/addon-vitest": "^10.1
|
|
77
|
-
"@storybook/react-vite": "^10.1
|
|
75
|
+
"@storybook/addon-docs": "^10.2.0-alpha.1",
|
|
76
|
+
"@storybook/addon-vitest": "^10.2.0-alpha.1",
|
|
77
|
+
"@storybook/react-vite": "^10.2.0-alpha.1",
|
|
78
78
|
"@tailwindcss/cli": "^4.1.7",
|
|
79
|
-
"@tailwindcss/vite": "^4.1.
|
|
79
|
+
"@tailwindcss/vite": "^4.1.17",
|
|
80
80
|
"@testing-library/react": "^16.0.1",
|
|
81
81
|
"@types/react": "^19.2.2",
|
|
82
82
|
"@types/react-dom": "^19.2.1",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"playwright": "latest",
|
|
94
94
|
"react": "^19.0.0",
|
|
95
95
|
"react-dom": "^19.0.0",
|
|
96
|
-
"storybook": "^10.1
|
|
96
|
+
"storybook": "^10.2.0-alpha.1",
|
|
97
97
|
"storybook-addon-tag-badges": "^3.0.2",
|
|
98
98
|
"tailwindcss": "^4.1.14",
|
|
99
99
|
"tsdown": "^0.16.6",
|
|
@@ -105,9 +105,9 @@
|
|
|
105
105
|
"zx": "^8.0.0"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
|
-
"@storybook/addon-vitest": "^10.1
|
|
108
|
+
"@storybook/addon-vitest": "^10.2.0-alpha.1",
|
|
109
109
|
"@vitest/browser": "^4",
|
|
110
|
-
"storybook": "^10.1
|
|
110
|
+
"storybook": "^10.2.0-alpha.1",
|
|
111
111
|
"vitest": "^4"
|
|
112
112
|
},
|
|
113
113
|
"publishConfig": {
|
package/src/index.ts
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
import './client/storybook/expect_extend.ts'
|
|
3
3
|
import './shared/global_matcher_augment.ts'
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { definePreviewAddon } from 'storybook/internal/csf'
|
|
6
|
+
import { expect } from 'storybook/test'
|
|
7
|
+
import type { SetupVisOptions } from 'vitest-plugin-vis'
|
|
8
|
+
import { autoSnapshotMatcher, setAutoSnapshotOptions } from 'vitest-plugin-vis/client-api'
|
|
9
|
+
import { commands, page } from './client/vitest_proxy.ts'
|
|
7
10
|
import { visAnnotations } from './preview/vis_annotation.ts'
|
|
8
11
|
|
|
9
12
|
export * from 'vitest-plugin-vis'
|
|
@@ -13,10 +16,29 @@ export * from './client/storybook/tags.ts'
|
|
|
13
16
|
|
|
14
17
|
export { page }
|
|
15
18
|
|
|
16
|
-
export default (options: SetupVisOptions = {}) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
export default (options: SetupVisOptions = { auto: false }) => {
|
|
20
|
+
let matcher: ReturnType<typeof autoSnapshotMatcher>
|
|
21
|
+
let matcherFn: () => Promise<void>
|
|
22
|
+
return definePreviewAddon({
|
|
19
23
|
tags: options.auto ? ['snapshot'] : [],
|
|
24
|
+
async beforeAll() {
|
|
25
|
+
matcher = autoSnapshotMatcher(commands, expect)
|
|
26
|
+
if (typeof options?.auto === 'function') {
|
|
27
|
+
matcherFn = matcher.createMatcher({
|
|
28
|
+
auto: options.auto,
|
|
29
|
+
})
|
|
30
|
+
} else if (typeof options?.auto === 'object') {
|
|
31
|
+
matcherFn = matcher.createMatcher(options.auto)
|
|
32
|
+
} else matcherFn = matcher.createMatcher({ async auto() {} })
|
|
33
|
+
|
|
34
|
+
await matcher.setup()
|
|
35
|
+
await setAutoSnapshotOptions(true)
|
|
36
|
+
},
|
|
37
|
+
afterEach() {
|
|
38
|
+
if (matcherFn) {
|
|
39
|
+
return matcherFn()
|
|
40
|
+
}
|
|
41
|
+
},
|
|
20
42
|
...visAnnotations,
|
|
21
|
-
}
|
|
43
|
+
})
|
|
22
44
|
}
|
package/src/manager.tsx
CHANGED
|
@@ -36,7 +36,7 @@ addons.register(NAME, (api) => {
|
|
|
36
36
|
// console.log('storybook/test', event)
|
|
37
37
|
// }),
|
|
38
38
|
]
|
|
39
|
-
api.emit(NAME, requestImageSnapshotResults(storyData))
|
|
39
|
+
if (storyData) api.emit(NAME, requestImageSnapshotResults(storyData))
|
|
40
40
|
return () =>
|
|
41
41
|
disposes.forEach((dispose) => {
|
|
42
42
|
dispose()
|
|
@@ -50,7 +50,7 @@ addons.register(NAME, (api) => {
|
|
|
50
50
|
active={active}
|
|
51
51
|
snapshotResults={snapshotResults}
|
|
52
52
|
onRefresh={() => {
|
|
53
|
-
api.emit(NAME, requestImageSnapshotResults(storyData))
|
|
53
|
+
if (storyData) api.emit(NAME, requestImageSnapshotResults(storyData))
|
|
54
54
|
}}
|
|
55
55
|
/>
|
|
56
56
|
)
|
package/src/overview.mdx
CHANGED
|
@@ -36,7 +36,7 @@ Please refer to its documentation for installation and setup instructions.
|
|
|
36
36
|
To setup [storybook-addon-vis][storybook-addon-vis], you need to do the following:
|
|
37
37
|
|
|
38
38
|
- Add the `storybookVis` plugin in [Vitest] along with the `storybookTest` plugin.
|
|
39
|
-
- Configure visual testing in
|
|
39
|
+
- Configure visual testing in `vitest.setup.ts` (and `.storybook/preview.ts` if you are writing your stories in CSF Next).
|
|
40
40
|
- Add [storybook-addon-vis][storybook-addon-vis] addon to your [Storybook] configuration in `.storybook/main.ts`.
|
|
41
41
|
- Ignore snapshot folders in your `.gitignore` file.
|
|
42
42
|
|
|
@@ -98,8 +98,8 @@ const annotations = setProjectAnnotations([
|
|
|
98
98
|
|
|
99
99
|
beforeAll(annotations.beforeAll)
|
|
100
100
|
|
|
101
|
-
// ADD THIS to
|
|
102
|
-
vis.setup(
|
|
101
|
+
// ADD THIS to enable visual testing
|
|
102
|
+
vis.setup()
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
For [Storybook], you need to add the addon to your `.storybook/main.ts`:
|
|
@@ -141,6 +141,16 @@ export default config
|
|
|
141
141
|
|
|
142
142
|
The `getAbsolutePath` function is a helper function typically added by [Storybook] automatically.
|
|
143
143
|
|
|
144
|
+
In `.storybook/preview.ts`, you can enable automatic snapshot by adding the `addonVis` addon and setting `auto` to `true`.
|
|
145
|
+
This will enable automatic snapshot taking at the end of each test.
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
// .storybook/preview.ts
|
|
149
|
+
export default {
|
|
150
|
+
tags: ['snapshot'],
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
144
154
|
### Ignore snapshot folders
|
|
145
155
|
|
|
146
156
|
Since [storybook-addon-vis][storybook-addon-vis] will save snapshot on your file system,
|
|
@@ -219,12 +229,12 @@ causes inconsistency and confuses both the editor and you.
|
|
|
219
229
|
### Basic Setup for CSF Next
|
|
220
230
|
|
|
221
231
|
If you are writing your stories in CSF Next,
|
|
222
|
-
|
|
223
|
-
Instead, you
|
|
224
|
-
|
|
232
|
+
You don't need to setup the visual testing in `vitest.setup.ts`.
|
|
233
|
+
Instead, you should setup the visual testing in `.storybook/preview.ts`.
|
|
225
234
|
|
|
226
235
|
```ts
|
|
227
236
|
// vitest.config.ts
|
|
237
|
+
// vitest.config.ts
|
|
228
238
|
import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'
|
|
229
239
|
import { storybookVis } from 'storybook-addon-vis/vitest-plugin'
|
|
230
240
|
import { defineConfig } from 'vitest/config'
|
|
@@ -236,19 +246,18 @@ export default defineConfig({
|
|
|
236
246
|
],
|
|
237
247
|
test: {
|
|
238
248
|
browser: { ... }, // your Vitest Browser Mode configuration
|
|
239
|
-
// setupFiles: ['./vitest.setup.ts'], //
|
|
249
|
+
// setupFiles: ['./vitest.setup.ts'], // REMOVE THIS
|
|
240
250
|
}
|
|
241
251
|
})
|
|
242
|
-
```
|
|
243
252
|
|
|
244
|
-
```ts
|
|
245
253
|
// .storybook/preview.ts
|
|
246
254
|
import addonVis from 'storybook-addon-vis'
|
|
247
255
|
import { definePreview } from '@storybook/your-framework/node'
|
|
248
256
|
|
|
249
257
|
export default definePreview({
|
|
250
258
|
addons: [
|
|
251
|
-
|
|
259
|
+
// Enable automatic snapshot taking at the end of each test
|
|
260
|
+
addonVis({ auto: true })
|
|
252
261
|
]
|
|
253
262
|
})
|
|
254
263
|
```
|
|
@@ -295,48 +304,32 @@ The options are the same as the options in [`vitest-plugin-vis`][vitest-plugin-v
|
|
|
295
304
|
|
|
296
305
|
For more details, please refer to the [vitest-plugin-vis documentation](https://github.com/repobuddy/visual-testing/tree/main/packages/vitest-plugin-vis).
|
|
297
306
|
|
|
298
|
-
In
|
|
299
|
-
|
|
300
|
-
The `addonVis()` used in `.storybook/preview.ts` and `vis.setup()` used in `vitest.setup.ts` have the same options.
|
|
301
|
-
Here, we will use the `addonVis()` options as an example.
|
|
307
|
+
In `vitest.setup.ts`, you can customize how the automatic snapshots are taken.
|
|
302
308
|
|
|
303
309
|
```ts
|
|
304
|
-
// .
|
|
305
|
-
import
|
|
306
|
-
import { definePreview } from '@storybook/your-framework/node'
|
|
310
|
+
// vitest.setup.ts
|
|
311
|
+
import { vis } from 'storybook-addon-vis/setup'
|
|
307
312
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
// Note that this changes the theme in the `afterEach` hook.
|
|
326
|
-
// If you want to capture manual snapshots in different themes,
|
|
327
|
-
// configure Vitest to run the tests in different themes.
|
|
328
|
-
addonVis({
|
|
329
|
-
auto: {
|
|
330
|
-
async dark() { document.body.classList.add('dark') },
|
|
331
|
-
async light() { document.body.classList.remove('dark') },
|
|
332
|
-
}
|
|
333
|
-
})
|
|
334
|
-
]
|
|
313
|
+
vis.setup({
|
|
314
|
+
// With automatic snapshot taking at the end of each test
|
|
315
|
+
auto: true,
|
|
316
|
+
|
|
317
|
+
// Control when automatic snapshot taking occurs
|
|
318
|
+
auto: async ({ tags }) => tags.includes('presentation'),
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
// Capture image snapshot at the end of each test for multiple themes (light and dark in this example).
|
|
322
|
+
//
|
|
323
|
+
// Note that this changes the theme in the `afterEach` hook.
|
|
324
|
+
// If you want to capture manual snapshots in different themes,
|
|
325
|
+
// configure Vitest to run the tests in different themes.
|
|
326
|
+
auto: {
|
|
327
|
+
async dark() { document.body.classList.add('dark') },
|
|
328
|
+
async light() { document.body.classList.remove('dark') },
|
|
329
|
+
}
|
|
335
330
|
})
|
|
336
331
|
```
|
|
337
332
|
|
|
338
|
-
All setup above will enable snapshot testing in storybook when the story has the `snapshot` tag.
|
|
339
|
-
|
|
340
333
|
#### Multiple vitest projects or custom snapshot paths
|
|
341
334
|
|
|
342
335
|
If your setup uses multiple vitest projects or custom paths,
|
package/src/vitest-setup.ts
CHANGED