storybook-addon-vis 4.0.0 → 4.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/{contants-DcocjING.mjs → exports/constants-D_WcloLE.mjs} +2 -2
- package/dist/exports/constants-D_WcloLE.mjs.map +1 -0
- package/dist/exports/matcher.d.mts +1 -0
- package/dist/{node.d.mts → exports/node.d.mts} +1 -1
- package/dist/exports/node.d.mts.map +1 -0
- package/dist/exports/node.mjs.map +1 -0
- package/dist/{preset.d.mts → exports/preset.d.mts} +2 -2
- package/dist/exports/preset.d.mts.map +1 -0
- package/dist/{preset.mjs → exports/preset.mjs} +14 -8
- package/dist/exports/preset.mjs.map +1 -0
- package/dist/{types-BG2k_RS_.d.mts → exports/types-CuNXsk6J.d.mts} +8 -1
- package/dist/exports/types-CuNXsk6J.d.mts.map +1 -0
- package/dist/exports/vitest-plugin.d.mts.map +1 -0
- package/dist/{vitest-plugin.mjs → exports/vitest-plugin.mjs} +1 -1
- package/dist/exports/vitest-plugin.mjs.map +1 -0
- package/dist/{vitest-setup.d.ts → exports/vitest-setup.d.mts} +3 -3
- package/dist/exports/vitest-setup.d.mts.map +1 -0
- package/dist/{vitest-setup.js → exports/vitest-setup.mjs} +3 -3
- package/dist/exports/vitest-setup.mjs.map +1 -0
- package/dist/{global_matcher_augment-CYxLwns2.d.ts → global_matcher_augment-B1plNA_9.d.mts} +1 -1
- package/dist/global_matcher_augment-B1plNA_9.d.mts.map +1 -0
- package/dist/{index.d.ts → index.d.mts} +3 -2
- package/dist/index.d.mts.map +1 -0
- package/dist/{index.js → index.mjs} +6 -5
- package/dist/index.mjs.map +1 -0
- package/dist/manager.js +2 -2
- package/dist/manager.js.map +1 -1
- package/dist/{vis_annotation-B8BqzClA.js → vis_annotation-B5Jl50Wp.mjs} +1 -1
- package/dist/vis_annotation-B5Jl50Wp.mjs.map +1 -0
- package/manager.js +2 -1
- package/package.json +23 -33
- package/preset.js +2 -1
- package/readme.md +2 -0
- package/src/{manager.tsx → exports/manager.tsx} +3 -3
- package/src/exports/matcher.ts +1 -0
- package/src/exports/node.ts +2 -0
- package/src/{preset.ts → exports/preset.ts} +4 -4
- package/src/exports/vitest-plugin.ts +2 -0
- package/src/{vitest-setup.ts → exports/vitest-setup.ts} +4 -4
- package/src/index.ts +12 -5
- package/src/overview.mdx +22 -1
- package/src/server/create_storybook_vis_server.ts +8 -1
- package/src/server/types.ts +7 -0
- package/src/vitest-plugin/storybook_vis.ts +1 -1
- package/dist/contants-DcocjING.mjs.map +0 -1
- package/dist/global_matcher_augment-CYxLwns2.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/matcher.d.ts +0 -1
- package/dist/node.d.mts.map +0 -1
- package/dist/node.mjs.map +0 -1
- package/dist/preset.d.mts.map +0 -1
- package/dist/preset.mjs.map +0 -1
- package/dist/types-BG2k_RS_.d.mts.map +0 -1
- package/dist/vis_annotation-B8BqzClA.js.map +0 -1
- package/dist/vitest-plugin.d.mts.map +0 -1
- package/dist/vitest-plugin.mjs.map +0 -1
- package/dist/vitest-setup.d.ts.map +0 -1
- package/dist/vitest-setup.js.map +0 -1
- package/src/matcher.ts +0 -1
- package/src/node.ts +0 -2
- package/src/testing.ts +0 -1
- package/src/vitest-plugin.ts +0 -2
- /package/dist/{matcher.js → exports/matcher.mjs} +0 -0
- /package/dist/{node.mjs → exports/node.mjs} +0 -0
- /package/dist/{vitest-plugin.d.mts → exports/vitest-plugin.d.mts} +0 -0
- /package/src/shared/{contants.ts → constants.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
//#region src/shared/
|
|
1
|
+
//#region src/shared/constants.ts
|
|
2
2
|
const NAME = "storybook-addon-vis";
|
|
3
3
|
const VIS_PANEL_ID = `${NAME}/vis_panel`;
|
|
4
4
|
|
|
5
5
|
//#endregion
|
|
6
6
|
export { NAME as t };
|
|
7
|
-
//# sourceMappingURL=
|
|
7
|
+
//# sourceMappingURL=constants-D_WcloLE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-D_WcloLE.mjs","names":[],"sources":["../../src/shared/constants.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 @@
|
|
|
1
|
+
import "../global_matcher_augment-B1plNA_9.mjs";
|
|
@@ -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"}
|
|
@@ -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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as StorybookVisOptions } from "./types-
|
|
1
|
+
import { t as StorybookVisOptions } from "./types-CuNXsk6J.mjs";
|
|
2
2
|
import { Channel } from "storybook/internal/channels";
|
|
3
3
|
|
|
4
|
-
//#region src/preset.d.ts
|
|
4
|
+
//#region src/exports/preset.d.ts
|
|
5
5
|
declare const experimental_serverChannel: (channel: Channel, options: StorybookVisOptions) => Promise<Channel>;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { experimental_serverChannel };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.d.mts","names":[],"sources":["../../src/exports/preset.ts"],"sourcesContent":[],"mappings":";;;;cAMa,sCAA6C,kBAAkB,wBAAmB,QAAA"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { t as NAME } from "./
|
|
1
|
+
import { t as NAME } from "./constants-D_WcloLE.mjs";
|
|
2
2
|
import { globSync } from "glob";
|
|
3
3
|
import ci from "is-ci";
|
|
4
4
|
import memoize from "memoize";
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import { platform } from "node:process";
|
|
7
7
|
import { basename, resolve } from "pathe";
|
|
8
|
-
import { BASELINE_DIR, DIFF_DIR, SNAPSHOT_ROOT_DIR, getSnapshotRootDir, trimCommonFolder } from "vitest-plugin-vis/server-utils";
|
|
8
|
+
import { BASELINE_DIR, DIFF_DIR, SNAPSHOT_ROOT_DIR, getSnapshotRootDir, resolveSnapshotSubpathWithinLimits, trimCommonFolder } from "vitest-plugin-vis/server-utils";
|
|
9
9
|
|
|
10
10
|
//#region src/server/create_storybook_vis_server.ts
|
|
11
11
|
function createStorybookVisServer(options) {
|
|
@@ -14,12 +14,18 @@ function createStorybookVisServer(options) {
|
|
|
14
14
|
options,
|
|
15
15
|
async getImageSnapshotResults(name, importPath) {
|
|
16
16
|
return visSuites.map((suite) => {
|
|
17
|
+
const snapshotRootDir = typeof suite.snapshotRootDir === "string" ? suite.snapshotRootDir : typeof suite.snapshotRootDir === "function" ? memoize(suite.snapshotRootDir)({
|
|
18
|
+
ci,
|
|
19
|
+
platform
|
|
20
|
+
}) : memoize(getSnapshotRootDir)(SNAPSHOT_ROOT_DIR);
|
|
21
|
+
const snapshotSubpathRaw = (typeof suite.snapshotSubpath === "function" ? memoize(suite.snapshotSubpath) : memoize(({ subpath }) => trimCommonFolder(subpath.startsWith("./") ? subpath.slice(2) : subpath)))({ subpath: importPath });
|
|
17
22
|
return {
|
|
18
|
-
snapshotRootDir
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
snapshotRootDir,
|
|
24
|
+
snapshotSubpath: resolveSnapshotSubpathWithinLimits({
|
|
25
|
+
snapshotBaselineRootAbs: resolve(snapshotRootDir, BASELINE_DIR),
|
|
26
|
+
rawSnapshotSubpath: snapshotSubpathRaw,
|
|
27
|
+
shortenLongSnapshotPaths: suite.shortenLongSnapshotPaths === true
|
|
28
|
+
})
|
|
23
29
|
};
|
|
24
30
|
}).flatMap(({ snapshotRootDir, snapshotSubpath }) => {
|
|
25
31
|
const taskId = name.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
@@ -50,7 +56,7 @@ const IMAGE_SNAPSHOT_RESULTS_REQUEST = "IMAGE_SNAPSHOT_RESULTS_REQUEST";
|
|
|
50
56
|
const IMAGE_SNAPSHOT_RESULTS_RESPONSE = "IMAGE_SNAPSHOT_RESULTS_RESPONSE";
|
|
51
57
|
|
|
52
58
|
//#endregion
|
|
53
|
-
//#region src/preset.ts
|
|
59
|
+
//#region src/exports/preset.ts
|
|
54
60
|
const experimental_serverChannel = async (channel, options) => {
|
|
55
61
|
const server = createStorybookVisServer(options);
|
|
56
62
|
channel.on(NAME, async (event) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.mjs","names":[],"sources":["../../src/server/create_storybook_vis_server.ts","../../src/shared/events.ts","../../src/exports/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\tresolveSnapshotSubpathWithinLimits,\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 snapshotSubpathRaw = snapshotSubpathFn({ subpath: importPath })\n\t\t\t\t\tconst snapshotBaselineRootAbs = resolve(snapshotRootDir, BASELINE_DIR)\n\t\t\t\t\tconst snapshotSubpath = resolveSnapshotSubpathWithinLimits({\n\t\t\t\t\t\tsnapshotBaselineRootAbs,\n\t\t\t\t\t\trawSnapshotSubpath: snapshotSubpathRaw,\n\t\t\t\t\t\tshortenLongSnapshotPaths: suite.shortenLongSnapshotPaths === true,\n\t\t\t\t\t})\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/constants.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":";;;;;;;;;;AAgBA,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;IACf,MAAM,kBACL,OAAO,MAAM,oBAAoB,WAC9B,MAAM,kBACN,OAAO,MAAM,oBAAoB,aAChC,QAAQ,MAAM,gBAAgB,CAAC;KAC/B;KACA;KACA,CAAC,GACD,QAAQ,mBAAmB,CAAC,kBAAkB;IAQnD,MAAM,sBALL,OAAO,MAAM,oBAAoB,aAC9B,QAAQ,MAAM,gBAAgB,GAC9B,SAAS,EAAE,cACX,iBAAiB,QAAQ,WAAW,KAAK,GAAG,QAAQ,MAAM,EAAE,GAAG,QAAQ,CACvE,EACyC,EAAE,SAAS,YAAY,CAAC;AAOrE,WAAO;KACN;KACA,iBAPuB,mCAAmC;MAC1D,yBAF+B,QAAQ,iBAAiB,aAAa;MAGrE,oBAAoB;MACpB,0BAA0B,MAAM,6BAA6B;MAC7D,CAAC;KAID;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;;;;;AC1EF,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"}
|
|
@@ -15,8 +15,15 @@ type StorybookVisOptions = {
|
|
|
15
15
|
snapshotSubpath?: ((options: {
|
|
16
16
|
subpath: string;
|
|
17
17
|
}) => string) | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Match Vitest `vis({ shortenLongSnapshotPaths })`. When true, uses the same path rules as
|
|
20
|
+
* the `vitest-plugin-vis`: paths are shortened when their absolute path would exceed safe limits).
|
|
21
|
+
*
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
shortenLongSnapshotPaths?: boolean | undefined;
|
|
18
25
|
}>;
|
|
19
26
|
};
|
|
20
27
|
//#endregion
|
|
21
28
|
export { StorybookVisOptions as t };
|
|
22
|
-
//# sourceMappingURL=types-
|
|
29
|
+
//# sourceMappingURL=types-CuNXsk6J.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-CuNXsk6J.d.mts","names":[],"sources":["../../src/server/types.ts"],"sourcesContent":[],"mappings":";;AAOA;;;;;;KAAY,mBAAA;eACE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-plugin.d.mts","names":[],"sources":["../../src/vitest-plugin/storybook_vis.ts"],"sourcesContent":[],"mappings":";;;;;AAOuC,iBAAvB,YAAuB,CAAA,UAAA,gBAAA,CAAA,CAAA,OAAA,CAAA,EAA4B,IAA5B,CAAiC,UAAjC,CAA4C,CAA5C,CAAA,EAAA,QAAA,CAAA,GAAA,SAAA,CAAA,EAAA,GAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-plugin.mjs","names":[],"sources":["../../src/vitest-plugin/storybook_vis.ts"],"sourcesContent":["/**\n * Return type is `any` to support different Vitest and Vite versions.\n */\nimport type { Omit } from 'type-plus'\nimport { type ComparisonMethod, type VisOptions, vis } from 'vitest-plugin-vis/config'\nimport { NAME } from '../shared/constants.ts'\n\nexport function storybookVis<M extends ComparisonMethod>(options?: Omit<VisOptions<M>, 'preset'> | undefined): any {\n\treturn {\n\t\t...vis({\n\t\t\t...options,\n\t\t\tpreset: 'custom',\n\t\t}),\n\t\tname: NAME,\n\t}\n}\n"],"mappings":";;;;AAOA,SAAgB,aAAyC,SAA0D;AAClH,QAAO;EACN,GAAG,IAAI;GACN,GAAG;GACH,QAAQ;GACR,CAAC;EACF,MAAM;EACN"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "
|
|
1
|
+
import "../global_matcher_augment-B1plNA_9.mjs";
|
|
2
2
|
import * as storybook_internal_csf1 from "storybook/internal/csf";
|
|
3
3
|
import { setAutoSnapshotOptions } from "vitest-plugin-vis";
|
|
4
4
|
import * as vitest_plugin_vis_setup_api0 from "vitest-plugin-vis/setup-api";
|
|
@@ -8,10 +8,10 @@ declare const visAnnotations: {
|
|
|
8
8
|
beforeEach(ctx: storybook_internal_csf1.StoryContext<any, storybook_internal_csf1.Args>): void;
|
|
9
9
|
};
|
|
10
10
|
//#endregion
|
|
11
|
-
//#region src/vitest-setup.d.ts
|
|
11
|
+
//#region src/exports/vitest-setup.d.ts
|
|
12
12
|
declare const vis: vitest_plugin_vis_setup_api0.VisClientConfigurator<{
|
|
13
13
|
tags: string[];
|
|
14
14
|
}>;
|
|
15
15
|
//#endregion
|
|
16
16
|
export { setAutoSnapshotOptions, vis, visAnnotations };
|
|
17
|
-
//# sourceMappingURL=vitest-setup.d.
|
|
17
|
+
//# sourceMappingURL=vitest-setup.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-setup.d.mts","names":[],"sources":["../../src/preview/vis_annotation.ts","../../src/exports/vitest-setup.ts"],"sourcesContent":[],"mappings":";;;;;;cAKa;kBAWoC,uBAAA,CAAA,kBAAA,uBAAA,CAAA,IAAA;;;;cCTpC,KAA6C,4BAAA,CAA1C"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { r as commands, t as visAnnotations } from "
|
|
1
|
+
import { r as commands, t as visAnnotations } from "../vis_annotation-B5Jl50Wp.mjs";
|
|
2
2
|
import { setAutoSnapshotOptions } from "vitest-plugin-vis";
|
|
3
3
|
import { createVis } from "vitest-plugin-vis/setup-api";
|
|
4
4
|
|
|
5
|
-
//#region src/vitest-setup.ts
|
|
5
|
+
//#region src/exports/vitest-setup.ts
|
|
6
6
|
const vis = createVis(commands);
|
|
7
7
|
|
|
8
8
|
//#endregion
|
|
9
9
|
export { setAutoSnapshotOptions, vis, visAnnotations };
|
|
10
|
-
//# sourceMappingURL=vitest-setup.
|
|
10
|
+
//# sourceMappingURL=vitest-setup.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-setup.mjs","names":[],"sources":["../../src/exports/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-api'\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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global_matcher_augment-B1plNA_9.d.mts","names":[],"sources":["../src/shared/global_matcher_augment.ts"],"sourcesContent":[],"mappings":";;;;;IAEwE,UAAA,QAAA,CAAA,CAAA,EAAA,CAAA,CAAA,SAIrC,oBAJqC,CAAA,CAAA;EAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./global_matcher_augment-
|
|
1
|
+
import "./global_matcher_augment-B1plNA_9.mjs";
|
|
2
2
|
import { ComparisonMethod, FailureThresholdOptions, ImageSnapshotCompareOptions, ImageSnapshotKeyOptions, ImageSnapshotKeyOptions as ImageSnapshotKeyOptions$1, ImageSnapshotSubjectOptions, ImageSnapshotTimeoutOptions, PixelComparisonOptions, SsimComparisonOptions, ToMatchImageSnapshotOptions } from "vitest-plugin-vis/client-api";
|
|
3
3
|
import * as storybook_internal_csf0 from "storybook/internal/csf";
|
|
4
4
|
import { SetupVisOptions } from "vitest-plugin-vis";
|
|
@@ -22,6 +22,7 @@ declare function hasImageSnapshot(options?: ImageSnapshotKeyOptions$1 | undefine
|
|
|
22
22
|
declare function defineAutoSnapshotParam<M extends ComparisonMethod>(snapshot: ToMatchImageSnapshotOptions<M> & ImageSnapshotSubjectOptions): {
|
|
23
23
|
snapshot: ImageSnapshotTimeoutOptions & ImageSnapshotKeyOptions & (M extends "ssim" ? SsimComparisonOptions<M> : PixelComparisonOptions<M>) & FailureThresholdOptions & {
|
|
24
24
|
expectToFail?: boolean | undefined;
|
|
25
|
+
createMissingBaseline?: boolean | undefined;
|
|
25
26
|
} & ImageSnapshotSubjectOptions;
|
|
26
27
|
};
|
|
27
28
|
//#endregion
|
|
@@ -32,4 +33,4 @@ declare function isSnapshotEnabled(tags: string[]): boolean;
|
|
|
32
33
|
declare const _default: (options?: SetupVisOptions) => storybook_internal_csf0.PreviewAddon<storybook_internal_csf0.AddonTypes>;
|
|
33
34
|
//#endregion
|
|
34
35
|
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 };
|
|
35
|
-
//# sourceMappingURL=index.d.
|
|
36
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","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;;;;;AFZ5C,CAAA;;;iBGjBgB,iBAAA;;;cCgBD,qBAEU,oBAAiC,uBAAA,CAAA,aAAA,uBAAA,CAAA,UAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as page, i as getCurrentTest, n as isSnapshotEnabled, r as commands, t as visAnnotations } from "./vis_annotation-
|
|
1
|
+
import { a as page, i as getCurrentTest, n as isSnapshotEnabled, r as commands, t as visAnnotations } from "./vis_annotation-B5Jl50Wp.mjs";
|
|
2
2
|
import { expect } from "storybook/test";
|
|
3
3
|
import { autoSnapshotMatcher, hasImageSnapshotAction, setAutoSnapshotOptions, toTaskId } from "vitest-plugin-vis/client-api";
|
|
4
4
|
import { definePreviewAddon } from "storybook/internal/csf";
|
|
@@ -42,9 +42,10 @@ var src_default = (options = { auto: false }) => {
|
|
|
42
42
|
tags: options.auto ? ["snapshot"] : [],
|
|
43
43
|
async beforeAll() {
|
|
44
44
|
matcher = autoSnapshotMatcher(commands, expect);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
else matcherFn = matcher.createMatcher(
|
|
45
|
+
const suiteDefaults = options?.createMissingBaseline !== void 0 ? { createMissingBaseline: options.createMissingBaseline } : void 0;
|
|
46
|
+
if (typeof options?.auto === "function") matcherFn = matcher.createMatcher({ auto: options.auto }, suiteDefaults);
|
|
47
|
+
else if (typeof options?.auto === "object") matcherFn = matcher.createMatcher(options.auto, suiteDefaults);
|
|
48
|
+
else matcherFn = matcher.createMatcher({ async auto() {} }, suiteDefaults);
|
|
48
49
|
await matcher.setup();
|
|
49
50
|
await setAutoSnapshotOptions(true);
|
|
50
51
|
},
|
|
@@ -57,4 +58,4 @@ var src_default = (options = { auto: false }) => {
|
|
|
57
58
|
|
|
58
59
|
//#endregion
|
|
59
60
|
export { src_default as default, defineAutoSnapshotParam, hasImageSnapshot, isSnapshotEnabled, page };
|
|
60
|
-
//# sourceMappingURL=index.
|
|
61
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","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 { 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\tconst suiteDefaults =\n\t\t\t\toptions?.createMissingBaseline !== undefined\n\t\t\t\t\t? { createMissingBaseline: options.createMissingBaseline }\n\t\t\t\t\t: undefined\n\t\t\tif (typeof options?.auto === 'function') {\n\t\t\t\tmatcherFn = matcher.createMatcher(\n\t\t\t\t\t{\n\t\t\t\t\t\tauto: options.auto,\n\t\t\t\t\t},\n\t\t\t\t\tsuiteDefaults,\n\t\t\t\t)\n\t\t\t} else if (typeof options?.auto === 'object') {\n\t\t\t\tmatcherFn = matcher.createMatcher(options.auto, suiteDefaults)\n\t\t\t} else matcherFn = matcher.createMatcher({ async auto() {} }, suiteDefaults)\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,IAAI;CACJ,IAAI;AACJ,QAAO,mBAAmB;EACzB,MAAM,QAAQ,OAAO,CAAC,WAAW,GAAG,EAAE;EACtC,MAAM,YAAY;AACjB,aAAU,oBAAoB,UAAU,OAAO;GAC/C,MAAM,gBACL,SAAS,0BAA0B,SAChC,EAAE,uBAAuB,QAAQ,uBAAuB,GACxD;AACJ,OAAI,OAAO,SAAS,SAAS,WAC5B,aAAY,QAAQ,cACnB,EACC,MAAM,QAAQ,MACd,EACD,cACA;YACS,OAAO,SAAS,SAAS,SACnC,aAAY,QAAQ,cAAc,QAAQ,MAAM,cAAc;OACxD,aAAY,QAAQ,cAAc,EAAE,MAAM,OAAO,IAAI,EAAE,cAAc;AAE5E,SAAM,QAAQ,OAAO;AACrB,SAAM,uBAAuB,KAAK;;EAEnC,YAAY;AACX,OAAI,UACH,QAAO,WAAW;;EAGpB,GAAG;EACH,CAAC"}
|
package/dist/manager.js
CHANGED
|
@@ -43,7 +43,7 @@ const SnapshotRow = styled.div(({ theme, failed }) => ({
|
|
|
43
43
|
}));
|
|
44
44
|
|
|
45
45
|
//#endregion
|
|
46
|
-
//#region src/shared/
|
|
46
|
+
//#region src/shared/constants.ts
|
|
47
47
|
const NAME = "storybook-addon-vis";
|
|
48
48
|
const VIS_PANEL_ID = `${NAME}/vis_panel`;
|
|
49
49
|
|
|
@@ -60,7 +60,7 @@ function requestImageSnapshotResults({ name, importPath }) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
//#endregion
|
|
63
|
-
//#region src/manager.tsx
|
|
63
|
+
//#region src/exports/manager.tsx
|
|
64
64
|
addons.register(NAME, (api) => {
|
|
65
65
|
if (globalThis.CONFIG_TYPE === "DEVELOPMENT") addons.add(VIS_PANEL_ID, {
|
|
66
66
|
type: types.PANEL,
|
package/dist/manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","names":["VisPanel"],"sources":["../src/components/vis_panel.tsx","../src/shared/
|
|
1
|
+
{"version":3,"file":"manager.js","names":["VisPanel"],"sources":["../src/components/vis_panel.tsx","../src/shared/constants.ts","../src/shared/events.ts","../src/exports/manager.tsx"],"sourcesContent":["import { RefreshIcon } from '@storybook/icons'\nimport React, { memo, useEffect, useState } from 'react'\nimport { AddonPanel, Button, 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\tgetSnapshotResults: () => Promise<ImageSnapshotResults[]>\n\tonRefresh: () => void\n}\n\nexport const VisPanel = memo(function VisPanel({ active, getSnapshotResults, onRefresh }: PanelProps) {\n\tconst [snapshotResults, setSnapshotResults] = useState<ImageSnapshotResults[]>([])\n\n\tuseEffect(() => {\n\t\tgetSnapshotResults().then(setSnapshotResults)\n\t}, [getSnapshotResults])\n\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<Button\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Reload snapshot\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tonRefresh()\n\t\t\t\t\t\t\t\t\t\t\t\tgetSnapshotResults().then(setSnapshotResults)\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<RefreshIcon />\n\t\t\t\t\t\t\t\t\t\t</Button>\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 }>(\n\t({ theme, failed }: { theme: any; failed?: boolean | undefined }) => ({\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tgap: '0.5rem',\n\t\tpaddingBlock: '0.5rem',\n\t\tpaddingInline: '0.2rem',\n\t\tbackgroundColor: failed ? theme.background.negative : theme.background.positive,\n\t\tcolor: theme.barTextColor,\n\t}),\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 from 'react'\nimport { addons, types } from 'storybook/manager-api'\nimport { VisPanel } from '../components/vis_panel.tsx'\nimport { NAME, VIS_PANEL_ID } from '../shared/constants.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\tif (!active) return null\n\t\t\t\tconst storyData = api.getCurrentStoryData()\n\t\t\t\tif (!storyData) return null\n\t\t\t\tapi.emit(NAME, requestImageSnapshotResults(storyData))\n\t\t\t\tasync function getSnapshotResults() {\n\t\t\t\t\treturn new Promise<ImageSnapshotResults[]>((resolve) => {\n\t\t\t\t\t\tapi.once(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\t\t\t\t\t\t\tif (event.type === IMAGE_SNAPSHOT_RESULTS_RESPONSE) {\n\t\t\t\t\t\t\t\tresolve(event.results)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t}\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\tgetSnapshotResults={getSnapshotResults}\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,oBAAoB,aAAyB;CACrG,MAAM,CAAC,iBAAiB,sBAAsB,SAAiC,EAAE,CAAC;AAElF,iBAAgB;AACf,sBAAoB,CAAC,KAAK,mBAAmB;IAC3C,CAAC,mBAAmB,CAAC;CAExB,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;EACA,cAAW;EACX,eAAe;AACd,cAAW;AACX,uBAAoB,CAAC,KAAK,mBAAmB;;IAG9C,oCAAC,kBAAc,CACP,CACI,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,KACzB,EAAE,OAAO,cAA4D;CACrE,SAAS;CACT,YAAY;CACZ,KAAK;CACL,cAAc;CACd,eAAe;CACf,iBAAiB,SAAS,MAAM,WAAW,WAAW,MAAM,WAAW;CACvE,OAAO,MAAM;CACb,EACD;;;;ACnFD,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;AAClB,OAAI,CAAC,OAAQ,QAAO;GACpB,MAAM,YAAY,IAAI,qBAAqB;AAC3C,OAAI,CAAC,UAAW,QAAO;AACvB,OAAI,KAAK,MAAM,4BAA4B,UAAU,CAAC;GACtD,eAAe,qBAAqB;AACnC,WAAO,IAAI,SAAiC,YAAY;AACvD,SAAI,KAAK,OAAO,UAAoB;AACnC,UAAI,MAAM,SAAS,UAAU,KAAM;AACnC,UAAI,MAAM,eAAe,UAAU,WAAY;AAC/C,UAAI,MAAM,SAAS,gCAClB,SAAQ,MAAM,QAAQ;OAEtB;MACD;;AAEH,UACC,oCAAC;IACQ;IACY;IACpB,iBAAiB;AAChB,SAAI,UAAW,KAAI,KAAK,MAAM,4BAA4B,UAAU,CAAC;;KAErE;;EAGJ,CAAC;EAEF"}
|
|
@@ -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-B5Jl50Wp.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vis_annotation-B5Jl50Wp.mjs","names":["toMatchImageSnapshot"],"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 vitest: Awaited<typeof import('vitest')>\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').then((m) => {\n\t\tvitest = 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\tvitest?.TestRunner.getCurrentTest() as\n\t\t| (ReturnType<typeof vitest.TestRunner.getCurrentTest> & SnapshotTestMeta)\n\t\t| 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,IAAI;AACJ,IAAI;AAEJ,IAAK,WAAmB,oBAAoB;AAC3C,QAAO,kBAAkB,MAAM,MAAM;AACpC,IAAE,KAAK,OAAO,EAAE,8CAAsB,CAAC;AACvC,mBAAiB;GAChB;AACF,QAAO,UAAU,MAAM,MAAM;AAC5B,WAAS;GACR;;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,QAAQ,WAAW,gBAAgB;;;;ACxBpC,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/manager.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import './dist/manager.js'
|
|
1
|
+
import './dist/exports/manager.js';
|
|
2
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "storybook-addon-vis",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Storybook Vitest visual testing addon",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"image-snapshot",
|
|
@@ -24,35 +24,25 @@
|
|
|
24
24
|
},
|
|
25
25
|
"type": "module",
|
|
26
26
|
"imports": {
|
|
27
|
-
"#storybook-addon-vis
|
|
28
|
-
"#storybook-addon-vis/
|
|
27
|
+
"#storybook-addon-vis": "./src/index.ts",
|
|
28
|
+
"#storybook-addon-vis/node": "./src/exports/node.ts",
|
|
29
|
+
"#storybook-addon-vis/vitest-plugin": "./src/exports/vitest-plugin.ts",
|
|
30
|
+
"#storybook-addon-vis/vitest-setup": "./src/exports/vitest-setup.ts"
|
|
29
31
|
},
|
|
30
32
|
"exports": {
|
|
31
33
|
".": {
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
+
"source": "./src/index.ts",
|
|
35
|
+
"types": "./dist/index.d.mts",
|
|
36
|
+
"default": "./dist/index.mjs"
|
|
34
37
|
},
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
"types": "./dist/
|
|
38
|
-
"
|
|
39
|
-
},
|
|
40
|
-
"./node": {
|
|
41
|
-
"types": "./dist/node.d.mts",
|
|
42
|
-
"import": "./dist/node.mjs"
|
|
43
|
-
},
|
|
44
|
-
"./preset": "./dist/preset.mjs",
|
|
45
|
-
"./vitest-setup": {
|
|
46
|
-
"types": "./dist/vitest-setup.d.ts",
|
|
47
|
-
"import": "./dist/vitest-setup.js"
|
|
48
|
-
},
|
|
49
|
-
"./vitest-plugin": {
|
|
50
|
-
"types": "./dist/vitest-plugin.d.mts",
|
|
51
|
-
"import": "./dist/vitest-plugin.mjs"
|
|
38
|
+
"./*": {
|
|
39
|
+
"source": "./src/exports/*.ts",
|
|
40
|
+
"types": "./dist/exports/*.d.mts",
|
|
41
|
+
"default": "./dist/exports/*.mjs"
|
|
52
42
|
},
|
|
53
43
|
"./package.json": "./package.json"
|
|
54
44
|
},
|
|
55
|
-
"types": "./dist/index.d.
|
|
45
|
+
"types": "./dist/index.d.mts",
|
|
56
46
|
"files": [
|
|
57
47
|
"dist",
|
|
58
48
|
"src",
|
|
@@ -67,7 +57,7 @@
|
|
|
67
57
|
"memoize": "^11.0.0",
|
|
68
58
|
"pathe": "^2.0.3",
|
|
69
59
|
"type-plus": "8.0.0-beta.8",
|
|
70
|
-
"vitest-plugin-vis": "^5.
|
|
60
|
+
"vitest-plugin-vis": "^5.1.0"
|
|
71
61
|
},
|
|
72
62
|
"devDependencies": {
|
|
73
63
|
"@repobuddy/storybook": "^2.28.0",
|
|
@@ -80,7 +70,7 @@
|
|
|
80
70
|
"@testing-library/react": "^16.0.1",
|
|
81
71
|
"@types/react": "^19.2.2",
|
|
82
72
|
"@types/react-dom": "^19.2.1",
|
|
83
|
-
"@vitejs/plugin-react": "^
|
|
73
|
+
"@vitejs/plugin-react": "^6.0.0",
|
|
84
74
|
"@vitest/browser": "^4.1.4",
|
|
85
75
|
"@vitest/browser-playwright": "^4.1.4",
|
|
86
76
|
"@vitest/browser-webdriverio": "^4.1.4",
|
|
@@ -97,7 +87,7 @@
|
|
|
97
87
|
"storybook-addon-tag-badges": "^3.1.0",
|
|
98
88
|
"tailwindcss": "^4.1.14",
|
|
99
89
|
"tsdown": "^0.19.0",
|
|
100
|
-
"typescript": "^
|
|
90
|
+
"typescript": "^6.0.0",
|
|
101
91
|
"vite": "^8.0.0",
|
|
102
92
|
"vitest": "^4.1.4",
|
|
103
93
|
"vitest-browser-react": "^2.0.2",
|
|
@@ -115,17 +105,17 @@
|
|
|
115
105
|
},
|
|
116
106
|
"bundler": {
|
|
117
107
|
"exportEntries": [
|
|
118
|
-
"src/index.ts",
|
|
119
|
-
"src/matcher.ts",
|
|
120
|
-
"src/vitest-setup.ts"
|
|
108
|
+
"./src/index.ts",
|
|
109
|
+
"./src/exports/matcher.ts",
|
|
110
|
+
"./src/exports/vitest-setup.ts"
|
|
121
111
|
],
|
|
122
112
|
"managerEntries": [
|
|
123
|
-
"src/manager.tsx"
|
|
113
|
+
"./src/exports/manager.tsx"
|
|
124
114
|
],
|
|
125
115
|
"nodeEntries": [
|
|
126
|
-
"./src/node.ts",
|
|
127
|
-
"./src/preset.ts",
|
|
128
|
-
"./src/vitest-plugin.ts"
|
|
116
|
+
"./src/exports/node.ts",
|
|
117
|
+
"./src/exports/preset.ts",
|
|
118
|
+
"./src/exports/vitest-plugin.ts"
|
|
129
119
|
]
|
|
130
120
|
},
|
|
131
121
|
"storybook": {
|
package/preset.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export * from './dist/preset.mjs'
|
|
1
|
+
export * from './dist/exports/preset.mjs';
|
|
2
|
+
|
package/readme.md
CHANGED
|
@@ -31,6 +31,8 @@ and controls how the auto image snapshot(s) are taken.
|
|
|
31
31
|
> [storybook-addon-vis] 2.0.0 supports Storybook 9.
|
|
32
32
|
>
|
|
33
33
|
> For Storybook 8, please use 1.x.
|
|
34
|
+
>
|
|
35
|
+
> With **Storybook 10.3+**, `@storybook/addon-vitest` often applies project annotations for you. If you are **not** on CSF Next, you may need to **remove** `visAnnotations` from `setProjectAnnotations([...])` in `vitest.setup.ts` and register the same hooks from **`.storybook/preview.ts`** instead (for example via `definePreview({ addons: [addonVis(...)] })` or `export default { ...visAnnotations, ... }`). See the [Overview docs](https://repobuddy.github.io/visual-testing/?path=/docs/overview--docs#storybook-103-and-vitest-project-annotations) section **Storybook 10.3+ and Vitest project annotations**.
|
|
34
36
|
|
|
35
37
|
## Install
|
|
36
38
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { addons, types } from 'storybook/manager-api'
|
|
3
|
-
import { VisPanel } from '
|
|
4
|
-
import { NAME, VIS_PANEL_ID } from '
|
|
3
|
+
import { VisPanel } from '../components/vis_panel.tsx'
|
|
4
|
+
import { NAME, VIS_PANEL_ID } from '../shared/constants.ts'
|
|
5
5
|
import {
|
|
6
6
|
IMAGE_SNAPSHOT_RESULTS_RESPONSE,
|
|
7
7
|
requestImageSnapshotResults,
|
|
8
8
|
type ImageSnapshotResults,
|
|
9
9
|
type VisEvent,
|
|
10
|
-
} from '
|
|
10
|
+
} from '../shared/events.ts'
|
|
11
11
|
|
|
12
12
|
// Register the addon
|
|
13
13
|
addons.register(NAME, (api) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '../shared/global_matcher_augment.ts'
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Channel } from 'storybook/internal/channels'
|
|
2
|
-
import { createStorybookVisServer } from '
|
|
3
|
-
import type { StorybookVisOptions } from '
|
|
4
|
-
import { NAME } from '
|
|
5
|
-
import { IMAGE_SNAPSHOT_RESULTS_REQUEST, IMAGE_SNAPSHOT_RESULTS_RESPONSE, type VisEvent } from '
|
|
2
|
+
import { createStorybookVisServer } from '../server/create_storybook_vis_server.ts'
|
|
3
|
+
import type { StorybookVisOptions } from '../server/types.ts'
|
|
4
|
+
import { NAME } from '../shared/constants.ts'
|
|
5
|
+
import { IMAGE_SNAPSHOT_RESULTS_REQUEST, IMAGE_SNAPSHOT_RESULTS_RESPONSE, type VisEvent } from '../shared/events.ts'
|
|
6
6
|
|
|
7
7
|
export const experimental_serverChannel = async (channel: Channel, options: StorybookVisOptions) => {
|
|
8
8
|
const server = createStorybookVisServer(options)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// `storybook-addon-vis/vitest-setup` provides code needed in `vitest.setup.ts`.
|
|
2
|
-
import '
|
|
3
|
-
import '
|
|
2
|
+
import '../client/storybook/expect_extend.ts'
|
|
3
|
+
import '../shared/global_matcher_augment.ts'
|
|
4
4
|
|
|
5
5
|
import { createVis } from 'vitest-plugin-vis/setup-api'
|
|
6
|
-
import { commands } from '
|
|
6
|
+
import { commands } from '../client/vitest_proxy.ts'
|
|
7
7
|
|
|
8
8
|
export const vis = createVis<{ tags: string[] }>(commands)
|
|
9
9
|
export { setAutoSnapshotOptions } from 'vitest-plugin-vis'
|
|
10
|
-
export { visAnnotations } from '
|
|
10
|
+
export { visAnnotations } from '../preview/vis_annotation.ts'
|
package/src/index.ts
CHANGED
|
@@ -23,13 +23,20 @@ export default (options: SetupVisOptions = { auto: false }) => {
|
|
|
23
23
|
tags: options.auto ? ['snapshot'] : [],
|
|
24
24
|
async beforeAll() {
|
|
25
25
|
matcher = autoSnapshotMatcher(commands, expect)
|
|
26
|
+
const suiteDefaults =
|
|
27
|
+
options?.createMissingBaseline !== undefined
|
|
28
|
+
? { createMissingBaseline: options.createMissingBaseline }
|
|
29
|
+
: undefined
|
|
26
30
|
if (typeof options?.auto === 'function') {
|
|
27
|
-
matcherFn = matcher.createMatcher(
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
matcherFn = matcher.createMatcher(
|
|
32
|
+
{
|
|
33
|
+
auto: options.auto,
|
|
34
|
+
},
|
|
35
|
+
suiteDefaults,
|
|
36
|
+
)
|
|
30
37
|
} else if (typeof options?.auto === 'object') {
|
|
31
|
-
matcherFn = matcher.createMatcher(options.auto)
|
|
32
|
-
} else matcherFn = matcher.createMatcher({ async auto() {} })
|
|
38
|
+
matcherFn = matcher.createMatcher(options.auto, suiteDefaults)
|
|
39
|
+
} else matcherFn = matcher.createMatcher({ async auto() {} }, suiteDefaults)
|
|
33
40
|
|
|
34
41
|
await matcher.setup()
|
|
35
42
|
await setAutoSnapshotOptions(true)
|
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 `vitest.setup.ts`
|
|
39
|
+
- Configure visual testing in `vitest.setup.ts` and/or `.storybook/preview.ts` (see [Storybook 10.3+ and Vitest project annotations](#storybook-103-and-vitest-project-annotations); with CSF Next, prefer preview-only setup as in [Basic Setup for CSF Next](#basic-setup-for-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
|
|
|
@@ -102,6 +102,21 @@ beforeAll(annotations.beforeAll)
|
|
|
102
102
|
vis.setup()
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
<a id="storybook-103-and-vitest-project-annotations" />
|
|
106
|
+
|
|
107
|
+
### Storybook 10.3+ and Vitest project annotations
|
|
108
|
+
|
|
109
|
+
From **Storybook 10.3** onward, [`@storybook/addon-vitest`][storybook-vitest-addon] often injects project annotations for you (for example via `setProjectAnnotations(getProjectAnnotations())`), so you may not need a hand-maintained `vitest.setup.ts` in every project. See the [Storybook Vitest integration docs][storybook-vitest-addon] for the current recommendation.
|
|
110
|
+
|
|
111
|
+
**If you are not using CSF Next** (or have not moved your preview config to `definePreview`), you may still need to adjust your setup: **do not** rely only on merging `visAnnotations` inside `setProjectAnnotations([...])` in `vitest.setup.ts`. Put the same lifecycle hooks in **`.storybook/preview.ts`** instead, so `getProjectAnnotations()` includes them when the Vitest addon builds annotations from your preview stack.
|
|
112
|
+
|
|
113
|
+
You can do that in either of these ways:
|
|
114
|
+
|
|
115
|
+
1. **Recommended:** use `definePreview({ addons: [addonVis({ auto: true })] })` in `preview.ts` even while your stories stay CSF 3—the pattern is the same as in [Basic Setup for CSF Next](#basic-setup-for-csf-next).
|
|
116
|
+
2. **Minimal migration:** import `visAnnotations` from `storybook-addon-vis/vitest-setup` and spread them into a classic preview export, for example `export default { ...visAnnotations, tags: ['snapshot'] }`, if you are not ready for `definePreview`.
|
|
117
|
+
|
|
118
|
+
You may still need `vis.setup()` and the `storybookVis()` Vitest plugin depending on your project; this note is only about **where** `visAnnotations` is merged (preview vs Vitest setup).
|
|
119
|
+
|
|
105
120
|
For [Storybook], you need to add the addon to your `.storybook/main.ts`:
|
|
106
121
|
```ts
|
|
107
122
|
// .storybook/main.ts
|
|
@@ -169,6 +184,12 @@ Note that the `__vis__/*/__baselines__` should not be ignored,
|
|
|
169
184
|
as it is used to store the baseline images.
|
|
170
185
|
They should be committed to your repository.
|
|
171
186
|
|
|
187
|
+
### First-run baselines (`createMissingBaseline` vs `updateSnapshot`)
|
|
188
|
+
|
|
189
|
+
In **vitest-plugin-vis** (and when using the same client APIs outside Storybook’s Vitest bridge), `createMissingBaseline: true` on `toMatchImageSnapshot` / `page.toMatchImageSnapshot`, or `vis.setup({ createMissingBaseline: true, ... })`, can create a missing baseline without passing `-u`.
|
|
190
|
+
|
|
191
|
+
When running **Storybook + Vitest browser mode** through this addon, matcher options are serialized over RPC; custom fields such as `createMissingBaseline` may not reach the server. In that setup, use Vitest’s snapshot update mode instead (for example temporarily set `server.config.snapshotOptions.updateSnapshot = 'all'` around the first run, or run with `-u`) to write new baselines—the same mechanism as a normal snapshot update.
|
|
192
|
+
|
|
172
193
|
### TypeScript Configuration
|
|
173
194
|
|
|
174
195
|
If you want to do manual snapshot testing, you need to tell TypeScript about the matcher.
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
BASELINE_DIR,
|
|
9
9
|
DIFF_DIR,
|
|
10
10
|
getSnapshotRootDir,
|
|
11
|
+
resolveSnapshotSubpathWithinLimits,
|
|
11
12
|
SNAPSHOT_ROOT_DIR,
|
|
12
13
|
trimCommonFolder,
|
|
13
14
|
} from 'vitest-plugin-vis/server-utils'
|
|
@@ -36,7 +37,13 @@ export function createStorybookVisServer(options: StorybookVisOptions) {
|
|
|
36
37
|
: memoize(({ subpath }: { subpath: string }) =>
|
|
37
38
|
trimCommonFolder(subpath.startsWith('./') ? subpath.slice(2) : subpath),
|
|
38
39
|
)
|
|
39
|
-
const
|
|
40
|
+
const snapshotSubpathRaw = snapshotSubpathFn({ subpath: importPath })
|
|
41
|
+
const snapshotBaselineRootAbs = resolve(snapshotRootDir, BASELINE_DIR)
|
|
42
|
+
const snapshotSubpath = resolveSnapshotSubpathWithinLimits({
|
|
43
|
+
snapshotBaselineRootAbs,
|
|
44
|
+
rawSnapshotSubpath: snapshotSubpathRaw,
|
|
45
|
+
shortenLongSnapshotPaths: suite.shortenLongSnapshotPaths === true,
|
|
46
|
+
})
|
|
40
47
|
return {
|
|
41
48
|
snapshotRootDir,
|
|
42
49
|
snapshotSubpath,
|
package/src/server/types.ts
CHANGED
|
@@ -9,5 +9,12 @@ export type StorybookVisOptions = {
|
|
|
9
9
|
visProjects: Array<{
|
|
10
10
|
snapshotRootDir: string | ((context: { ci: boolean; platform: string }) => string) | undefined
|
|
11
11
|
snapshotSubpath?: ((options: { subpath: string }) => string) | undefined
|
|
12
|
+
/**
|
|
13
|
+
* Match Vitest `vis({ shortenLongSnapshotPaths })`. When true, uses the same path rules as
|
|
14
|
+
* the `vitest-plugin-vis`: paths are shortened when their absolute path would exceed safe limits).
|
|
15
|
+
*
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
shortenLongSnapshotPaths?: boolean | undefined
|
|
12
19
|
}>
|
|
13
20
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { Omit } from 'type-plus'
|
|
5
5
|
import { type ComparisonMethod, type VisOptions, vis } from 'vitest-plugin-vis/config'
|
|
6
|
-
import { NAME } from '../shared/
|
|
6
|
+
import { NAME } from '../shared/constants.ts'
|
|
7
7
|
|
|
8
8
|
export function storybookVis<M extends ComparisonMethod>(options?: Omit<VisOptions<M>, 'preset'> | undefined): any {
|
|
9
9
|
return {
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1 +0,0 @@
|
|
|
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,SAIrC,oBAJqC,CAAA,CAAA;EAAA"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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 { 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,IAAI;CACJ,IAAI;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/matcher.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "./global_matcher_augment-CYxLwns2.js";
|
package/dist/node.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/preset.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"preset.d.mts","names":[],"sources":["../src/preset.ts"],"sourcesContent":[],"mappings":";;;;cAMa,sCAA6C,kBAAkB,wBAAmB,QAAA"}
|
package/dist/preset.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-BG2k_RS_.d.mts","names":[],"sources":["../src/server/types.ts"],"sourcesContent":[],"mappings":";;AAOA;;;;;;KAAY,mBAAA;eACE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vis_annotation-B8BqzClA.js","names":["toMatchImageSnapshot"],"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 vitest: Awaited<typeof import('vitest')>\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').then((m) => {\n\t\tvitest = 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\tvitest?.TestRunner.getCurrentTest() as\n\t\t| (ReturnType<typeof vitest.TestRunner.getCurrentTest> & SnapshotTestMeta)\n\t\t| 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,IAAI;AACJ,IAAI;AAEJ,IAAK,WAAmB,oBAAoB;AAC3C,QAAO,kBAAkB,MAAM,MAAM;AACpC,IAAE,KAAK,OAAO,EAAE,8CAAsB,CAAC;AACvC,mBAAiB;GAChB;AACF,QAAO,UAAU,MAAM,MAAM;AAC5B,WAAS;GACR;;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,QAAQ,WAAW,gBAAgB;;;;ACxBpC,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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-plugin.d.mts","names":[],"sources":["../src/vitest-plugin/storybook_vis.ts"],"sourcesContent":[],"mappings":";;;;;AAOuC,iBAAvB,YAAuB,CAAA,UAAA,gBAAA,CAAA,CAAA,OAAA,CAAA,EAA4B,IAA5B,CAAiC,UAAjC,CAA4C,CAA5C,CAAA,EAAA,QAAA,CAAA,GAAA,SAAA,CAAA,EAAA,GAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-plugin.mjs","names":[],"sources":["../src/vitest-plugin/storybook_vis.ts"],"sourcesContent":["/**\n * Return type is `any` to support different Vitest and Vite versions.\n */\nimport type { Omit } from 'type-plus'\nimport { type ComparisonMethod, type VisOptions, vis } from 'vitest-plugin-vis/config'\nimport { NAME } from '../shared/contants.ts'\n\nexport function storybookVis<M extends ComparisonMethod>(options?: Omit<VisOptions<M>, 'preset'> | undefined): any {\n\treturn {\n\t\t...vis({\n\t\t\t...options,\n\t\t\tpreset: 'custom',\n\t\t}),\n\t\tname: NAME,\n\t}\n}\n"],"mappings":";;;;AAOA,SAAgB,aAAyC,SAA0D;AAClH,QAAO;EACN,GAAG,IAAI;GACN,GAAG;GACH,QAAQ;GACR,CAAC;EACF,MAAM;EACN"}
|
|
@@ -1 +0,0 @@
|
|
|
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,4BAAA,CAA1C"}
|
package/dist/vitest-setup.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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-api'\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/src/matcher.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './shared/global_matcher_augment.ts'
|
package/src/node.ts
DELETED
package/src/testing.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from 'vitest-plugin-vis/testing'
|
package/src/vitest-plugin.ts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|