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.
Files changed (109) hide show
  1. package/dist/auto_snapshots/_extract_auto_snapshot_options.mjs +1 -1
  2. package/dist/auto_snapshots/_extract_auto_snapshot_options.mjs.map +1 -1
  3. package/dist/client/external/vitest/vitest_suite_proxy.d.mts +0 -1
  4. package/dist/client/snapshot/compare_image_snapshot.logic.mjs +2 -1
  5. package/dist/client/snapshot/compare_image_snapshot.logic.mjs.map +1 -1
  6. package/dist/client/snapshot/compare_image_snapshot.mjs +1 -1
  7. package/dist/client/snapshot/compare_image_snapshot.mjs.map +1 -1
  8. package/dist/client/suite/auto_snapshot_matcher.d.mts +2 -2
  9. package/dist/client/suite/auto_snapshot_matcher.d.mts.map +1 -1
  10. package/dist/client/suite/auto_snapshot_matcher.mjs +5 -3
  11. package/dist/client/suite/auto_snapshot_matcher.mjs.map +1 -1
  12. package/dist/config/types.d.mts +14 -0
  13. package/dist/{client-api.d.mts → exports/client-api.d.mts} +12 -12
  14. package/dist/exports/client-api.mjs +11 -0
  15. package/dist/exports/config.d.mts +5 -0
  16. package/dist/exports/config.mjs +4 -0
  17. package/dist/exports/presets/auto.mjs +9 -0
  18. package/dist/exports/presets/auto.mjs.map +1 -0
  19. package/dist/exports/presets/manual.mjs +9 -0
  20. package/dist/exports/presets/manual.mjs.map +1 -0
  21. package/dist/exports/server-utils.d.mts +5 -0
  22. package/dist/exports/server-utils.mjs +6 -0
  23. package/dist/exports/setup-api.d.mts +4 -0
  24. package/dist/exports/setup-api.mjs +5 -0
  25. package/dist/exports/setup.d.mts +3 -0
  26. package/dist/exports/setup.mjs +4 -0
  27. package/dist/exports/testing/node.d.mts +4 -0
  28. package/dist/exports/testing/node.mjs +5 -0
  29. package/dist/exports/testing.d.mts +2 -0
  30. package/dist/exports/testing.mjs +3 -0
  31. package/dist/server/commands/prepare_image_snapshot_comparison.mjs.map +1 -1
  32. package/dist/server/commands/prepare_page_image_snapshot_comparison.mjs.map +1 -1
  33. package/dist/server/snapshot_path.d.mts +0 -1
  34. package/dist/server/snapshot_path.d.mts.map +1 -1
  35. package/dist/server/snapshot_path_limits.d.mts +28 -0
  36. package/dist/server/snapshot_path_limits.d.mts.map +1 -0
  37. package/dist/server/snapshot_path_limits.mjs +92 -0
  38. package/dist/server/snapshot_path_limits.mjs.map +1 -0
  39. package/dist/server/suite.mjs +8 -2
  40. package/dist/server/suite.mjs.map +1 -1
  41. package/dist/server/testing/stubBrowserCommandContext.mjs +9 -0
  42. package/dist/server/testing/stubBrowserCommandContext.mjs.map +1 -0
  43. package/dist/server/testing/stubSuite.d.mts +17 -0
  44. package/dist/server/testing/stubSuite.d.mts.map +1 -0
  45. package/dist/server/testing/stubSuite.mjs +23 -0
  46. package/dist/server/testing/stubSuite.mjs.map +1 -0
  47. package/dist/server/testing/stubUserConfig.mjs +8 -0
  48. package/dist/server/testing/stubUserConfig.mjs.map +1 -0
  49. package/dist/server/vis_options.d.mts +120 -0
  50. package/dist/server/vis_options.d.mts.map +1 -0
  51. package/dist/server/vis_options.mjs +7 -1
  52. package/dist/server/vis_options.mjs.map +1 -1
  53. package/dist/server/vis_server_context.logic.mjs +37 -10
  54. package/dist/server/vis_server_context.logic.mjs.map +1 -1
  55. package/dist/server/vis_server_context.types.d.mts +32 -1
  56. package/dist/server/vis_server_context.types.d.mts.map +1 -0
  57. package/dist/setup/create_vis.mjs +6 -6
  58. package/dist/setup/create_vis.mjs.map +1 -1
  59. package/dist/shared/types.d.mts +21 -1
  60. package/dist/shared/types.d.mts.map +1 -1
  61. package/package.json +13 -36
  62. package/readme.md +6 -0
  63. package/src/auto_snapshots/_extract_auto_snapshot_options.ts +1 -1
  64. package/src/client/expect/to_match_image_snapshot.mdx +24 -1
  65. package/src/client/page/to_match_image_snapshot.mdx +23 -1
  66. package/src/client/snapshot/compare_image_snapshot.logic.ts +1 -0
  67. package/src/client/snapshot/compare_image_snapshot.ts +2 -2
  68. package/src/client/suite/auto_snapshot_matcher.ts +10 -2
  69. package/src/config/types.ts +14 -0
  70. package/src/exports/client-api.ts +13 -0
  71. package/src/exports/config.ts +3 -0
  72. package/src/exports/server-utils.ts +7 -0
  73. package/src/exports/setup-api.ts +5 -0
  74. package/src/exports/setup.ts +3 -0
  75. package/src/exports/testing/node.ts +4 -0
  76. package/src/exports/testing.ts +1 -0
  77. package/src/server/commands/prepare_image_snapshot_comparison.ts +2 -2
  78. package/src/server/commands/prepare_page_image_snapshot_comparison.ts +2 -1
  79. package/src/server/snapshot_path_limits.ts +135 -0
  80. package/src/server/suite.ts +19 -4
  81. package/src/server/vis_options.ts +10 -1
  82. package/src/server/vis_server_context.logic.ts +47 -17
  83. package/src/setup/create_vis.ts +12 -11
  84. package/src/shared/types.ts +21 -1
  85. package/dist/client-api.mjs +0 -11
  86. package/dist/config.d.mts +0 -5
  87. package/dist/config.mjs +0 -4
  88. package/dist/presets/auto.mjs +0 -9
  89. package/dist/presets/auto.mjs.map +0 -1
  90. package/dist/presets/manual.mjs +0 -9
  91. package/dist/presets/manual.mjs.map +0 -1
  92. package/dist/server-utils.d.mts +0 -4
  93. package/dist/server-utils.mjs +0 -5
  94. package/dist/setup-api.d.mts +0 -4
  95. package/dist/setup-api.mjs +0 -5
  96. package/dist/setup.d.mts +0 -3
  97. package/dist/setup.mjs +0 -4
  98. package/dist/testing.d.mts +0 -2
  99. package/dist/testing.mjs +0 -3
  100. package/src/client-api.ts +0 -13
  101. package/src/config.ts +0 -3
  102. package/src/server-utils.ts +0 -3
  103. package/src/setup-api.ts +0 -5
  104. package/src/setup.ts +0 -3
  105. package/src/testing.ts +0 -1
  106. /package/dist/{presets → exports/presets}/auto.d.mts +0 -0
  107. /package/dist/{presets → exports/presets}/manual.d.mts +0 -0
  108. /package/src/{presets → exports/presets}/auto.ts +0 -0
  109. /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,8 @@
