vitest-plugin-vis 5.0.0 → 5.1.1
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/auto_snapshots/_extract_auto_snapshot_options.mjs +1 -1
- package/dist/auto_snapshots/_extract_auto_snapshot_options.mjs.map +1 -1
- package/dist/client/external/vitest/vitest_suite_proxy.d.mts +0 -1
- package/dist/client/snapshot/compare_image_snapshot.logic.mjs +2 -1
- package/dist/client/snapshot/compare_image_snapshot.logic.mjs.map +1 -1
- package/dist/client/snapshot/compare_image_snapshot.mjs +1 -1
- package/dist/client/snapshot/compare_image_snapshot.mjs.map +1 -1
- package/dist/client/suite/auto_snapshot_matcher.d.mts +2 -2
- package/dist/client/suite/auto_snapshot_matcher.d.mts.map +1 -1
- package/dist/client/suite/auto_snapshot_matcher.mjs +5 -3
- package/dist/client/suite/auto_snapshot_matcher.mjs.map +1 -1
- package/dist/config/types.d.mts +14 -0
- package/dist/{client-api.d.mts → exports/client-api.d.mts} +12 -12
- package/dist/exports/client-api.mjs +11 -0
- package/dist/exports/config.d.mts +5 -0
- package/dist/exports/config.mjs +4 -0
- package/dist/exports/presets/auto.mjs +9 -0
- package/dist/exports/presets/auto.mjs.map +1 -0
- package/dist/exports/presets/manual.mjs +9 -0
- package/dist/exports/presets/manual.mjs.map +1 -0
- package/dist/exports/server-utils.d.mts +5 -0
- package/dist/exports/server-utils.mjs +6 -0
- package/dist/exports/setup-api.d.mts +4 -0
- package/dist/exports/setup-api.mjs +5 -0
- package/dist/exports/setup.d.mts +3 -0
- package/dist/exports/setup.mjs +4 -0
- package/dist/exports/testing/node.d.mts +4 -0
- package/dist/exports/testing/node.mjs +5 -0
- package/dist/exports/testing.d.mts +2 -0
- package/dist/exports/testing.mjs +3 -0
- package/dist/server/commands/prepare_image_snapshot_comparison.mjs.map +1 -1
- package/dist/server/commands/prepare_page_image_snapshot_comparison.mjs.map +1 -1
- package/dist/server/snapshot_path.d.mts +0 -1
- package/dist/server/snapshot_path.d.mts.map +1 -1
- package/dist/server/snapshot_path_limits.d.mts +28 -0
- package/dist/server/snapshot_path_limits.d.mts.map +1 -0
- package/dist/server/snapshot_path_limits.mjs +92 -0
- package/dist/server/snapshot_path_limits.mjs.map +1 -0
- package/dist/server/suite.mjs +8 -2
- package/dist/server/suite.mjs.map +1 -1
- package/dist/server/testing/stubBrowserCommandContext.mjs +9 -0
- package/dist/server/testing/stubBrowserCommandContext.mjs.map +1 -0
- package/dist/server/testing/stubSuite.d.mts +17 -0
- package/dist/server/testing/stubSuite.d.mts.map +1 -0
- package/dist/server/testing/stubSuite.mjs +23 -0
- package/dist/server/testing/stubSuite.mjs.map +1 -0
- package/dist/server/testing/stubUserConfig.mjs +8 -0
- package/dist/server/testing/stubUserConfig.mjs.map +1 -0
- package/dist/server/vis_options.d.mts +120 -0
- package/dist/server/vis_options.d.mts.map +1 -0
- package/dist/server/vis_options.mjs +7 -1
- package/dist/server/vis_options.mjs.map +1 -1
- package/dist/server/vis_server_context.logic.mjs +37 -10
- package/dist/server/vis_server_context.logic.mjs.map +1 -1
- package/dist/server/vis_server_context.types.d.mts +32 -1
- package/dist/server/vis_server_context.types.d.mts.map +1 -0
- package/dist/setup/create_vis.mjs +6 -6
- package/dist/setup/create_vis.mjs.map +1 -1
- package/dist/shared/types.d.mts +21 -1
- package/dist/shared/types.d.mts.map +1 -1
- package/package.json +13 -36
- package/readme.md +6 -0
- package/src/auto_snapshots/_extract_auto_snapshot_options.ts +1 -1
- package/src/client/expect/to_match_image_snapshot.mdx +24 -1
- package/src/client/page/to_match_image_snapshot.mdx +23 -1
- package/src/client/snapshot/compare_image_snapshot.logic.ts +1 -0
- package/src/client/snapshot/compare_image_snapshot.ts +2 -2
- package/src/client/suite/auto_snapshot_matcher.ts +10 -2
- package/src/config/types.ts +14 -0
- package/src/exports/client-api.ts +13 -0
- package/src/exports/config.ts +3 -0
- package/src/exports/server-utils.ts +7 -0
- package/src/exports/setup-api.ts +5 -0
- package/src/exports/setup.ts +3 -0
- package/src/exports/testing/node.ts +4 -0
- package/src/exports/testing.ts +1 -0
- package/src/server/commands/prepare_image_snapshot_comparison.ts +2 -2
- package/src/server/commands/prepare_page_image_snapshot_comparison.ts +2 -1
- package/src/server/snapshot_path_limits.ts +135 -0
- package/src/server/suite.ts +19 -4
- package/src/server/vis_options.ts +10 -1
- package/src/server/vis_server_context.logic.ts +47 -17
- package/src/setup/create_vis.ts +12 -11
- package/src/shared/types.ts +21 -1
- package/dist/client-api.mjs +0 -11
- package/dist/config.d.mts +0 -5
- package/dist/config.mjs +0 -4
- package/dist/presets/auto.mjs +0 -9
- package/dist/presets/auto.mjs.map +0 -1
- package/dist/presets/manual.mjs +0 -9
- package/dist/presets/manual.mjs.map +0 -1
- package/dist/server-utils.d.mts +0 -4
- package/dist/server-utils.mjs +0 -5
- package/dist/setup-api.d.mts +0 -4
- package/dist/setup-api.mjs +0 -5
- package/dist/setup.d.mts +0 -3
- package/dist/setup.mjs +0 -4
- package/dist/testing.d.mts +0 -2
- package/dist/testing.mjs +0 -3
- package/src/client-api.ts +0 -13
- package/src/config.ts +0 -3
- package/src/server-utils.ts +0 -3
- package/src/setup-api.ts +0 -5
- package/src/setup.ts +0 -3
- package/src/testing.ts +0 -1
- /package/dist/{presets → exports/presets}/auto.d.mts +0 -0
- /package/dist/{presets → exports/presets}/manual.d.mts +0 -0
- /package/src/{presets → exports/presets}/auto.ts +0 -0
- /package/src/{presets → exports/presets}/manual.ts +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ExtendedBrowserCommandContext } from "../vis_server_context.types.mjs";
|
|
2
|
+
import { RecursivePartial } from "type-plus";
|
|
3
|
+
import * as vite0 from "vite";
|
|
4
|
+
import { TestUserConfig } from "vitest/node";
|
|
5
|
+
|
|
6
|
+
//#region src/server/testing/stubSuite.d.ts
|
|
7
|
+
declare function stubSuite(partialUserConfig?: RecursivePartial<{
|
|
8
|
+
test?: {
|
|
9
|
+
name?: TestUserConfig['name'];
|
|
10
|
+
};
|
|
11
|
+
}>, partialBrowserCommandContext?: RecursivePartial<ExtendedBrowserCommandContext>): {
|
|
12
|
+
userConfig: vite0.UserConfig;
|
|
13
|
+
browserCommandContext: ExtendedBrowserCommandContext;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { stubSuite };
|
|
17
|
+
//# sourceMappingURL=stubSuite.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stubSuite.d.mts","names":[],"sources":["../../../src/server/testing/stubSuite.ts"],"sourcesContent":[],"mappings":";;;;;;iBAOgB,SAAA,kBACuC,GAAnC;;WAAmC;EADvC,CAAA;CACuC,CAAA,EAAA,4BAAA,CAAA,EACxB,gBADwB,CACP,6BADO,CAAA,CAAA,EAAA;EAAnC,UAAA,EAC2B,KAAA,CAAA,UAD3B;EAC4B,qBAAA,+BAAA;CAAjB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { stubBrowserCommandContext } from "./stubBrowserCommandContext.mjs";
|
|
2
|
+
import { stubUserConfig } from "./stubUserConfig.mjs";
|
|
3
|
+
import { resolve } from "pathe";
|
|
4
|
+
import { requiredDeep } from "type-plus";
|
|
5
|
+
|
|
6
|
+
//#region src/server/testing/stubSuite.ts
|
|
7
|
+
function stubSuite(partialUserConfig = {}, partialBrowserCommandContext = {}) {
|
|
8
|
+
const root = resolve(import.meta.dirname, "../..");
|
|
9
|
+
return {
|
|
10
|
+
userConfig: stubUserConfig({
|
|
11
|
+
root,
|
|
12
|
+
...partialUserConfig
|
|
13
|
+
}),
|
|
14
|
+
browserCommandContext: stubBrowserCommandContext(requiredDeep({ project: {
|
|
15
|
+
config: { root },
|
|
16
|
+
runner: { config: { name: partialUserConfig.test?.name } }
|
|
17
|
+
} }, partialBrowserCommandContext))
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { stubSuite };
|
|
23
|
+
//# sourceMappingURL=stubSuite.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stubSuite.mjs","names":[],"sources":["../../../src/server/testing/stubSuite.ts"],"sourcesContent":["import { resolve } from 'pathe'\nimport { requiredDeep, type RecursivePartial } from 'type-plus'\nimport type { TestUserConfig } from 'vitest/node'\nimport type { ExtendedBrowserCommandContext } from '../vis_server_context.types.ts'\nimport { stubBrowserCommandContext } from './stubBrowserCommandContext.ts'\nimport { stubUserConfig } from './stubUserConfig.ts'\n\nexport function stubSuite(\n\tpartialUserConfig: RecursivePartial<{ test?: { name?: TestUserConfig['name'] } }> = {},\n\tpartialBrowserCommandContext: RecursivePartial<ExtendedBrowserCommandContext> = {},\n) {\n\tconst root = resolve(import.meta.dirname, '../..')\n\tconst userConfig = stubUserConfig({\n\t\troot,\n\t\t...partialUserConfig,\n\t})\n\tconst browserCommandContext = stubBrowserCommandContext(\n\t\trequiredDeep<RecursivePartial<ExtendedBrowserCommandContext>>(\n\t\t\t{\n\t\t\t\tproject: {\n\t\t\t\t\tconfig: { root },\n\t\t\t\t\trunner: {\n\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\tname: partialUserConfig.test?.name as string | undefined,\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\tpartialBrowserCommandContext,\n\t\t),\n\t)\n\treturn {\n\t\tuserConfig,\n\t\tbrowserCommandContext,\n\t}\n}\n"],"mappings":";;;;;;AAOA,SAAgB,UACf,oBAAoF,EAAE,EACtF,+BAAgF,EAAE,EACjF;CACD,MAAM,OAAO,QAAQ,OAAO,KAAK,SAAS,QAAQ;AAoBlD,QAAO;EACN,YApBkB,eAAe;GACjC;GACA,GAAG;GACH,CAAC;EAkBD,uBAjB6B,0BAC7B,aACC,EACC,SAAS;GACR,QAAQ,EAAE,MAAM;GAChB,QAAQ,EACP,QAAQ,EACP,MAAM,kBAAkB,MAAM,MAC9B,EACD;GACD,EACD,EACD,6BACA,CACD;EAIA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stubUserConfig.mjs","names":["stub"],"sources":["../../../src/server/testing/stubUserConfig.ts"],"sourcesContent":["import { stub } from 'type-plus'\nimport type { ViteUserConfig } from 'vitest/config'\n\nexport const stubUserConfig = stub.build<ViteUserConfig>((stub) => ({\n\t...stub,\n}))\n"],"mappings":";;;AAGA,MAAa,iBAAiB,KAAK,OAAuB,YAAU,EACnE,GAAGA,QACH,EAAE"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { PixelDiffOptions } from "../shared/types.mjs";
|
|
2
|
+
import { ExtendedBrowserCommandContext } from "./vis_server_context.types.mjs";
|
|
3
|
+
import "../index.mjs";
|
|
4
|
+
import * as ssim_js0 from "ssim.js";
|
|
5
|
+
import { TestUserConfig } from "vitest/node";
|
|
6
|
+
|
|
7
|
+
//#region src/server/vis_options.d.ts
|
|
8
|
+
|
|
9
|
+
declare function getVisOption(context: ExtendedBrowserCommandContext): {
|
|
10
|
+
comparisonMethod: any;
|
|
11
|
+
diffOptions?: Partial<ssim_js0.Options> | undefined;
|
|
12
|
+
failureThresholdType?: "pixel" | "percent" | undefined;
|
|
13
|
+
failureThreshold?: number | undefined;
|
|
14
|
+
timeout?: number | undefined;
|
|
15
|
+
snapshotKey?: string | undefined;
|
|
16
|
+
subject?: string | undefined;
|
|
17
|
+
preset?: "manual" | "auto" | "custom" | undefined;
|
|
18
|
+
snapshotRootDir?: string | ((context: {
|
|
19
|
+
ci: boolean;
|
|
20
|
+
rootDir: string;
|
|
21
|
+
projectName?: string | undefined;
|
|
22
|
+
browserName?: string | undefined;
|
|
23
|
+
providerName: string;
|
|
24
|
+
platform: string;
|
|
25
|
+
screenshotFailures?: boolean | undefined;
|
|
26
|
+
screenshotDirectory?: string | undefined;
|
|
27
|
+
}) => string) | undefined;
|
|
28
|
+
snapshotSubpath?: ((options: {
|
|
29
|
+
subpath: string;
|
|
30
|
+
}) => string) | undefined;
|
|
31
|
+
shortenLongSnapshotPaths?: boolean | undefined;
|
|
32
|
+
} | {
|
|
33
|
+
comparisonMethod: any;
|
|
34
|
+
diffOptions?: {
|
|
35
|
+
threshold?: number | undefined;
|
|
36
|
+
includeAA?: boolean | undefined;
|
|
37
|
+
alpha?: number | undefined;
|
|
38
|
+
aaColor?: [number, number, number] | undefined;
|
|
39
|
+
diffColor?: [number, number, number] | undefined;
|
|
40
|
+
diffColorAlt?: [number, number, number] | undefined;
|
|
41
|
+
diffMask?: boolean | undefined;
|
|
42
|
+
} | Partial<ssim_js0.Options> | undefined;
|
|
43
|
+
failureThresholdType?: "pixel" | "percent" | undefined;
|
|
44
|
+
failureThreshold?: number | undefined;
|
|
45
|
+
timeout?: number | undefined;
|
|
46
|
+
snapshotKey?: string | undefined;
|
|
47
|
+
subject?: string | undefined;
|
|
48
|
+
preset?: "manual" | "auto" | "custom" | undefined;
|
|
49
|
+
snapshotRootDir?: string | ((context: {
|
|
50
|
+
ci: boolean;
|
|
51
|
+
rootDir: string;
|
|
52
|
+
projectName?: string | undefined;
|
|
53
|
+
browserName?: string | undefined;
|
|
54
|
+
providerName: string;
|
|
55
|
+
platform: string;
|
|
56
|
+
screenshotFailures?: boolean | undefined;
|
|
57
|
+
screenshotDirectory?: string | undefined;
|
|
58
|
+
}) => string) | undefined;
|
|
59
|
+
snapshotSubpath?: ((options: {
|
|
60
|
+
subpath: string;
|
|
61
|
+
}) => string) | undefined;
|
|
62
|
+
shortenLongSnapshotPaths?: boolean | undefined;
|
|
63
|
+
} | {
|
|
64
|
+
comparisonMethod: any;
|
|
65
|
+
diffOptions?: {
|
|
66
|
+
threshold?: number | undefined;
|
|
67
|
+
includeAA?: boolean | undefined;
|
|
68
|
+
alpha?: number | undefined;
|
|
69
|
+
aaColor?: [number, number, number] | undefined;
|
|
70
|
+
diffColor?: [number, number, number] | undefined;
|
|
71
|
+
diffColorAlt?: [number, number, number] | undefined;
|
|
72
|
+
diffMask?: boolean | undefined;
|
|
73
|
+
} | Partial<ssim_js0.Options> | undefined;
|
|
74
|
+
failureThresholdType?: "pixel" | "percent" | undefined;
|
|
75
|
+
failureThreshold?: number | undefined;
|
|
76
|
+
timeout?: number | undefined;
|
|
77
|
+
snapshotKey?: string | undefined;
|
|
78
|
+
subject?: string | undefined;
|
|
79
|
+
preset?: "manual" | "auto" | "custom" | undefined;
|
|
80
|
+
snapshotRootDir?: string | ((context: {
|
|
81
|
+
ci: boolean;
|
|
82
|
+
rootDir: string;
|
|
83
|
+
projectName?: string | undefined;
|
|
84
|
+
browserName?: string | undefined;
|
|
85
|
+
providerName: string;
|
|
86
|
+
platform: string;
|
|
87
|
+
screenshotFailures?: boolean | undefined;
|
|
88
|
+
screenshotDirectory?: string | undefined;
|
|
89
|
+
}) => string) | undefined;
|
|
90
|
+
snapshotSubpath?: ((options: {
|
|
91
|
+
subpath: string;
|
|
92
|
+
}) => string) | undefined;
|
|
93
|
+
shortenLongSnapshotPaths?: boolean | undefined;
|
|
94
|
+
} | {
|
|
95
|
+
comparisonMethod?: any;
|
|
96
|
+
diffOptions?: PixelDiffOptions | undefined;
|
|
97
|
+
failureThresholdType?: "pixel" | "percent" | undefined;
|
|
98
|
+
failureThreshold?: number | undefined;
|
|
99
|
+
timeout?: number | undefined;
|
|
100
|
+
snapshotKey?: string | undefined;
|
|
101
|
+
subject?: string | undefined;
|
|
102
|
+
preset?: "manual" | "auto" | "custom" | undefined;
|
|
103
|
+
snapshotRootDir?: string | ((context: {
|
|
104
|
+
ci: boolean;
|
|
105
|
+
rootDir: string;
|
|
106
|
+
projectName?: string | undefined;
|
|
107
|
+
browserName?: string | undefined;
|
|
108
|
+
providerName: string;
|
|
109
|
+
platform: string;
|
|
110
|
+
screenshotFailures?: boolean | undefined;
|
|
111
|
+
screenshotDirectory?: string | undefined;
|
|
112
|
+
}) => string) | undefined;
|
|
113
|
+
snapshotSubpath?: ((options: {
|
|
114
|
+
subpath: string;
|
|
115
|
+
}) => string) | undefined;
|
|
116
|
+
shortenLongSnapshotPaths?: boolean | undefined;
|
|
117
|
+
};
|
|
118
|
+
//#endregion
|
|
119
|
+
export { getVisOption };
|
|
120
|
+
//# sourceMappingURL=vis_options.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vis_options.d.mts","names":[],"sources":["../../src/server/vis_options.ts"],"sourcesContent":[],"mappings":";;;;;;;;iBA6BgB,YAAA,UAAsB;;wBAA6B,QAAA,CAAA,OAAA"}
|
|
@@ -11,7 +11,13 @@ function setVisOption(userConfig, options) {
|
|
|
11
11
|
visOptions[id] = options;
|
|
12
12
|
}
|
|
13
13
|
function getVisOption(context) {
|
|
14
|
-
|
|
14
|
+
const id = getProjectName(context) || DEFAULT_PROJECT_NAME;
|
|
15
|
+
const base = visOptions[DEFAULT_PROJECT_NAME] ?? {};
|
|
16
|
+
const override = visOptions[id] ?? {};
|
|
17
|
+
return {
|
|
18
|
+
...base,
|
|
19
|
+
...override
|
|
20
|
+
};
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vis_options.mjs","names":[],"sources":["../../src/server/vis_options.ts"],"sourcesContent":["import type { TestUserConfig } from 'vitest/node'\nimport type { VisOptions } from '../config/types.ts'\nimport { assertSnapshotKeyWithoutDash } from '../shared/asserts.ts'\nimport { getProjectName } from './project.ts'\nimport type { ExtendedBrowserCommandContext } from './vis_server_context.types.ts'\n\nconst DEFAULT_PROJECT_NAME = '__default'\n\nconst visOptions: Record<string, VisOptions<any> | undefined> = {}\n\nexport function setVisOption(\n\tuserConfig: { test?: { name?: TestUserConfig['name'] | undefined } },\n\toptions: VisOptions<any> | undefined,\n) {\n\tassertSnapshotKeyWithoutDash(options?.snapshotKey)\n\n\tconst name = userConfig.test?.name\n\tconst id = typeof name === 'string' ? name : typeof name === 'object' ? name?.label : DEFAULT_PROJECT_NAME\n\n\tvisOptions[id] = options\n}\n\nexport function getVisOption(context: ExtendedBrowserCommandContext) {\n\tconst id = getProjectName(context) || DEFAULT_PROJECT_NAME\n\
|
|
1
|
+
{"version":3,"file":"vis_options.mjs","names":[],"sources":["../../src/server/vis_options.ts"],"sourcesContent":["import type { TestUserConfig } from 'vitest/node'\nimport type { VisOptions } from '../config/types.ts'\nimport { assertSnapshotKeyWithoutDash } from '../shared/asserts.ts'\nimport { getProjectName } from './project.ts'\nimport type { ExtendedBrowserCommandContext } from './vis_server_context.types.ts'\n\nconst DEFAULT_PROJECT_NAME = '__default'\n\nconst visOptions: Record<string, VisOptions<any> | undefined> = {}\n\n/** Clears stored options (for tests that share this module). */\nexport function clearVisOptionsRegistryForTesting() {\n\tfor (const key of Object.keys(visOptions)) {\n\t\tdelete visOptions[key]\n\t}\n}\n\nexport function setVisOption(\n\tuserConfig: { test?: { name?: TestUserConfig['name'] | undefined } },\n\toptions: VisOptions<any> | undefined,\n) {\n\tassertSnapshotKeyWithoutDash(options?.snapshotKey)\n\n\tconst name = userConfig.test?.name\n\tconst id = typeof name === 'string' ? name : typeof name === 'object' ? name?.label : DEFAULT_PROJECT_NAME\n\n\tvisOptions[id] = options\n}\n\nexport function getVisOption(context: ExtendedBrowserCommandContext) {\n\tconst id = getProjectName(context) || DEFAULT_PROJECT_NAME\n\tconst base = visOptions[DEFAULT_PROJECT_NAME] ?? {}\n\tconst override = visOptions[id] ?? {}\n\treturn { ...base, ...override }\n}\n"],"mappings":";;;;AAMA,MAAM,uBAAuB;AAE7B,MAAM,aAA0D,EAAE;AASlE,SAAgB,aACf,YACA,SACC;AACD,8BAA6B,SAAS,YAAY;CAElD,MAAM,OAAO,WAAW,MAAM;CAC9B,MAAM,KAAK,OAAO,SAAS,WAAW,OAAO,OAAO,SAAS,WAAW,MAAM,QAAQ;AAEtF,YAAW,MAAM;;AAGlB,SAAgB,aAAa,SAAwC;CACpE,MAAM,KAAK,eAAe,QAAQ,IAAI;CACtC,MAAM,OAAO,WAAW,yBAAyB,EAAE;CACnD,MAAM,WAAW,WAAW,OAAO,EAAE;AACrC,QAAO;EAAE,GAAG;EAAM,GAAG;EAAU"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { file } from "./externals/file.mjs";
|
|
2
|
+
import { absoluteSnapshotFilePath, getLegacySnapshotFilename, resolveLegacySnapshotFileRelativePath } from "./snapshot_path_limits.mjs";
|
|
2
3
|
import { getVisOption } from "./vis_options.mjs";
|
|
3
4
|
import { getSuite, getTaskSubpath } from "./suite.mjs";
|
|
4
5
|
import { basename, join, resolve } from "pathe";
|
|
@@ -9,14 +10,17 @@ function createVisServerContext() {
|
|
|
9
10
|
const context = {
|
|
10
11
|
async getSnapshotResults(browserContext, taskId) {
|
|
11
12
|
const suiteInfo = await context.getSuiteInfo(browserContext, taskId);
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const legacyPattern = join(resolve(suiteInfo.projectRoot, suiteInfo.baselineDir), `${suiteInfo.taskId}-*.png`);
|
|
14
|
+
const baselines = await file.glob(legacyPattern);
|
|
15
|
+
const resultPattern = join(resolve(suiteInfo.projectRoot, suiteInfo.resultDir), `${suiteInfo.taskId}-*.png`);
|
|
16
|
+
const results = await file.glob(resultPattern);
|
|
17
|
+
const diffPattern = join(resolve(suiteInfo.projectRoot, suiteInfo.diffDir), `${suiteInfo.taskId}-*.png`);
|
|
18
|
+
const diffs = await file.glob(diffPattern);
|
|
15
19
|
const r = [];
|
|
16
20
|
await Promise.all(baselines.map(async (baselinePath) => {
|
|
17
21
|
const filename = basename(baselinePath);
|
|
18
|
-
const resultPath = results.find((
|
|
19
|
-
const diffPath = diffs.find((
|
|
22
|
+
const resultPath = results.find((p) => p.endsWith(filename));
|
|
23
|
+
const diffPath = diffs.find((p) => p.endsWith(filename));
|
|
20
24
|
const baselineBuffer = await file.tryReadFile(baselinePath);
|
|
21
25
|
const resultBuffer = await file.tryReadFile(resultPath);
|
|
22
26
|
const diffBuffer = await file.tryReadFile(diffPath);
|
|
@@ -33,7 +37,7 @@ function createVisServerContext() {
|
|
|
33
37
|
const suiteInfo = await context.getSuiteInfo(browserContext, taskId);
|
|
34
38
|
const snapshotFilename = context.getSnapshotFilename(browserContext, suiteInfo, options?.snapshotKey);
|
|
35
39
|
const { baselineDir, resultDir, diffDir, task } = suiteInfo;
|
|
36
|
-
task.count
|
|
40
|
+
task.count += 1;
|
|
37
41
|
const baselinePath = join(baselineDir, snapshotFilename);
|
|
38
42
|
const resultPath = join(resultDir, snapshotFilename);
|
|
39
43
|
const diffPath = join(diffDir, snapshotFilename);
|
|
@@ -49,13 +53,36 @@ function createVisServerContext() {
|
|
|
49
53
|
},
|
|
50
54
|
async hasImageSnapshot(browserContext, taskId, snapshotKey) {
|
|
51
55
|
const info = await context.getSuiteInfo(browserContext, taskId);
|
|
52
|
-
|
|
56
|
+
const visOptions = getVisOption(browserContext);
|
|
57
|
+
const legacyFilename = getLegacySnapshotFilename({
|
|
58
|
+
taskId: info.taskId,
|
|
59
|
+
explicitSnapshotKey: snapshotKey,
|
|
60
|
+
defaultSnapshotKey: typeof visOptions.snapshotKey === "string" ? visOptions.snapshotKey : void 0,
|
|
61
|
+
taskCount: info.task.count
|
|
62
|
+
});
|
|
63
|
+
const filename = resolveLegacySnapshotFileRelativePath({
|
|
64
|
+
projectRoot: info.projectRoot,
|
|
65
|
+
baselineDir: info.baselineDir,
|
|
66
|
+
legacySnapshotFilename: legacyFilename,
|
|
67
|
+
shortenLongSnapshotPaths: visOptions.shortenLongSnapshotPaths === true
|
|
68
|
+
});
|
|
69
|
+
const legacyAbs = absoluteSnapshotFilePath(info.projectRoot, info.baselineDir, filename);
|
|
70
|
+
return file.existFile(legacyAbs);
|
|
53
71
|
},
|
|
54
72
|
getSnapshotFilename(browserContext, info, snapshotKey) {
|
|
55
|
-
if (snapshotKey) return `${info.taskId}-${snapshotKey}.png`;
|
|
56
73
|
const visOptions = getVisOption(browserContext);
|
|
57
|
-
|
|
58
|
-
|
|
74
|
+
const legacyFilename = getLegacySnapshotFilename({
|
|
75
|
+
taskId: info.taskId,
|
|
76
|
+
explicitSnapshotKey: snapshotKey,
|
|
77
|
+
defaultSnapshotKey: typeof visOptions.snapshotKey === "string" ? visOptions.snapshotKey : void 0,
|
|
78
|
+
taskCount: info.task.count
|
|
79
|
+
});
|
|
80
|
+
return resolveLegacySnapshotFileRelativePath({
|
|
81
|
+
projectRoot: info.projectRoot,
|
|
82
|
+
baselineDir: info.baselineDir,
|
|
83
|
+
legacySnapshotFilename: legacyFilename,
|
|
84
|
+
shortenLongSnapshotPaths: visOptions.shortenLongSnapshotPaths === true
|
|
85
|
+
});
|
|
59
86
|
},
|
|
60
87
|
async getSuiteInfo(browserContext, taskId) {
|
|
61
88
|
const projectState = await getSuite(browserContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vis_server_context.logic.mjs","names":[
|
|
1
|
+
{"version":3,"file":"vis_server_context.logic.mjs","names":[],"sources":["../../src/server/vis_server_context.logic.ts"],"sourcesContent":["import { basename, join, resolve } from 'pathe'\nimport { pick } from 'type-plus'\nimport type { ImageSnapshotKeyOptions } from '../exports/client-api.ts'\nimport type { ImageSnapshotResult } from '../shared/commands.types.ts'\nimport { file } from './externals/file.ts'\nimport {\n\tabsoluteSnapshotFilePath,\n\tgetLegacySnapshotFilename,\n\tresolveLegacySnapshotFileRelativePath,\n} from './snapshot_path_limits.ts'\nimport { getSuite, getTaskSubpath } from './suite.ts'\nimport { getVisOption } from './vis_options.ts'\nimport type { ExtendedBrowserCommandContext } from './vis_server_context.types.ts'\n\nexport function createVisServerContext() {\n\tconst context = {\n\t\tasync getSnapshotResults(browserContext: ExtendedBrowserCommandContext, taskId: string) {\n\t\t\tconst suiteInfo = await context.getSuiteInfo(browserContext, taskId)\n\t\t\tconst base = resolve(suiteInfo.projectRoot, suiteInfo.baselineDir)\n\n\t\t\tconst legacyPattern = join(base, `${suiteInfo.taskId}-*.png`)\n\t\t\tconst baselines = await file.glob(legacyPattern)\n\n\t\t\tconst resultPattern = join(resolve(suiteInfo.projectRoot, suiteInfo.resultDir), `${suiteInfo.taskId}-*.png`)\n\t\t\tconst results = await file.glob(resultPattern)\n\n\t\t\tconst diffPattern = join(resolve(suiteInfo.projectRoot, suiteInfo.diffDir), `${suiteInfo.taskId}-*.png`)\n\t\t\tconst diffs = await file.glob(diffPattern)\n\n\t\t\tconst r: ImageSnapshotResult[] = []\n\t\t\tawait Promise.all(\n\t\t\t\tbaselines.map(async (baselinePath) => {\n\t\t\t\t\tconst filename = basename(baselinePath)\n\t\t\t\t\tconst resultPath = results.find((p) => p.endsWith(filename))\n\t\t\t\t\tconst diffPath = diffs.find((p) => p.endsWith(filename))\n\n\t\t\t\t\tconst baselineBuffer = await file.tryReadFile(baselinePath)\n\t\t\t\t\tconst resultBuffer = await file.tryReadFile(resultPath)\n\t\t\t\t\tconst diffBuffer = await file.tryReadFile(diffPath)\n\t\t\t\t\tr.push({\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tbaseline: baselineBuffer?.toString('base64'),\n\t\t\t\t\t\tresult: resultBuffer?.toString('base64'),\n\t\t\t\t\t\tdiff: diffBuffer?.toString('base64'),\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t)\n\t\t\treturn r\n\t\t},\n\t\tasync getSnapshotInfo(\n\t\t\tbrowserContext: ExtendedBrowserCommandContext,\n\t\t\ttaskId: string,\n\t\t\toptions?: ImageSnapshotKeyOptions,\n\t\t) {\n\t\t\tconst suiteInfo = await context.getSuiteInfo(browserContext, taskId)\n\t\t\tconst snapshotFilename = context.getSnapshotFilename(browserContext, suiteInfo, options?.snapshotKey)\n\n\t\t\tconst { baselineDir, resultDir, diffDir, task } = suiteInfo\n\n\t\t\ttask.count += 1\n\t\t\tconst baselinePath = join(baselineDir, snapshotFilename)\n\t\t\tconst resultPath = join(resultDir, snapshotFilename)\n\t\t\tconst diffPath = join(diffDir, snapshotFilename)\n\n\t\t\treturn {\n\t\t\t\t...pick(\n\t\t\t\t\tgetVisOption(browserContext),\n\t\t\t\t\t'comparisonMethod',\n\t\t\t\t\t'diffOptions',\n\t\t\t\t\t'failureThreshold',\n\t\t\t\t\t'failureThresholdType',\n\t\t\t\t\t'timeout',\n\t\t\t\t),\n\t\t\t\tbaselinePath,\n\t\t\t\tresultPath,\n\t\t\t\tdiffPath,\n\t\t\t}\n\t\t},\n\n\t\tasync getTaskCount(browserContext: ExtendedBrowserCommandContext, taskId: string) {\n\t\t\treturn (await context.getSuiteInfo(browserContext, taskId)).task.count\n\t\t},\n\t\tasync hasImageSnapshot(\n\t\t\tbrowserContext: ExtendedBrowserCommandContext,\n\t\t\ttaskId: string,\n\t\t\tsnapshotKey: string | undefined,\n\t\t) {\n\t\t\tconst info = await context.getSuiteInfo(browserContext, taskId)\n\t\t\tconst visOptions = getVisOption(browserContext)\n\t\t\tconst legacyFilename = getLegacySnapshotFilename({\n\t\t\t\ttaskId: info.taskId,\n\t\t\t\texplicitSnapshotKey: snapshotKey,\n\t\t\t\tdefaultSnapshotKey: typeof visOptions.snapshotKey === 'string' ? visOptions.snapshotKey : undefined,\n\t\t\t\ttaskCount: info.task.count,\n\t\t\t})\n\t\t\tconst filename = resolveLegacySnapshotFileRelativePath({\n\t\t\t\tprojectRoot: info.projectRoot,\n\t\t\t\tbaselineDir: info.baselineDir,\n\t\t\t\tlegacySnapshotFilename: legacyFilename,\n\t\t\t\tshortenLongSnapshotPaths: visOptions.shortenLongSnapshotPaths === true,\n\t\t\t})\n\t\t\tconst legacyAbs = absoluteSnapshotFilePath(info.projectRoot, info.baselineDir, filename)\n\t\t\treturn file.existFile(legacyAbs)\n\t\t},\n\t\tgetSnapshotFilename(\n\t\t\tbrowserContext: ExtendedBrowserCommandContext,\n\t\t\tinfo: { taskId: string; task: { count: number }; suiteId: string; baselineDir: string; projectRoot: string },\n\t\t\tsnapshotKey: string | undefined,\n\t\t) {\n\t\t\tconst visOptions = getVisOption(browserContext)\n\t\t\tconst legacyFilename = getLegacySnapshotFilename({\n\t\t\t\ttaskId: info.taskId,\n\t\t\t\texplicitSnapshotKey: snapshotKey,\n\t\t\t\tdefaultSnapshotKey: typeof visOptions.snapshotKey === 'string' ? visOptions.snapshotKey : undefined,\n\t\t\t\ttaskCount: info.task.count,\n\t\t\t})\n\t\t\treturn resolveLegacySnapshotFileRelativePath({\n\t\t\t\tprojectRoot: info.projectRoot,\n\t\t\t\tbaselineDir: info.baselineDir,\n\t\t\t\tlegacySnapshotFilename: legacyFilename,\n\t\t\t\tshortenLongSnapshotPaths: visOptions.shortenLongSnapshotPaths === true,\n\t\t\t})\n\t\t},\n\t\tasync getSuiteInfo(browserContext: ExtendedBrowserCommandContext, taskId: string) {\n\t\t\tconst projectState = await getSuite(browserContext)\n\t\t\tconst visOptions = getVisOption(browserContext)\n\t\t\tconst moduleId = getTaskSubpath(projectState, browserContext.testPath, visOptions)\n\t\t\tconst m = projectState.modules[moduleId]!\n\t\t\tconst task = (m.tasks[taskId] = m.tasks[taskId] ?? { count: 1 })\n\t\t\treturn {\n\t\t\t\tprojectRoot: projectState.projectRoot,\n\t\t\t\tsuiteId: moduleId,\n\t\t\t\ttaskId,\n\t\t\t\tbaselineDir: m.baselineDir,\n\t\t\t\tresultDir: m.resultDir,\n\t\t\t\tdiffDir: m.diffDir,\n\t\t\t\ttask,\n\t\t\t}\n\t\t},\n\t}\n\treturn context\n}\n"],"mappings":"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"}
|
|
@@ -1 +1,32 @@
|
|
|
1
|
-
import "
|
|
1
|
+
import { Merge } from "type-plus";
|
|
2
|
+
import { BrowserCommandContext } from "vitest/node";
|
|
3
|
+
|
|
4
|
+
//#region src/server/vis_server_context.types.d.ts
|
|
5
|
+
|
|
6
|
+
type ExtendedBrowserCommandContext = {
|
|
7
|
+
page: BrowserCommandContext['page'];
|
|
8
|
+
browser: BrowserCommandContext['browser'];
|
|
9
|
+
iframe: BrowserCommandContext['iframe'];
|
|
10
|
+
testPath: NonNullable<BrowserCommandContext['testPath']>;
|
|
11
|
+
provider: BrowserCommandContext['provider'];
|
|
12
|
+
project: Merge<BrowserCommandContext['project'], {
|
|
13
|
+
browser: {
|
|
14
|
+
config: {
|
|
15
|
+
browser: {
|
|
16
|
+
name: string;
|
|
17
|
+
screenshotFailures: boolean;
|
|
18
|
+
screenshotDirectory: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
config: BrowserCommandContext['project']['config'];
|
|
23
|
+
runner: {
|
|
24
|
+
config: {
|
|
25
|
+
name: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
}>;
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
export { ExtendedBrowserCommandContext };
|
|
32
|
+
//# sourceMappingURL=vis_server_context.types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vis_server_context.types.d.mts","names":[],"sources":["../../src/server/vis_server_context.types.ts"],"sourcesContent":[],"mappings":";;;;;KAuCY,6BAAA;QACL;WACG;UACD;YACE,YAAY;YACZ;WAED,MACR;;;;;;;;;;YAWS"}
|
|
@@ -6,14 +6,14 @@ import { afterEach, beforeAll, expect } from "vitest";
|
|
|
6
6
|
function createVis(commands) {
|
|
7
7
|
const matcher = autoSnapshotMatcher(commands, expect);
|
|
8
8
|
return { setup(options) {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const suiteDefaults = options?.createMissingBaseline !== void 0 ? { createMissingBaseline: options.createMissingBaseline } : void 0;
|
|
10
|
+
beforeAll(async () => {
|
|
11
11
|
await matcher.setup();
|
|
12
|
-
setAutoSnapshotOptions(
|
|
12
|
+
setAutoSnapshotOptions(!!options?.auto);
|
|
13
13
|
});
|
|
14
|
-
if (typeof options?.auto === "function") afterEach(matcher.createMatcher({ auto: options.auto }));
|
|
15
|
-
else if (typeof options?.auto === "object") afterEach(matcher.createMatcher(options.auto));
|
|
16
|
-
else afterEach(matcher.createMatcher({ async auto() {} }));
|
|
14
|
+
if (typeof options?.auto === "function") afterEach(matcher.createMatcher({ auto: options.auto }, suiteDefaults));
|
|
15
|
+
else if (typeof options?.auto === "object") afterEach(matcher.createMatcher(options.auto, suiteDefaults));
|
|
16
|
+
else afterEach(matcher.createMatcher({ async auto() {} }, suiteDefaults));
|
|
17
17
|
} };
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create_vis.mjs","names":[],"sources":["../../src/setup/create_vis.ts"],"sourcesContent":["import { afterEach, beforeAll, expect } from 'vitest'\nimport { setAutoSnapshotOptions } from '../auto_snapshots/auto_snapshot_options.ts'\nimport { autoSnapshotMatcher } from '../client/suite/auto_snapshot_matcher.ts'\nimport type { SetupVisSuiteCommand } from '../shared/commands.types.ts'\nimport type { SetupVisOptions } from '../shared/types.ts'\n\n/**\n * Visual test configuration on the client side.\n */\nexport type VisClientConfigurator<GM extends Record<string, any> | unknown = unknown> = {\n\t/**\n\t * Setup the visual test configuration.\n\t *\n\t * @example\n\t * ```ts\n\t * // Setup with auto snapshot enabled\n\t * vis().setup({ auto: true })\n\t *\n\t * // Setup with auto snapshot disabled\n\t * vis().setup({ auto: false })\n\t *\n\t * // Same as `vis.setup({ auto: false })`\n\t * vis.setup()\n\t *\n\t * // Setup with auto snapshot determined by the test meta\n\t * vis.setup({\n\t * \tauto: async ({ meta }) => meta['darkOnly'],\n\t * })\n\t *\n\t * // Setup with multiple auto snapshots\n\t * vis.setup({\n\t * auto: {\n\t * async light() { document.body.classList.remove('dark') },\n\t * async dark() { document.body.classList.add('dark') },\n\t * }\n\t * })\n\t * ```\n\t */\n\tsetup(options?: SetupVisOptions<GM>): void\n}\n\nexport function createVis<GM extends Record<string, any> | unknown = unknown>(commands: SetupVisSuiteCommand) {\n\tconst matcher = autoSnapshotMatcher(commands, expect)\n\n\tconst vis: VisClientConfigurator<GM> = {\n\t\tsetup(options) {\n\t\t\
|
|
1
|
+
{"version":3,"file":"create_vis.mjs","names":[],"sources":["../../src/setup/create_vis.ts"],"sourcesContent":["import { afterEach, beforeAll, expect } from 'vitest'\nimport { setAutoSnapshotOptions } from '../auto_snapshots/auto_snapshot_options.ts'\nimport { autoSnapshotMatcher } from '../client/suite/auto_snapshot_matcher.ts'\nimport type { SetupVisSuiteCommand } from '../shared/commands.types.ts'\nimport type { SetupVisOptions } from '../shared/types.ts'\n\n/**\n * Visual test configuration on the client side.\n */\nexport type VisClientConfigurator<GM extends Record<string, any> | unknown = unknown> = {\n\t/**\n\t * Setup the visual test configuration.\n\t *\n\t * @example\n\t * ```ts\n\t * // Setup with auto snapshot enabled\n\t * vis().setup({ auto: true })\n\t *\n\t * // Setup with auto snapshot disabled\n\t * vis().setup({ auto: false })\n\t *\n\t * // Same as `vis.setup({ auto: false })`\n\t * vis.setup()\n\t *\n\t * // Setup with auto snapshot determined by the test meta\n\t * vis.setup({\n\t * \tauto: async ({ meta }) => meta['darkOnly'],\n\t * })\n\t *\n\t * // Setup with multiple auto snapshots\n\t * vis.setup({\n\t * auto: {\n\t * async light() { document.body.classList.remove('dark') },\n\t * async dark() { document.body.classList.add('dark') },\n\t * }\n\t * })\n\t * ```\n\t */\n\tsetup(options?: SetupVisOptions<GM>): void\n}\n\nexport function createVis<GM extends Record<string, any> | unknown = unknown>(commands: SetupVisSuiteCommand) {\n\tconst matcher = autoSnapshotMatcher(commands, expect)\n\n\tconst vis: VisClientConfigurator<GM> = {\n\t\tsetup(options) {\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\n\t\t\tbeforeAll(async () => {\n\t\t\t\tawait matcher.setup()\n\t\t\t\tsetAutoSnapshotOptions(!!options?.auto)\n\t\t\t})\n\n\t\t\tif (typeof options?.auto === 'function') {\n\t\t\t\tafterEach(matcher.createMatcher({ auto: options.auto }, suiteDefaults))\n\t\t\t} else if (typeof options?.auto === 'object') {\n\t\t\t\tafterEach(matcher.createMatcher(options.auto, suiteDefaults))\n\t\t\t} else {\n\t\t\t\tafterEach(matcher.createMatcher({ async auto() {} }, suiteDefaults))\n\t\t\t}\n\t\t},\n\t}\n\treturn vis\n}\n"],"mappings":";;;;;AAyCA,SAAgB,UAA8D,UAAgC;CAC7G,MAAM,UAAU,oBAAoB,UAAU,OAAO;AAuBrD,QArBuC,EACtC,MAAM,SAAS;EACd,MAAM,gBACL,SAAS,0BAA0B,SAChC,EAAE,uBAAuB,QAAQ,uBAAuB,GACxD;AAEJ,YAAU,YAAY;AACrB,SAAM,QAAQ,OAAO;AACrB,0BAAuB,CAAC,CAAC,SAAS,KAAK;IACtC;AAEF,MAAI,OAAO,SAAS,SAAS,WAC5B,WAAU,QAAQ,cAAc,EAAE,MAAM,QAAQ,MAAM,EAAE,cAAc,CAAC;WAC7D,OAAO,SAAS,SAAS,SACnC,WAAU,QAAQ,cAAc,QAAQ,MAAM,cAAc,CAAC;MAE7D,WAAU,QAAQ,cAAc,EAAE,MAAM,OAAO,IAAI,EAAE,cAAc,CAAC;IAGtE"}
|
package/dist/shared/types.d.mts
CHANGED
|
@@ -79,6 +79,15 @@ type ToMatchImageSnapshotOptions<M extends ComparisonMethod = 'pixel'> = ImageSn
|
|
|
79
79
|
* If it passes, it will throw an error with details.
|
|
80
80
|
*/
|
|
81
81
|
expectToFail?: boolean | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Create a baseline image when none exists on disk.
|
|
84
|
+
*
|
|
85
|
+
* If `true`, the captured image is written to the baseline path and the assertion succeeds,
|
|
86
|
+
* without Vitest `-u` / `updateSnapshot: 'all'`.
|
|
87
|
+
*
|
|
88
|
+
* @default false
|
|
89
|
+
*/
|
|
90
|
+
createMissingBaseline?: boolean | undefined;
|
|
82
91
|
};
|
|
83
92
|
interface PageImageSnapshotOptions {
|
|
84
93
|
fullPage?: boolean | undefined;
|
|
@@ -120,9 +129,20 @@ type ImageSnapshotComparisonInfo = {
|
|
|
120
129
|
*/
|
|
121
130
|
diff?: string | undefined;
|
|
122
131
|
} & ImageSnapshotTimeoutOptions & FailureThresholdOptions & (SsimComparisonOptions | PixelComparisonOptions);
|
|
123
|
-
type MatchImageSnapshotOptions = ImageSnapshotTimeoutOptions & ImageSnapshotCompareOptions<any> & ImageSnapshotKeyOptions
|
|
132
|
+
type MatchImageSnapshotOptions = ImageSnapshotTimeoutOptions & ImageSnapshotCompareOptions<any> & ImageSnapshotKeyOptions & {
|
|
133
|
+
/**
|
|
134
|
+
* When `true`, write a missing baseline on first run (see {@link ToMatchImageSnapshotOptions} `createMissingBaseline`).
|
|
135
|
+
*/
|
|
136
|
+
createMissingBaseline?: boolean | undefined;
|
|
137
|
+
};
|
|
124
138
|
type SetupVisOptions<GM extends Record<string, any> | unknown = unknown> = {
|
|
125
139
|
auto?: boolean | (<C extends ComparisonMethod, M extends Record<string, any> | unknown = unknown>(options: SnapshotMeta<C> & M & GM) => Promise<boolean> | Promise<void> | boolean | void) | Record<string, boolean | (<C extends ComparisonMethod, M extends Record<string, any> | unknown = unknown>(options: SnapshotMeta<C> & M & GM) => Promise<boolean> | Promise<void> | boolean | void)>;
|
|
140
|
+
/**
|
|
141
|
+
* Default {@link ToMatchImageSnapshotOptions#createMissingBaseline} for auto snapshots.
|
|
142
|
+
*
|
|
143
|
+
* @default false
|
|
144
|
+
*/
|
|
145
|
+
createMissingBaseline?: boolean | undefined;
|
|
126
146
|
};
|
|
127
147
|
//#endregion
|
|
128
148
|
export { Awaitable, ComparisonMethod, FailureThresholdOptions, ImageSnapshotCompareOptions, ImageSnapshotComparisonInfo, ImageSnapshotKeyOptions, ImageSnapshotSubjectOptions, ImageSnapshotTimeoutOptions, MatchImageSnapshotOptions, PageImageSnapshotOptions, PixelComparisonOptions, PixelDiffOptions, SetupVisOptions, SnapshotTestMeta, SsimComparisonOptions, type SsimDiffOptions, ToMatchImageSnapshotOptions, ToMatchPageImageSnapshotOptions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","names":[],"sources":["../../src/shared/types.ts"],"sourcesContent":[],"mappings":";;;;;;KAKY,eAAe,IAAI,YAAY;UAE1B,2BAAA;EAFL;;;;;EAEK,OAAA,CAAA,EAAA,MAAA,GAAA,SAAA;AASjB;AAOY,UAPK,uBAAA,CAOW;EAEhB;AA6BZ;;EAKuB,WAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;AAAD,KApCV,gBAAA,GAoCU,OAAA,GAAA,MAAA;AAKV,KAvCA,uBAAA,GAuCsB;EAQtB;AAEZ;;;;EACG,oBAAA,CAAA,EAAA,OAAA,GAAA,SAAA,GAAA,SAAA;EACuB;;;;AAG1B;AASA;;;;;;;
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../src/shared/types.ts"],"sourcesContent":[],"mappings":";;;;;;KAKY,eAAe,IAAI,YAAY;UAE1B,2BAAA;EAFL;;;;;EAEK,OAAA,CAAA,EAAA,MAAA,GAAA,SAAA;AASjB;AAOY,UAPK,uBAAA,CAOW;EAEhB;AA6BZ;;EAKuB,WAAA,CAAA,EAAA,MAAA,GAAA,SAAA;;AAAD,KApCV,gBAAA,GAoCU,OAAA,GAAA,MAAA;AAKV,KAvCA,uBAAA,GAuCsB;EAQtB;AAEZ;;;;EACG,oBAAA,CAAA,EAAA,OAAA,GAAA,SAAA,GAAA,SAAA;EACuB;;;;AAG1B;AASA;;;;;;;AAmBA;AAIA;;;;;;EAGY,gBAAA,CAAA,EAAgB,MAAA,GAAA,SAAA;CAEJ;AAAb,KA9DC,qBA8DD,CAAA,IAAA,MAAA,CAAA,GAAA;EAAR,gBAAA,EA7DgB,CA6DhB;EAAI;AAIP;;EA+BC,WAAA,CAAA,EA5Fc,OA4Fd,CA5FsB,eA4FtB,CAAA,GAAA,SAAA;CACC;AAA8C,KAxFpC,sBAwFoC,CAAA,IAAA,OAAA,CAAA,GAAA;EAEpC,gBAAA,CAAA,EAzFQ,CAyFR,GAAA,SAAyB;EAAG;;;EAEhB,WAAA,CAAA,EAvFT,gBAuFS,GAAA,SAAA;AAOxB,CAAA;AAAuC,KA3F3B,gBAAA,GAAmB,UA2FQ,CAAA,OA3FU,UA2FV,CAAA,CAAA,CAAA,CAAA;AAGvB,KA5FJ,2BA4FI,CAAA,UA5FkC,gBA4FlC,GAAA,OAAA,CAAA,GAAA,CA5FiE,CA4FjE,SAAA,MAAA,GA3Fb,qBA2Fa,CA3FS,CA2FT,CAAA,GA1Fb,sBA0Fa,CA1FU,CA0FV,CAAA,CAAA,GAzFf,uBAyFe;AAA4B,KAvFhC,2BAAA,GAuFgC;EAClB;;;;;;EAKR,OAAA,CAAA,EAAA,MAAA,GAAA,SAAA;CAA4B;AAClB,KArFhB,2BAqFgB,CAAA,UArFsB,gBAqFtB,GAAA,OAAA,CAAA,GArFoD,2BAqFpD,GApF3B,uBAoF2B,GAnF3B,2BAmF2B,CAnFC,CAmFD,CAAA,GAAA;EAAb;;;;EACe,YAAA,CAAA,EAAA,OAAA,GAAA,SAAA;EAL1B;;;;;;;;;;UA9Da,wBAAA;;;KAIL,0CAA0C,8BAA8B,4BAA4B,KAC/G;KAEW,gBAAA;;KAET,IAAA,IAAQ,aAAa;;;KAIZ,2BAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BR,8BACH,2BACC,wBAAwB;KAEd,yBAAA,GAA4B,8BACvC,mCACA;;;;;;KAOW,2BAA2B;+BAGvB,4BAA4B,kDAC/B,aAAa,KAAK,IAAI,OAC1B,mBAAmB,kCACxB,qCAGc,4BAA4B,kDAC/B,aAAa,KAAK,IAAI,OAC1B,mBAAmB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-plugin-vis",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "Vitest visual testing plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"image-snapshot",
|
|
@@ -21,46 +21,23 @@
|
|
|
21
21
|
"type": "module",
|
|
22
22
|
"imports": {
|
|
23
23
|
"#vitest-plugin-vis": "./src/index.ts",
|
|
24
|
-
"#vitest-plugin-vis/client-api": "./src/client-api.ts",
|
|
25
|
-
"#vitest-plugin-vis/config": "./src/config.ts",
|
|
26
|
-
"#vitest-plugin-vis/setup": "./src/setup.ts"
|
|
24
|
+
"#vitest-plugin-vis/client-api": "./src/exports/client-api.ts",
|
|
25
|
+
"#vitest-plugin-vis/config": "./src/exports/config.ts",
|
|
26
|
+
"#vitest-plugin-vis/setup": "./src/exports/setup.ts",
|
|
27
|
+
"#vitest-plugin-vis/setup-api": "./src/exports/setup-api.ts",
|
|
28
|
+
"#vitest-plugin-vis/testing": "./src/exports/testing.ts",
|
|
29
|
+
"#vitest-plugin-vis/testing/node": "./src/exports/testing/node.ts"
|
|
27
30
|
},
|
|
28
31
|
"exports": {
|
|
29
32
|
".": {
|
|
33
|
+
"source": "./src/index.ts",
|
|
30
34
|
"types": "./dist/index.d.mts",
|
|
31
35
|
"default": "./dist/index.mjs"
|
|
32
36
|
},
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
"./client-api": {
|
|
38
|
-
"types": "./dist/client-api.d.mts",
|
|
39
|
-
"default": "./dist/client-api.mjs"
|
|
40
|
-
},
|
|
41
|
-
"./presets/auto": {
|
|
42
|
-
"types": "./dist/presets/auto.d.mts",
|
|
43
|
-
"default": "./dist/presets/auto.mjs"
|
|
44
|
-
},
|
|
45
|
-
"./presets/manual": {
|
|
46
|
-
"types": "./dist/presets/manual.d.mts",
|
|
47
|
-
"default": "./dist/presets/manual.mjs"
|
|
48
|
-
},
|
|
49
|
-
"./server-utils": {
|
|
50
|
-
"types": "./dist/server-utils.d.mts",
|
|
51
|
-
"default": "./dist/server-utils.mjs"
|
|
52
|
-
},
|
|
53
|
-
"./setup": {
|
|
54
|
-
"types": "./dist/setup.d.mts",
|
|
55
|
-
"default": "./dist/setup.mjs"
|
|
56
|
-
},
|
|
57
|
-
"./setup-api": {
|
|
58
|
-
"types": "./dist/setup-api.d.mts",
|
|
59
|
-
"default": "./dist/setup-api.mjs"
|
|
60
|
-
},
|
|
61
|
-
"./testing": {
|
|
62
|
-
"types": "./dist/testing.d.mts",
|
|
63
|
-
"default": "./dist/testing.mjs"
|
|
37
|
+
"./*": {
|
|
38
|
+
"source": "./src/exports/*.ts",
|
|
39
|
+
"types": "./dist/exports/*.d.mts",
|
|
40
|
+
"default": "./dist/exports/*.mjs"
|
|
64
41
|
},
|
|
65
42
|
"./package.json": "./package.json"
|
|
66
43
|
},
|
|
@@ -109,7 +86,7 @@
|
|
|
109
86
|
"storybook-addon-tag-badges": "^3.1.0",
|
|
110
87
|
"tailwindcss": "^4.1.14",
|
|
111
88
|
"tsdown": "^0.19.0",
|
|
112
|
-
"typescript": "^
|
|
89
|
+
"typescript": "^6.0.0",
|
|
113
90
|
"vite": "^8.0.0",
|
|
114
91
|
"vitest": "^4.1.4",
|
|
115
92
|
"vitest-browser-react": "^2.0.2"
|
package/readme.md
CHANGED
|
@@ -261,6 +261,10 @@ export default defineConfig({
|
|
|
261
261
|
})
|
|
262
262
|
```
|
|
263
263
|
|
|
264
|
+
#### `shortenLongSnapshotPaths` (long absolute paths)
|
|
265
|
+
|
|
266
|
+
Defaults to `false`. When `true`, the plugin keeps legacy snapshot files as `taskId-key.png` and only adjusts the **`snapshotSubpath` segment** when needed: it builds **absolute** paths under `__baselines__` (after `snapshotRootDir` and your `snapshotSubpath`) plus representative snapshot filenames; if those would exceed typical Windows limits (length at least **250**, below classic `MAX_PATH` **260** with margin, or a path component longer than **255**), **directory segments stay as-is** and only the **final path component** (the file name derived from your test/story path) is shortened to `{firstToken}-{hash12}{ext}` — the first token is the substring before the first `.` in the basename (similar in spirit to [tersify](https://github.com/unional/tersify) terse labels). The same resolved subpath is used for **baselines**, **results**, and **diffs**. Your `snapshotRootDir` is not rewritten.
|
|
267
|
+
|
|
264
268
|
#### Multiple browser instances
|
|
265
269
|
|
|
266
270
|
When using multiple browser instances (e.g., different viewports or browsers),
|
|
@@ -451,6 +455,8 @@ setAutoSnapshotOptions({
|
|
|
451
455
|
})
|
|
452
456
|
```
|
|
453
457
|
|
|
458
|
+
`createMissingBaseline` (on the matcher or on `vis.setup`) writes a missing baseline on the first run without `-u`. For auto snapshots, `vis.setup({ createMissingBaseline: true, auto: true })` applies a default; a test can override with `setAutoSnapshotOptions({ createMissingBaseline: false })` or equivalent meta.
|
|
459
|
+
|
|
454
460
|
You can also enable/disable auto snapshot by passing boolean:
|
|
455
461
|
|
|
456
462
|
```ts
|
|
@@ -72,6 +72,26 @@ it('should use custom snapshot key', async ({ expect }) => {
|
|
|
72
72
|
})
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
#### `createMissingBaseline`
|
|
76
|
+
|
|
77
|
+
When `true`, if there is **no baseline image yet**,
|
|
78
|
+
the matcher writes the captured image to the baseline path and the assertion succeeds—without using Vitest's `-u` / `updateSnapshot` mode.
|
|
79
|
+
If a baseline already exists, `createMissingBaseline` does not change comparison behavior.
|
|
80
|
+
|
|
81
|
+
You can also set a default for **auto** snapshots with `vis.setup({ createMissingBaseline: true, auto: ... })`.
|
|
82
|
+
Per-test options from `setAutoSnapshotOptions` / test meta override that default when they set `createMissingBaseline` explicitly.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
it('creates baseline on first run with createMissingBaseline', async ({ expect }) => {
|
|
86
|
+
render(<MyComponent />)
|
|
87
|
+
|
|
88
|
+
await expect(document.body).toMatchImageSnapshot({
|
|
89
|
+
snapshotKey: 'first_run',
|
|
90
|
+
createMissingBaseline: true
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
75
95
|
### Failure Threshold
|
|
76
96
|
|
|
77
97
|
#### `failureThreshold` and `failureThresholdType`
|
|
@@ -258,7 +278,10 @@ it('should demonstrate all options', async ({ expect }) => {
|
|
|
258
278
|
timeout: 45000,
|
|
259
279
|
|
|
260
280
|
// Testing utility
|
|
261
|
-
expectToFail: false
|
|
281
|
+
expectToFail: false,
|
|
282
|
+
|
|
283
|
+
// First-run baseline (optional)
|
|
284
|
+
createMissingBaseline: false
|
|
262
285
|
})
|
|
263
286
|
})
|
|
264
287
|
```
|