1
+ import { stub } from "type-plus";
2
+
3
+ //#region src/server/testing/stubUserConfig.ts
4
+ const stubUserConfig = stub.build((stub$1) => ({ ...stub$1 }));
5
+
6
+ //#endregion
7
+ export { stubUserConfig };
8
+ //# sourceMappingURL=stubUserConfig.mjs.map
@@ -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
- return visOptions[getProjectName(context) || DEFAULT_PROJECT_NAME] ?? {};
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\treturn visOptions[id] ?? {}\n}\n"],"mappings":";;;;AAMA,MAAM,uBAAuB;AAE7B,MAAM,aAA0D,EAAE;AAElE,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;AAEpE,QAAO,WADI,eAAe,QAAQ,IAAI,yBACb,EAAE"}
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 baselines = await file.glob(join(suiteInfo.projectRoot, suiteInfo.baselineDir, `${suiteInfo.taskId}-*.png`));
13
- const results = await file.glob(join(suiteInfo.projectRoot, suiteInfo.resultDir, `${suiteInfo.taskId}-*.png`));
14
- const diffs = await file.glob(join(suiteInfo.projectRoot, suiteInfo.diffDir, `${suiteInfo.taskId}-*.png`));
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((r$1) => r$1.endsWith(filename));
19
- const diffPath = diffs.find((d) => d.endsWith(filename));
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 = task.count + 1;
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
- return file.existFile(resolve(info.projectRoot, info.baselineDir, context.getSnapshotFilename(browserContext, info, snapshotKey)));
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
- if (typeof visOptions.snapshotKey === "string") return `${info.taskId}-${visOptions.snapshotKey}.png`;
58
- return `${info.taskId}-${info.task.count}.png`;
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":["r"],"sources":["../../src/server/vis_server_context.logic.ts"],"sourcesContent":["import { basename, join, resolve } from 'pathe'\nimport { pick } from 'type-plus'\nimport type { ImageSnapshotKeyOptions } from '../client-api.ts'\nimport type { ImageSnapshotResult } from '../shared/commands.types.ts'\nimport { file } from './externals/file.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 baselines = await file.glob(join(suiteInfo.projectRoot, suiteInfo.baselineDir, `${suiteInfo.taskId}-*.png`))\n\t\t\tconst results = await file.glob(join(suiteInfo.projectRoot, suiteInfo.resultDir, `${suiteInfo.taskId}-*.png`))\n\t\t\tconst diffs = await file.glob(join(suiteInfo.projectRoot, suiteInfo.diffDir, `${suiteInfo.taskId}-*.png`))\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((r) => r.endsWith(filename))\n\t\t\t\t\tconst diffPath = diffs.find((d) => d.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 = task.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\n\t\t\treturn file.existFile(\n\t\t\t\tresolve(info.projectRoot, info.baselineDir, context.getSnapshotFilename(browserContext, info, snapshotKey)),\n\t\t\t)\n\t\t},\n\t\tgetSnapshotFilename(\n\t\t\tbrowserContext: ExtendedBrowserCommandContext,\n\t\t\tinfo: { taskId: string; task: { count: number } },\n\t\t\tsnapshotKey: string | undefined,\n\t\t) {\n\t\t\tif (snapshotKey) return `${info.taskId}-${snapshotKey}.png`\n\t\t\tconst visOptions = getVisOption(browserContext)\n\t\t\tif (typeof visOptions.snapshotKey === 'string') {\n\t\t\t\treturn `${info.taskId}-${visOptions.snapshotKey}.png`\n\t\t\t}\n\t\t\treturn `${info.taskId}-${info.task.count}.png`\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":";;;;;;;AASA,SAAgB,yBAAyB;CACxC,MAAM,UAAU;EACf,MAAM,mBAAmB,gBAA+C,QAAgB;GACvF,MAAM,YAAY,MAAM,QAAQ,aAAa,gBAAgB,OAAO;GACpE,MAAM,YAAY,MAAM,KAAK,KAAK,KAAK,UAAU,aAAa,UAAU,aAAa,GAAG,UAAU,OAAO,QAAQ,CAAC;GAClH,MAAM,UAAU,MAAM,KAAK,KAAK,KAAK,UAAU,aAAa,UAAU,WAAW,GAAG,UAAU,OAAO,QAAQ,CAAC;GAC9G,MAAM,QAAQ,MAAM,KAAK,KAAK,KAAK,UAAU,aAAa,UAAU,SAAS,GAAG,UAAU,OAAO,QAAQ,CAAC;GAE1G,MAAM,IAA2B,EAAE;AACnC,SAAM,QAAQ,IACb,UAAU,IAAI,OAAO,iBAAiB;IACrC,MAAM,WAAW,SAAS,aAAa;IACvC,MAAM,aAAa,QAAQ,MAAM,QAAMA,IAAE,SAAS,SAAS,CAAC;IAC5D,MAAM,WAAW,MAAM,MAAM,MAAM,EAAE,SAAS,SAAS,CAAC;IAExD,MAAM,iBAAiB,MAAM,KAAK,YAAY,aAAa;IAC3D,MAAM,eAAe,MAAM,KAAK,YAAY,WAAW;IACvD,MAAM,aAAa,MAAM,KAAK,YAAY,SAAS;AACnD,MAAE,KAAK;KACN;KACA,UAAU,gBAAgB,SAAS,SAAS;KAC5C,QAAQ,cAAc,SAAS,SAAS;KACxC,MAAM,YAAY,SAAS,SAAS;KACpC,CAAC;KACD,CACF;AACD,UAAO;;EAER,MAAM,gBACL,gBACA,QACA,SACC;GACD,MAAM,YAAY,MAAM,QAAQ,aAAa,gBAAgB,OAAO;GACpE,MAAM,mBAAmB,QAAQ,oBAAoB,gBAAgB,WAAW,SAAS,YAAY;GAErG,MAAM,EAAE,aAAa,WAAW,SAAS,SAAS;AAElD,QAAK,QAAQ,KAAK,QAAQ;GAC1B,MAAM,eAAe,KAAK,aAAa,iBAAiB;GACxD,MAAM,aAAa,KAAK,WAAW,iBAAiB;GACpD,MAAM,WAAW,KAAK,SAAS,iBAAiB;AAEhD,UAAO;IACN,GAAG,KACF,aAAa,eAAe,EAC5B,oBACA,eACA,oBACA,wBACA,UACA;IACD;IACA;IACA;IACA;;EAGF,MAAM,aAAa,gBAA+C,QAAgB;AACjF,WAAQ,MAAM,QAAQ,aAAa,gBAAgB,OAAO,EAAE,KAAK;;EAElE,MAAM,iBACL,gBACA,QACA,aACC;GACD,MAAM,OAAO,MAAM,QAAQ,aAAa,gBAAgB,OAAO;AAE/D,UAAO,KAAK,UACX,QAAQ,KAAK,aAAa,KAAK,aAAa,QAAQ,oBAAoB,gBAAgB,MAAM,YAAY,CAAC,CAC3G;;EAEF,oBACC,gBACA,MACA,aACC;AACD,OAAI,YAAa,QAAO,GAAG,KAAK,OAAO,GAAG,YAAY;GACtD,MAAM,aAAa,aAAa,eAAe;AAC/C,OAAI,OAAO,WAAW,gBAAgB,SACrC,QAAO,GAAG,KAAK,OAAO,GAAG,WAAW,YAAY;AAEjD,UAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK,MAAM;;EAE1C,MAAM,aAAa,gBAA+C,QAAgB;GACjF,MAAM,eAAe,MAAM,SAAS,eAAe;GACnD,MAAM,aAAa,aAAa,eAAe;GAC/C,MAAM,WAAW,eAAe,cAAc,eAAe,UAAU,WAAW;GAClF,MAAM,IAAI,aAAa,QAAQ;GAC/B,MAAM,OAAQ,EAAE,MAAM,UAAU,EAAE,MAAM,WAAW,EAAE,OAAO,GAAG;AAC/D,UAAO;IACN,aAAa,aAAa;IAC1B,SAAS;IACT;IACA,aAAa,EAAE;IACf,WAAW,EAAE;IACb,SAAS,EAAE;IACX;IACA;;EAEF;AACD,QAAO"}
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 "../shared/types.mjs";
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
- if (!options || options.auto === false) beforeAll(matcher.setup);
10
- else beforeAll(async () => {
9
+ const suiteDefaults = options?.createMissingBaseline !== void 0 ? { createMissingBaseline: options.createMissingBaseline } : void 0;
10
+ beforeAll(async () => {
11
11
  await matcher.setup();
12
- setAutoSnapshotOptions(true);
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\tif (!options || options.auto === false) {\n\t\t\t\tbeforeAll(matcher.setup)\n\t\t\t} else {\n\t\t\t\tbeforeAll(async () => {\n\t\t\t\t\tawait matcher.setup()\n\t\t\t\t\tsetAutoSnapshotOptions(true)\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (typeof options?.auto === 'function') {\n\t\t\t\tafterEach(matcher.createMatcher({ auto: options.auto }))\n\t\t\t} else if (typeof options?.auto === 'object') {\n\t\t\t\tafterEach(matcher.createMatcher(options.auto))\n\t\t\t} else {\n\t\t\t\tafterEach(matcher.createMatcher({ async auto() {} }))\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;AAsBrD,QApBuC,EACtC,MAAM,SAAS;AACd,MAAI,CAAC,WAAW,QAAQ,SAAS,MAChC,WAAU,QAAQ,MAAM;MAExB,WAAU,YAAY;AACrB,SAAM,QAAQ,OAAO;AACrB,0BAAuB,KAAK;IAC3B;AAGH,MAAI,OAAO,SAAS,SAAS,WAC5B,WAAU,QAAQ,cAAc,EAAE,MAAM,QAAQ,MAAM,CAAC,CAAC;WAC9C,OAAO,SAAS,SAAS,SACnC,WAAU,QAAQ,cAAc,QAAQ,KAAK,CAAC;MAE9C,WAAU,QAAQ,cAAc,EAAE,MAAM,OAAO,IAAI,CAAC,CAAC;IAGvD"}
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"}
@@ -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;;;;;;;AAUA;AAIA;;;;;;EAGY,gBAAA,CAAA,EAAgB,MAAA,GAAA,SAAA;CAEJ;AAAb,KArDC,qBAqDD,CAAA,IAAA,MAAA,CAAA,GAAA;EAAR,gBAAA,EApDgB,CAoDhB;EAAI;AAIP;;EA+BC,WAAA,CAAA,EAnFc,OAmFd,CAnFsB,eAmFtB,CAAA,GAAA,SAAA;CACC;AAA8C,KA/EpC,sBA+EoC,CAAA,IAAA,OAAA,CAAA,GAAA;EAEpC,gBAAA,CAAA,EAhFQ,CAgFR,GAAA,SAAyB;EAAG;;;EAEhB,WAAA,CAAA,EA9ET,gBA8ES,GAAA,SAAA;AAExB,CAAA;AAAuC,KA7E3B,gBAAA,GAAmB,UA6EQ,CAAA,OA7EU,UA6EV,CAAA,CAAA,CAAA,CAAA;AAGvB,KA9EJ,2BA8EI,CAAA,UA9EkC,gBA8ElC,GAAA,OAAA,CAAA,GAAA,CA9EiE,CA8EjE,SAAA,MAAA,GA7Eb,qBA6Ea,CA7ES,CA6ET,CAAA,GA5Eb,sBA4Ea,CA5EU,CA4EV,CAAA,CAAA,GA3Ef,uBA2Ee;AAA4B,KAzEhC,2BAAA,GAyEgC;EAClB;;;;;;EAKR,OAAA,CAAA,EAAA,MAAA,GAAA,SAAA;CAA4B;AAClB,KAvEhB,2BAuEgB,CAAA,UAvEsB,gBAuEtB,GAAA,OAAA,CAAA,GAvEoD,2BAuEpD,GAtE3B,uBAsE2B,GArE3B,2BAqE2B,CArEC,CAqED,CAAA,GAAA;EAAb;;;;EACe,YAAA,CAAA,EAAA,OAAA,GAAA,SAAA;CAL1B;AAAM,UAzDO,wBAAA,CAyDP;;;KArDE,0CAA0C,8BAA8B,4BAA4B,KAC/G;KAEW,gBAAA;;KAET,IAAA,IAAQ,aAAa;;;KAIZ,2BAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BR,8BACH,2BACC,wBAAwB;KAEd,yBAAA,GAA4B,8BACvC,mCACA;KAEW,2BAA2B;+BAGvB,4BAA4B,kDAC/B,aAAa,KAAK,IAAI,OAC1B,mBAAmB,kCACxB,qCAGc,4BAA4B,kDAC/B,aAAa,KAAK,IAAI,OAC1B,mBAAmB"}
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.0.0",
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
- "./config": {
34
- "types": "./dist/config.d.mts",
35
- "default": "./dist/config.mjs"
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": "^5.9.3",
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
@@ -1,4 +1,4 @@
1
- import { NAME } from '../client-api.ts'
1
+ import { NAME } from '../exports/client-api.ts'
2
2
  import type { MetaTask } from './auto_snapshot_options.ts'
3
3
  import type { SnapshotMeta } from './snapshot_meta.ts'
4
4
 
@@ -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
  ```