vitest-plugin-vis 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/client/match_image_snapshot.d.ts.map +1 -1
- package/esm/client/match_image_snapshot.js +4 -2
- package/esm/config/vis.d.ts +1 -1
- package/esm/presets/auto.d.ts +1 -1
- package/esm/presets/auto.d.ts.map +1 -1
- package/esm/presets/auto.js +0 -1
- package/esm/presets/manual.d.ts +1 -1
- package/esm/presets/manual.d.ts.map +1 -1
- package/esm/presets/manual.js +0 -1
- package/esm/server/commands/_assertions.d.ts +5 -0
- package/esm/server/commands/_assertions.d.ts.map +1 -0
- package/esm/server/commands/_assertions.js +11 -0
- package/esm/server/commands/extend.d.ts +1 -1
- package/esm/server/commands/has_image_snapshot.d.ts.map +1 -1
- package/esm/server/commands/has_image_snapshot.js +2 -3
- package/esm/server/commands/image_snapshot_next_index.d.ts.map +1 -1
- package/esm/server/commands/image_snapshot_next_index.js +2 -3
- package/esm/server/commands/match_image_snapshot.d.ts.map +1 -1
- package/esm/server/commands/match_image_snapshot.js +6 -5
- package/esm/server/commands/prepare_image_snapshot_comparison.d.ts.map +1 -1
- package/esm/server/commands/prepare_image_snapshot_comparison.js +2 -3
- package/esm/server/commands/setup_vis_suite.d.ts.map +1 -1
- package/esm/server/commands/setup_vis_suite.js +2 -0
- package/esm/server/commands/write_image_snapshot.d.ts +8 -2
- package/esm/server/commands/write_image_snapshot.d.ts.map +1 -1
- package/esm/server/commands/write_image_snapshot.js +6 -7
- package/esm/server/vis_context.d.ts.map +1 -1
- package/esm/server/vis_context.logic.d.ts +1 -1
- package/esm/server/vis_context.logic.d.ts.map +1 -1
- package/esm/shared/compare_image.d.ts +6 -0
- package/esm/shared/compare_image.d.ts.map +1 -0
- package/esm/shared/compare_image.js +10 -0
- package/esm/testing/stubBrowserCommandContext.d.ts +3 -0
- package/esm/testing/stubBrowserCommandContext.d.ts.map +1 -0
- package/esm/testing/stubBrowserCommandContext.js +2 -0
- package/esm/testing.d.ts +1 -0
- package/esm/testing.d.ts.map +1 -1
- package/esm/testing.js +1 -0
- package/package.json +2 -1
- package/readme.md +20 -2
- package/src/client/match_image_snapshot.ts +11 -2
- package/src/presets/auto.ts +0 -1
- package/src/presets/manual.ts +0 -1
- package/src/server/commands/_assertions.ts +18 -0
- package/src/server/commands/has_image_snapshot.ts +2 -3
- package/src/server/commands/image_snapshot_next_index.ts +2 -3
- package/src/server/commands/match_image_snapshot.ts +13 -6
- package/src/server/commands/prepare_image_snapshot_comparison.ts +2 -3
- package/src/server/commands/setup_vis_suite.ts +3 -0
- package/src/server/commands/write_image_snapshot.ts +17 -11
- package/src/server/vis_context.logic.ts +2 -2
- package/src/shared/compare_image.ts +20 -0
- package/src/testing/stubBrowserCommandContext.ts +4 -0
- package/src/testing.ts +1 -0
- package/esm/client/compare_image.d.ts +0 -7
- package/esm/client/compare_image.d.ts.map +0 -1
- package/esm/client/compare_image.js +0 -13
- package/esm/server/commands/is_ci.d.ts +0 -2
- package/esm/server/commands/is_ci.d.ts.map +0 -1
- package/esm/server/commands/is_ci.js +0 -6
- package/esm/server/compare_image.d.ts +0 -8
- package/esm/server/compare_image.d.ts.map +0 -1
- package/esm/server/compare_image.js +0 -16
- package/src/client/compare_image.ts +0 -21
- package/src/server/commands/is_ci.ts +0 -7
- package/src/server/compare_image.ts +0 -34
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match_image_snapshot.d.ts","sourceRoot":"","sources":["../../src/client/match_image_snapshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAIlC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAA;AAO5F,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,2BAA2B,
|
|
1
|
+
{"version":3,"file":"match_image_snapshot.d.ts","sourceRoot":"","sources":["../../src/client/match_image_snapshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAIlC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAA;AAO5F,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,2BAA2B,iBAgDvG;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,GAAG,OAOrD"}
|
|
@@ -2,8 +2,8 @@ import { commands } from '@vitest/browser/context';
|
|
|
2
2
|
import dedent from 'dedent';
|
|
3
3
|
import { resolve } from 'pathe';
|
|
4
4
|
import { isBase64String } from "../shared/base64.js";
|
|
5
|
+
import { compareImage } from "../shared/compare_image.js";
|
|
5
6
|
import { alignImagesToSameSize } from "./align_images.js";
|
|
6
|
-
import { compareImage } from "./compare_image.js";
|
|
7
7
|
import { toDataURL, toImageData } from "./image_data.js";
|
|
8
8
|
import { prettifyOptions } from "./match_image_snapshot.logic.js";
|
|
9
9
|
import { convertElementToCssSelector } from "./selector.js";
|
|
@@ -17,7 +17,9 @@ export async function matchImageSnapshot(test, subject, options) {
|
|
|
17
17
|
const baselineImage = await toImageData(info.baseline);
|
|
18
18
|
const resultImage = await toImageData(info.result);
|
|
19
19
|
const [baselineAlignedImage, resultAlignedImage] = alignImagesToSameSize(baselineImage, resultImage);
|
|
20
|
-
const {
|
|
20
|
+
const { width, height } = baselineAlignedImage;
|
|
21
|
+
const diffImage = new ImageData(width, height);
|
|
22
|
+
const { pass, diffAmount } = compareImage(baselineAlignedImage.data, resultAlignedImage.data, diffImage.data, width, height, options);
|
|
21
23
|
if (pass)
|
|
22
24
|
return;
|
|
23
25
|
if (server.config.snapshotOptions.updateSnapshot === 'all') {
|
package/esm/config/vis.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export declare function vis(options?: VisOptions): {
|
|
|
17
17
|
hasImageSnapshot: import("vitest/node").BrowserCommand<[taskId: string, snapshotId?: string | undefined]>;
|
|
18
18
|
matchImageSnapshot: import("vitest/node").BrowserCommand<[taskId: string, subject: string, options?: import("../commands.ts").MatchImageSnapshotOptions | undefined]>;
|
|
19
19
|
prepareImageSnapshotComparison: import("vitest/node").BrowserCommand<[taskId: string, snapshotId: string, options?: import("../commands.ts").MatchImageSnapshotOptions | undefined]>;
|
|
20
|
-
writeImageSnapshot: import("vitest/node").BrowserCommand<[
|
|
20
|
+
writeImageSnapshot: import("vitest/node").BrowserCommand<[relativeFilePath: string, imageBase64: string]>;
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
setupFiles: string[] | undefined;
|
package/esm/presets/auto.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=auto.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto.d.ts","sourceRoot":"","sources":["../../src/presets/auto.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auto.d.ts","sourceRoot":"","sources":["../../src/presets/auto.ts"],"names":[],"mappings":""}
|
package/esm/presets/auto.js
CHANGED
package/esm/presets/manual.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=manual.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manual.d.ts","sourceRoot":"","sources":["../../src/presets/manual.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manual.d.ts","sourceRoot":"","sources":["../../src/presets/manual.ts"],"names":[],"mappings":""}
|
package/esm/presets/manual.js
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RequiredPick } from 'type-plus';
|
|
2
|
+
import type { BrowserCommandContext } from 'vitest/node';
|
|
3
|
+
export declare function assertTestPathDefined(context: BrowserCommandContext, commandName: string): asserts context is RequiredPick<BrowserCommandContext, 'testPath'>;
|
|
4
|
+
export declare function assertIsRelativePath(relativeFilePath: string, propName: string): void;
|
|
5
|
+
//# sourceMappingURL=_assertions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_assertions.d.ts","sourceRoot":"","sources":["../../../src/server/commands/_assertions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAExD,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,qBAAqB,EAC9B,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,IAAI,YAAY,CAAC,qBAAqB,EAAE,UAAU,CAAC,CAIpE;AAED,wBAAgB,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAI9E"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isAbsolute } from 'pathe';
|
|
2
|
+
export function assertTestPathDefined(context, commandName) {
|
|
3
|
+
if (!context.testPath) {
|
|
4
|
+
throw new Error(`'commands.${commandName}' requires testPath to be defined`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export function assertIsRelativePath(relativeFilePath, propName) {
|
|
8
|
+
if (isAbsolute(relativeFilePath)) {
|
|
9
|
+
throw new Error(`'${propName}' must be a relative path`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -14,6 +14,6 @@ export declare const commands: {
|
|
|
14
14
|
hasImageSnapshot: import("vitest/node").BrowserCommand<[taskId: string, snapshotId?: string | undefined]>;
|
|
15
15
|
matchImageSnapshot: import("vitest/node").BrowserCommand<[taskId: string, subject: string, options?: import("./match_image_snapshot.ts").MatchImageSnapshotOptions | undefined]>;
|
|
16
16
|
prepareImageSnapshotComparison: import("vitest/node").BrowserCommand<[taskId: string, snapshotId: string, options?: import("./match_image_snapshot.ts").MatchImageSnapshotOptions | undefined]>;
|
|
17
|
-
writeImageSnapshot: import("vitest/node").BrowserCommand<[
|
|
17
|
+
writeImageSnapshot: import("vitest/node").BrowserCommand<[relativeFilePath: string, imageBase64: string]>;
|
|
18
18
|
};
|
|
19
19
|
//# sourceMappingURL=extend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"has_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/has_image_snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"has_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/has_image_snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,MAAM,WAAW,uBAAuB;IACvC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACnF;AAED,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,CAQ9F,CAAA"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { visContext } from "../vis_context.js";
|
|
2
|
+
import { assertTestPathDefined } from "./_assertions.js";
|
|
2
3
|
export const hasImageSnapshot = async (context, taskId, snapshotId) => {
|
|
3
|
-
|
|
4
|
-
throw new Error('Cannot take snapshot without testPath');
|
|
5
|
-
}
|
|
4
|
+
assertTestPathDefined(context, 'hasImageSnapshot');
|
|
6
5
|
return visContext.hasImageSnapshot(context.testPath, taskId, snapshotId);
|
|
7
6
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image_snapshot_next_index.d.ts","sourceRoot":"","sources":["../../../src/server/commands/image_snapshot_next_index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"image_snapshot_next_index.d.ts","sourceRoot":"","sources":["../../../src/server/commands/image_snapshot_next_index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,MAAM,WAAW,6BAA6B;IAC7C;;OAEG;IACH,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACvD;AAED,eAAO,MAAM,sBAAsB,EAAE,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAInE,CAAA"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { visContext } from "../vis_context.js";
|
|
2
|
+
import { assertTestPathDefined } from "./_assertions.js";
|
|
2
3
|
export const imageSnapshotNextIndex = async (context, taskId) => {
|
|
3
|
-
|
|
4
|
-
throw new Error('Cannot take snapshot without testPath');
|
|
5
|
-
}
|
|
4
|
+
assertTestPathDefined(context, 'imageSnapshotNextIndex');
|
|
6
5
|
return visContext.getTaskCount(context.testPath, taskId);
|
|
7
6
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/match_image_snapshot.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"match_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/match_image_snapshot.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAKjD,OAAO,KAAK,EACX,2BAA2B,EAC3B,sBAAsB,EACtB,2BAA2B,EAC3B,MAAM,uBAAuB,CAAA;AAM9B,MAAM,WAAW,yBAAyB;IACzC,kBAAkB,EAAE,CACnB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,yBAAyB,GAAG,SAAS,KAC3C,OAAO,CAAC,IAAI,CAAC,CAAA;CAClB;AAED,MAAM,WAAW,yBAChB,SAAQ,2BAA2B,EAClC,sBAAsB,EACtB,2BAA2B;IAC5B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAC9C;IAAC,MAAM,EAAE,MAAM;IAAE,OAAO,EAAE,MAAM;IAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,SAAS;CAAC,CAuElF,CAAA"}
|
|
@@ -3,16 +3,15 @@ import ci from 'is-ci';
|
|
|
3
3
|
import { resolve } from 'pathe';
|
|
4
4
|
import { PNG } from 'pngjs';
|
|
5
5
|
import { isBase64String } from "../../shared/base64.js";
|
|
6
|
+
import { compareImage } from "../../shared/compare_image.js";
|
|
6
7
|
import { getMaxSize } from "../../shared/get_max_size.js";
|
|
7
8
|
import { isSameSize } from "../../shared/is_same_size.js";
|
|
8
|
-
import { compareImage } from "../compare_image.js";
|
|
9
9
|
import { file } from "../file.js";
|
|
10
10
|
import { takeSnapshot, takeSnapshotByBrowser, writeSnapshot, writeSnapshotBuffer } from "../snapshot.js";
|
|
11
11
|
import { visContext } from "../vis_context.js";
|
|
12
|
+
import { assertTestPathDefined } from "./_assertions.js";
|
|
12
13
|
export const matchImageSnapshot = async (context, taskId, subject, options) => {
|
|
13
|
-
|
|
14
|
-
throw new Error('Cannot match snapshot without testPath');
|
|
15
|
-
}
|
|
14
|
+
assertTestPathDefined(context, 'matchImageSnapshot');
|
|
16
15
|
// vitest:browser passes in `null` when not defined
|
|
17
16
|
if (!options)
|
|
18
17
|
options = {};
|
|
@@ -32,7 +31,9 @@ export const matchImageSnapshot = async (context, taskId, subject, options) => {
|
|
|
32
31
|
const baselineImage = PNG.sync.read(baselineBuffer, { skipRescale: true, checkCRC: false });
|
|
33
32
|
const resultImage = PNG.sync.read(resultBuffer, { skipRescale: true, checkCRC: false });
|
|
34
33
|
const [baselineAlignedImage, resultAlignedImage] = alignImageSizes(baselineImage, resultImage);
|
|
35
|
-
const {
|
|
34
|
+
const { width, height } = baselineAlignedImage;
|
|
35
|
+
const diffImage = new PNG({ width, height });
|
|
36
|
+
const { pass, diffAmount } = compareImage(baselineAlignedImage.data, resultAlignedImage.data, diffImage.data, width, height, options);
|
|
36
37
|
if (pass) {
|
|
37
38
|
if (sizeNotChanged(baselineImage, baselineAlignedImage) && sizeNotChanged(resultImage, resultAlignedImage)) {
|
|
38
39
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare_image_snapshot_comparison.d.ts","sourceRoot":"","sources":["../../../src/server/commands/prepare_image_snapshot_comparison.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"prepare_image_snapshot_comparison.d.ts","sourceRoot":"","sources":["../../../src/server/commands/prepare_image_snapshot_comparison.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAMjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAA;AAE1E,KAAK,2BAA2B,GAAG;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,WAAW,qCAAqC;IACrD,8BAA8B,EAAE,CAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,yBAAyB,GAAG,SAAS,KAC3C,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAAA;CACrD;AAED,eAAO,MAAM,8BAA8B,EAAE,cAAc,CAC1D;IAAC,MAAM,EAAE,MAAM;IAAE,UAAU,EAAE,MAAM;IAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,SAAS;CAAC,CA0BrF,CAAA"}
|
|
@@ -3,10 +3,9 @@ import { isBase64String } from "../../shared/base64.js";
|
|
|
3
3
|
import { file } from "../file.js";
|
|
4
4
|
import { takeSnapshot, takeSnapshotByBrowser, writeSnapshot } from "../snapshot.js";
|
|
5
5
|
import { visContext } from "../vis_context.js";
|
|
6
|
+
import { assertTestPathDefined } from "./_assertions.js";
|
|
6
7
|
export const prepareImageSnapshotComparison = async (context, taskId, subject, options) => {
|
|
7
|
-
|
|
8
|
-
throw new Error('Cannot match snapshot without testPath');
|
|
9
|
-
}
|
|
8
|
+
assertTestPathDefined(context, 'prepareImageSnapshotComparison');
|
|
10
9
|
// vitest:browser passes in `null` when not defined
|
|
11
10
|
if (!options)
|
|
12
11
|
options = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup_vis_suite.d.ts","sourceRoot":"","sources":["../../../src/server/commands/setup_vis_suite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"setup_vis_suite.d.ts","sourceRoot":"","sources":["../../../src/server/commands/setup_vis_suite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,MAAM,WAAW,oBAAoB;IACpC;;;;;;OAMG;IACH,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,cAAc,CAAC,EAAE,CAI5C,CAAA"}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { BrowserCommand } from 'vitest/node';
|
|
2
2
|
export interface WriteImageSnapshotCommand {
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Writes the image snapshot to the file system.
|
|
5
|
+
* @param relativeFilePath The file path to write the image snapshot to.
|
|
6
|
+
* It is relative to the project root.
|
|
7
|
+
* @param imageBase64 The base64 encoded image.
|
|
8
|
+
*/
|
|
9
|
+
writeImageSnapshot(relativeFilePath: string, imageBase64: string): Promise<void>;
|
|
4
10
|
}
|
|
5
|
-
export declare const writeImageSnapshot: BrowserCommand<[
|
|
11
|
+
export declare const writeImageSnapshot: BrowserCommand<[relativeFilePath: string, imageBase64: string]>;
|
|
6
12
|
//# sourceMappingURL=write_image_snapshot.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/write_image_snapshot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"write_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/write_image_snapshot.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,MAAM,WAAW,yBAAyB;IACzC;;;;;OAKG;IACH,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChF;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,CAAC,gBAAgB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAS9F,CAAA"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { mkdirp } from 'mkdirp';
|
|
2
|
-
import { dirname } from 'pathe';
|
|
2
|
+
import { dirname, isAbsolute } from 'pathe';
|
|
3
3
|
import { file } from "../file.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
await
|
|
9
|
-
await file.writeFile(filePath, base64, { encoding: 'base64' });
|
|
4
|
+
import { assertIsRelativePath } from "./_assertions.js";
|
|
5
|
+
export const writeImageSnapshot = async (_, relativeFilePath, imageBase64) => {
|
|
6
|
+
assertIsRelativePath(relativeFilePath, 'relativeFilePath');
|
|
7
|
+
await mkdirp(dirname(relativeFilePath));
|
|
8
|
+
await file.writeFile(relativeFilePath, imageBase64, { encoding: 'base64' });
|
|
10
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vis_context.d.ts","sourceRoot":"","sources":["../../src/server/vis_context.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU;;;;;;;
|
|
1
|
+
{"version":3,"file":"vis_context.d.ts","sourceRoot":"","sources":["../../src/server/vis_context.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU;;;;;;;sBAC+hD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAD3gD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vis_context.logic.d.ts","sourceRoot":"","sources":["../../src/server/vis_context.logic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAKpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAEtD,MAAM,MAAM,4BAA4B,GAAG;IAC1C,OAAO,EAAE;QACR,MAAM,EAAE;YACP,IAAI,EAAE,MAAM,CAAA;YACZ,eAAe,EAAE;gBAChB,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;aACtC,CAAA;YACD,WAAW,EAAE,MAAM,CAAA;YACnB,WAAW,EAAE,MAAM,CAAA;SACnB,CAAA;KACD,CAAA;IACD,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"vis_context.logic.d.ts","sourceRoot":"","sources":["../../src/server/vis_context.logic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAKpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAEtD,MAAM,MAAM,4BAA4B,GAAG;IAC1C,OAAO,EAAE;QACR,MAAM,EAAE;YACP,IAAI,EAAE,MAAM,CAAA;YACZ,eAAe,EAAE;gBAChB,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;aACtC,CAAA;YACD,WAAW,EAAE,MAAM,CAAA;YACnB,WAAW,EAAE,MAAM,CAAA;SACnB,CAAA;KACD,CAAA;IACD,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,gBAAgB;yBAMV,UAAU;;;;IAY9B;;;;OAIG;wBACuB,4BAA4B;8BAY5B,MAAM,QAAQ,MAAM,YAAY;QAAE,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE;;;;;2BAiB1E,MAAM,UAAU,MAAM;+BAGlB,MAAM,UAAU,MAAM,kBAAkB,MAAM,GAAG,SAAS;8BAI3D;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,kBAAkB,MAAM,GAAG,SAAS;2BAMlF,MAAM,UAAU,MAAM;;;;;;;;;;EAe9C;AAuBD,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,UAEhF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;;;;;;;;EAWjF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ImageSnapshotCompareOptions } from './types.ts';
|
|
2
|
+
export declare function compareImage(img1: Uint8ClampedArray | Buffer, img2: Uint8ClampedArray | Buffer, output: Uint8ClampedArray | Buffer, width: number, height: number, { failureThreshold, failureThresholdType, diffOptions }?: ImageSnapshotCompareOptions): {
|
|
3
|
+
pass: boolean;
|
|
4
|
+
diffAmount: number;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=compare_image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare_image.d.ts","sourceRoot":"","sources":["../../src/shared/compare_image.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AAE7D,wBAAgB,YAAY,CAC3B,IAAI,EAAE,iBAAiB,GAAG,MAAM,EAChC,IAAI,EAAE,iBAAiB,GAAG,MAAM,EAChC,MAAM,EAAE,iBAAiB,GAAG,MAAM,EAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,EAAE,gBAAoB,EAAE,oBAA8B,EAAE,WAAW,EAAE,GAAE,2BAAgC;;;EASvG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import pixelmatch from 'pixelmatch';
|
|
2
|
+
import { convertThresholdUnit } from "./convert_threshold_unit.js";
|
|
3
|
+
export function compareImage(img1, img2, output, width, height, { failureThreshold = 0, failureThresholdType = 'pixel', diffOptions } = {}) {
|
|
4
|
+
const pixelDiff = pixelmatch(img1, img2, output, width, height, diffOptions);
|
|
5
|
+
const diffAmount = convertThresholdUnit({ failureThresholdType, width, height }, pixelDiff);
|
|
6
|
+
return {
|
|
7
|
+
pass: diffAmount <= failureThreshold,
|
|
8
|
+
diffAmount,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stubBrowserCommandContext.d.ts","sourceRoot":"","sources":["../../src/testing/stubBrowserCommandContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAExD,eAAO,MAAM,yBAAyB,2GAAwC,CAAA"}
|
package/esm/testing.d.ts
CHANGED
package/esm/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,wCAAwC,CAAA"}
|
package/esm/testing.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-plugin-vis",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Vitest visual testing plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"image-snapshot",
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
"@vitest/coverage-v8": "^2.1.8",
|
|
81
81
|
"@vitest/expect": "^2.1.8",
|
|
82
82
|
"cross-env": "^7.0.3",
|
|
83
|
+
"never-fail": "^1.1.4",
|
|
83
84
|
"npm-run-all2": "^7.0.2",
|
|
84
85
|
"playwright": "^1.49.0",
|
|
85
86
|
"react": "^19.0.0",
|
package/readme.md
CHANGED
|
@@ -103,7 +103,7 @@ vis.presets.auto()
|
|
|
103
103
|
vis.presets.manual()
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
// or capture image snapshot for all
|
|
106
|
+
// or capture image snapshot for all rendering tests
|
|
107
107
|
// for multiple themes (light and dark in this example)
|
|
108
108
|
vis.presets.theme({
|
|
109
109
|
light() { document.body.classList.remove('dark') },
|
|
@@ -115,7 +115,8 @@ vis.presets.theme({
|
|
|
115
115
|
|
|
116
116
|
### Auto Snapshot
|
|
117
117
|
|
|
118
|
-
By default, the plugin will use the `auto` preset,
|
|
118
|
+
By default, the plugin will use the `auto` preset,
|
|
119
|
+
which will take a snapshot at the end of each test.
|
|
119
120
|
|
|
120
121
|
You can control how the auto snapshot is taken using the `setAutoSnapshotOptions` function:
|
|
121
122
|
|
|
@@ -153,6 +154,23 @@ describe('nested scope', () => {
|
|
|
153
154
|
})
|
|
154
155
|
```
|
|
155
156
|
|
|
157
|
+
The options are similar to `expect(...).toMatchImageSnapshot(options)`:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
// enable/disable auto snapshot
|
|
161
|
+
setAutoSnapshotOptions(true /* or false */)
|
|
162
|
+
|
|
163
|
+
// detailed options
|
|
164
|
+
setAutoSnapshotOptions({
|
|
165
|
+
enable: true,
|
|
166
|
+
customizeSnapshotId: (id, index) => `${id}-custom-${index}`,
|
|
167
|
+
diffOptions: { threshold: 0.01 } // pixelmatch options,
|
|
168
|
+
failureThreshold: 0.01,
|
|
169
|
+
failureThresholdType: 'percent',
|
|
170
|
+
timeout: 15000
|
|
171
|
+
})
|
|
172
|
+
```
|
|
173
|
+
|
|
156
174
|
### Manual Snapshot
|
|
157
175
|
|
|
158
176
|
You can also set the preset to `manual` and compare snapshots manually:
|
|
@@ -3,8 +3,8 @@ import dedent from 'dedent'
|
|
|
3
3
|
import { resolve } from 'pathe'
|
|
4
4
|
import type { Task } from 'vitest'
|
|
5
5
|
import { isBase64String } from '../shared/base64.ts'
|
|
6
|
+
import { compareImage } from '../shared/compare_image.ts'
|
|
6
7
|
import { alignImagesToSameSize } from './align_images.ts'
|
|
7
|
-
import { compareImage } from './compare_image.ts'
|
|
8
8
|
import type { ToMatchImageSnapshotOptions } from './expect/to_match_image_snapshot.types.ts'
|
|
9
9
|
import { toDataURL, toImageData } from './image_data.ts'
|
|
10
10
|
import { prettifyOptions } from './match_image_snapshot.logic.ts'
|
|
@@ -25,7 +25,16 @@ export async function matchImageSnapshot(test: Task, subject: any, options?: ToM
|
|
|
25
25
|
const baselineImage = await toImageData(info.baseline)
|
|
26
26
|
const resultImage = await toImageData(info.result)
|
|
27
27
|
const [baselineAlignedImage, resultAlignedImage] = alignImagesToSameSize(baselineImage, resultImage)
|
|
28
|
-
const {
|
|
28
|
+
const { width, height } = baselineAlignedImage
|
|
29
|
+
const diffImage = new ImageData(width, height)
|
|
30
|
+
const { pass, diffAmount } = compareImage(
|
|
31
|
+
baselineAlignedImage.data,
|
|
32
|
+
resultAlignedImage.data,
|
|
33
|
+
diffImage.data,
|
|
34
|
+
width,
|
|
35
|
+
height,
|
|
36
|
+
options,
|
|
37
|
+
)
|
|
29
38
|
if (pass) return
|
|
30
39
|
if (server.config.snapshotOptions.updateSnapshot === 'all') {
|
|
31
40
|
await writeSnapshot(info.baselinePath, resultImage)
|
package/src/presets/auto.ts
CHANGED
package/src/presets/manual.ts
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isAbsolute } from 'pathe'
|
|
2
|
+
import type { RequiredPick } from 'type-plus'
|
|
3
|
+
import type { BrowserCommandContext } from 'vitest/node'
|
|
4
|
+
|
|
5
|
+
export function assertTestPathDefined(
|
|
6
|
+
context: BrowserCommandContext,
|
|
7
|
+
commandName: string,
|
|
8
|
+
): asserts context is RequiredPick<BrowserCommandContext, 'testPath'> {
|
|
9
|
+
if (!context.testPath) {
|
|
10
|
+
throw new Error(`'commands.${commandName}' requires testPath to be defined`)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function assertIsRelativePath(relativeFilePath: string, propName: string) {
|
|
15
|
+
if (isAbsolute(relativeFilePath)) {
|
|
16
|
+
throw new Error(`'${propName}' must be a relative path`)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BrowserCommand } from 'vitest/node'
|
|
2
2
|
import { visContext } from '../vis_context.ts'
|
|
3
|
+
import { assertTestPathDefined } from './_assertions.ts'
|
|
3
4
|
|
|
4
5
|
export interface HasImageSnapshotCommand {
|
|
5
6
|
hasImageSnapshot(taskId: string, snapshotId?: string | undefined): Promise<boolean>
|
|
@@ -10,9 +11,7 @@ export const hasImageSnapshot: BrowserCommand<[taskId: string, snapshotId?: stri
|
|
|
10
11
|
taskId,
|
|
11
12
|
snapshotId,
|
|
12
13
|
) => {
|
|
13
|
-
|
|
14
|
-
throw new Error('Cannot take snapshot without testPath')
|
|
15
|
-
}
|
|
14
|
+
assertTestPathDefined(context, 'hasImageSnapshot')
|
|
16
15
|
|
|
17
16
|
return visContext.hasImageSnapshot(context.testPath, taskId, snapshotId)
|
|
18
17
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BrowserCommand } from 'vitest/node'
|
|
2
2
|
import { visContext } from '../vis_context.ts'
|
|
3
|
+
import { assertTestPathDefined } from './_assertions.ts'
|
|
3
4
|
|
|
4
5
|
export interface ImageSnapshotNextIndexCommand {
|
|
5
6
|
/**
|
|
@@ -9,9 +10,7 @@ export interface ImageSnapshotNextIndexCommand {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export const imageSnapshotNextIndex: BrowserCommand<[taskId: string]> = async (context, taskId) => {
|
|
12
|
-
|
|
13
|
-
throw new Error('Cannot take snapshot without testPath')
|
|
14
|
-
}
|
|
13
|
+
assertTestPathDefined(context, 'imageSnapshotNextIndex')
|
|
15
14
|
|
|
16
15
|
return visContext.getTaskCount(context.testPath, taskId)
|
|
17
16
|
}
|
|
@@ -4,6 +4,7 @@ import { resolve } from 'pathe'
|
|
|
4
4
|
import { PNG } from 'pngjs'
|
|
5
5
|
import type { BrowserCommand } from 'vitest/node'
|
|
6
6
|
import { isBase64String } from '../../shared/base64.ts'
|
|
7
|
+
import { compareImage } from '../../shared/compare_image.ts'
|
|
7
8
|
import { getMaxSize } from '../../shared/get_max_size.ts'
|
|
8
9
|
import { isSameSize } from '../../shared/is_same_size.ts'
|
|
9
10
|
import type {
|
|
@@ -11,10 +12,10 @@ import type {
|
|
|
11
12
|
ImageSnapshotIdOptions,
|
|
12
13
|
ImageSnapshotTimeoutOptions,
|
|
13
14
|
} from '../../shared/types.ts'
|
|
14
|
-
import { compareImage } from '../compare_image.ts'
|
|
15
15
|
import { file } from '../file.ts'
|
|
16
16
|
import { takeSnapshot, takeSnapshotByBrowser, writeSnapshot, writeSnapshotBuffer } from '../snapshot.ts'
|
|
17
17
|
import { visContext } from '../vis_context.ts'
|
|
18
|
+
import { assertTestPathDefined } from './_assertions.ts'
|
|
18
19
|
|
|
19
20
|
export interface MatchImageSnapshotCommand {
|
|
20
21
|
matchImageSnapshot: (
|
|
@@ -37,9 +38,7 @@ export interface MatchImageSnapshotOptions
|
|
|
37
38
|
export const matchImageSnapshot: BrowserCommand<
|
|
38
39
|
[taskId: string, subject: string, options?: MatchImageSnapshotOptions | undefined]
|
|
39
40
|
> = async (context, taskId, subject, options) => {
|
|
40
|
-
|
|
41
|
-
throw new Error('Cannot match snapshot without testPath')
|
|
42
|
-
}
|
|
41
|
+
assertTestPathDefined(context, 'matchImageSnapshot')
|
|
43
42
|
|
|
44
43
|
// vitest:browser passes in `null` when not defined
|
|
45
44
|
if (!options) options = {}
|
|
@@ -60,8 +59,16 @@ export const matchImageSnapshot: BrowserCommand<
|
|
|
60
59
|
const baselineImage = PNG.sync.read(baselineBuffer, { skipRescale: true, checkCRC: false })
|
|
61
60
|
const resultImage = PNG.sync.read(resultBuffer, { skipRescale: true, checkCRC: false })
|
|
62
61
|
const [baselineAlignedImage, resultAlignedImage] = alignImageSizes(baselineImage, resultImage)
|
|
63
|
-
|
|
64
|
-
const
|
|
62
|
+
const { width, height } = baselineAlignedImage
|
|
63
|
+
const diffImage = new PNG({ width, height })
|
|
64
|
+
const { pass, diffAmount } = compareImage(
|
|
65
|
+
baselineAlignedImage.data,
|
|
66
|
+
resultAlignedImage.data,
|
|
67
|
+
diffImage.data,
|
|
68
|
+
width,
|
|
69
|
+
height,
|
|
70
|
+
options,
|
|
71
|
+
)
|
|
65
72
|
if (pass) {
|
|
66
73
|
if (sizeNotChanged(baselineImage, baselineAlignedImage) && sizeNotChanged(resultImage, resultAlignedImage)) {
|
|
67
74
|
return
|
|
@@ -4,6 +4,7 @@ import { isBase64String } from '../../shared/base64.ts'
|
|
|
4
4
|
import { file } from '../file.ts'
|
|
5
5
|
import { takeSnapshot, takeSnapshotByBrowser, writeSnapshot } from '../snapshot.ts'
|
|
6
6
|
import { visContext } from '../vis_context.ts'
|
|
7
|
+
import { assertTestPathDefined } from './_assertions.ts'
|
|
7
8
|
import type { MatchImageSnapshotOptions } from './match_image_snapshot.ts'
|
|
8
9
|
|
|
9
10
|
type ImageSnapshotComparisonInfo = {
|
|
@@ -26,9 +27,7 @@ export interface PrepareImageSnapshotComparisonCommand {
|
|
|
26
27
|
export const prepareImageSnapshotComparison: BrowserCommand<
|
|
27
28
|
[taskId: string, snapshotId: string, options?: MatchImageSnapshotOptions | undefined]
|
|
28
29
|
> = async (context, taskId, subject, options) => {
|
|
29
|
-
|
|
30
|
-
throw new Error('Cannot match snapshot without testPath')
|
|
31
|
-
}
|
|
30
|
+
assertTestPathDefined(context, 'prepareImageSnapshotComparison')
|
|
32
31
|
|
|
33
32
|
// vitest:browser passes in `null` when not defined
|
|
34
33
|
if (!options) options = {}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BrowserCommand } from 'vitest/node'
|
|
2
2
|
import { visContext } from '../vis_context.ts'
|
|
3
|
+
import { assertTestPathDefined } from './_assertions.ts'
|
|
3
4
|
|
|
4
5
|
export interface SetupVisSuiteCommand {
|
|
5
6
|
/**
|
|
@@ -13,5 +14,7 @@ export interface SetupVisSuiteCommand {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export const setupVisSuite: BrowserCommand<[]> = async (context) => {
|
|
17
|
+
assertTestPathDefined(context, 'setupVisSuite')
|
|
18
|
+
|
|
16
19
|
await visContext.setupSuite(context)
|
|
17
20
|
}
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { mkdirp } from 'mkdirp'
|
|
2
|
-
import { dirname } from 'pathe'
|
|
2
|
+
import { dirname, isAbsolute } from 'pathe'
|
|
3
3
|
import type { BrowserCommand } from 'vitest/node'
|
|
4
4
|
import { file } from '../file.ts'
|
|
5
|
+
import { assertIsRelativePath } from './_assertions.ts'
|
|
5
6
|
|
|
6
7
|
export interface WriteImageSnapshotCommand {
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Writes the image snapshot to the file system.
|
|
10
|
+
* @param relativeFilePath The file path to write the image snapshot to.
|
|
11
|
+
* It is relative to the project root.
|
|
12
|
+
* @param imageBase64 The base64 encoded image.
|
|
13
|
+
*/
|
|
14
|
+
writeImageSnapshot(relativeFilePath: string, imageBase64: string): Promise<void>
|
|
8
15
|
}
|
|
9
16
|
|
|
10
|
-
export const writeImageSnapshot: BrowserCommand<[
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
export const writeImageSnapshot: BrowserCommand<[relativeFilePath: string, imageBase64: string]> = async (
|
|
18
|
+
_,
|
|
19
|
+
relativeFilePath,
|
|
20
|
+
imageBase64,
|
|
14
21
|
) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
await
|
|
19
|
-
await file.writeFile(filePath, base64, { encoding: 'base64' })
|
|
22
|
+
assertIsRelativePath(relativeFilePath, 'relativeFilePath')
|
|
23
|
+
|
|
24
|
+
await mkdirp(dirname(relativeFilePath))
|
|
25
|
+
await file.writeFile(relativeFilePath, imageBase64, { encoding: 'base64' })
|
|
20
26
|
}
|
|
@@ -17,7 +17,7 @@ export type PartialBrowserCommandContext = {
|
|
|
17
17
|
hookTimeout: number
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
testPath: string
|
|
20
|
+
testPath: string
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function createVisContext() {
|
|
@@ -51,7 +51,7 @@ export function createVisContext() {
|
|
|
51
51
|
await globalStateReady
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const { suiteId, suite } = createSuite(state, context.testPath
|
|
54
|
+
const { suiteId, suite } = createSuite(state, context.testPath, visOptions)
|
|
55
55
|
state.suites[suiteId] = suite
|
|
56
56
|
await Promise.allSettled([ctx.rimraf(suite.diffDir), ctx.rimraf(suite.resultDir)])
|
|
57
57
|
},
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import pixelmatch from 'pixelmatch'
|
|
2
|
+
import { convertThresholdUnit } from './convert_threshold_unit.ts'
|
|
3
|
+
import type { ImageSnapshotCompareOptions } from './types.ts'
|
|
4
|
+
|
|
5
|
+
export function compareImage(
|
|
6
|
+
img1: Uint8ClampedArray | Buffer,
|
|
7
|
+
img2: Uint8ClampedArray | Buffer,
|
|
8
|
+
output: Uint8ClampedArray | Buffer,
|
|
9
|
+
width: number,
|
|
10
|
+
height: number,
|
|
11
|
+
{ failureThreshold = 0, failureThresholdType = 'pixel', diffOptions }: ImageSnapshotCompareOptions = {},
|
|
12
|
+
) {
|
|
13
|
+
const pixelDiff = pixelmatch(img1, img2, output, width, height, diffOptions)
|
|
14
|
+
const diffAmount = convertThresholdUnit({ failureThresholdType, width, height }, pixelDiff)
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
pass: diffAmount <= failureThreshold,
|
|
18
|
+
diffAmount,
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/testing.ts
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { ImageSnapshotCompareOptions } from '../shared/types.ts';
|
|
2
|
-
export declare function compareImage(baselineImage: ImageData, resultImage: ImageData, { failureThreshold, failureThresholdType, diffOptions }?: ImageSnapshotCompareOptions): {
|
|
3
|
-
pass: boolean;
|
|
4
|
-
diffAmount: number;
|
|
5
|
-
diffImage: ImageData;
|
|
6
|
-
};
|
|
7
|
-
//# sourceMappingURL=compare_image.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compare_image.d.ts","sourceRoot":"","sources":["../../src/client/compare_image.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAErE,wBAAgB,YAAY,CAC3B,aAAa,EAAE,SAAS,EACxB,WAAW,EAAE,SAAS,EACtB,EAAE,gBAAoB,EAAE,oBAA8B,EAAE,WAAW,EAAE,GAAE,2BAAgC;;;;EAavG"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import pixelmatch from 'pixelmatch';
|
|
2
|
-
import { convertThresholdUnit } from "../shared/convert_threshold_unit.js";
|
|
3
|
-
export function compareImage(baselineImage, resultImage, { failureThreshold = 0, failureThresholdType = 'pixel', diffOptions } = {}) {
|
|
4
|
-
const { width, height } = resultImage;
|
|
5
|
-
const diffImage = new ImageData(width, height);
|
|
6
|
-
const pixelDiff = pixelmatch(resultImage.data, baselineImage.data, diffImage.data, width, height, diffOptions);
|
|
7
|
-
const diffAmount = convertThresholdUnit({ failureThresholdType, width, height }, pixelDiff);
|
|
8
|
-
return {
|
|
9
|
-
pass: diffAmount <= failureThreshold,
|
|
10
|
-
diffAmount,
|
|
11
|
-
diffImage,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"is_ci.d.ts","sourceRoot":"","sources":["../../../src/server/commands/is_ci.ts"],"names":[],"mappings":""}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { PNG } from 'pngjs';
|
|
2
|
-
import type { ImageSnapshotCompareOptions } from '../shared/types.ts';
|
|
3
|
-
export declare function compareImage(baselineImage: PNG, resultImage: PNG, { failureThreshold, failureThresholdType, diffOptions }?: ImageSnapshotCompareOptions): {
|
|
4
|
-
pass: boolean;
|
|
5
|
-
diffAmount: number;
|
|
6
|
-
diffImage: PNG;
|
|
7
|
-
};
|
|
8
|
-
//# sourceMappingURL=compare_image.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compare_image.d.ts","sourceRoot":"","sources":["../../src/server/compare_image.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAE3B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAErE,wBAAgB,YAAY,CAC3B,aAAa,EAAE,GAAG,EAClB,WAAW,EAAE,GAAG,EAChB,EAAE,gBAAoB,EAAE,oBAA8B,EAAE,WAAW,EAAE,GAAE,2BAAgC;;;;EAyBvG"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import pixelmatch from 'pixelmatch';
|
|
2
|
-
import { PNG } from 'pngjs';
|
|
3
|
-
import { convertThresholdUnit } from "../shared/convert_threshold_unit.js";
|
|
4
|
-
export function compareImage(baselineImage, resultImage, { failureThreshold = 0, failureThresholdType = 'pixel', diffOptions } = {}) {
|
|
5
|
-
const diffImage = new PNG({
|
|
6
|
-
width: baselineImage.width,
|
|
7
|
-
height: baselineImage.height,
|
|
8
|
-
});
|
|
9
|
-
const pixelDiff = pixelmatch(resultImage.data, baselineImage.data, diffImage.data, baselineImage.width, baselineImage.height, diffOptions);
|
|
10
|
-
const diffAmount = convertThresholdUnit({ failureThresholdType, width: baselineImage.width, height: baselineImage.height }, pixelDiff);
|
|
11
|
-
return {
|
|
12
|
-
pass: diffAmount <= failureThreshold,
|
|
13
|
-
diffAmount,
|
|
14
|
-
diffImage,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import pixelmatch from 'pixelmatch'
|
|
2
|
-
import { convertThresholdUnit } from '../shared/convert_threshold_unit.ts'
|
|
3
|
-
import type { ImageSnapshotCompareOptions } from '../shared/types.ts'
|
|
4
|
-
|
|
5
|
-
export function compareImage(
|
|
6
|
-
baselineImage: ImageData,
|
|
7
|
-
resultImage: ImageData,
|
|
8
|
-
{ failureThreshold = 0, failureThresholdType = 'pixel', diffOptions }: ImageSnapshotCompareOptions = {},
|
|
9
|
-
) {
|
|
10
|
-
const { width, height } = resultImage
|
|
11
|
-
const diffImage = new ImageData(width, height)
|
|
12
|
-
|
|
13
|
-
const pixelDiff = pixelmatch(resultImage.data, baselineImage.data, diffImage.data, width, height, diffOptions)
|
|
14
|
-
const diffAmount = convertThresholdUnit({ failureThresholdType, width, height }, pixelDiff)
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
pass: diffAmount <= failureThreshold,
|
|
18
|
-
diffAmount,
|
|
19
|
-
diffImage,
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import pixelmatch from 'pixelmatch'
|
|
2
|
-
import { PNG } from 'pngjs'
|
|
3
|
-
import { convertThresholdUnit } from '../shared/convert_threshold_unit.ts'
|
|
4
|
-
import type { ImageSnapshotCompareOptions } from '../shared/types.ts'
|
|
5
|
-
|
|
6
|
-
export function compareImage(
|
|
7
|
-
baselineImage: PNG,
|
|
8
|
-
resultImage: PNG,
|
|
9
|
-
{ failureThreshold = 0, failureThresholdType = 'pixel', diffOptions }: ImageSnapshotCompareOptions = {},
|
|
10
|
-
) {
|
|
11
|
-
const diffImage = new PNG({
|
|
12
|
-
width: baselineImage.width,
|
|
13
|
-
height: baselineImage.height,
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
const pixelDiff = pixelmatch(
|
|
17
|
-
resultImage.data,
|
|
18
|
-
baselineImage.data,
|
|
19
|
-
diffImage.data,
|
|
20
|
-
baselineImage.width,
|
|
21
|
-
baselineImage.height,
|
|
22
|
-
diffOptions,
|
|
23
|
-
)
|
|
24
|
-
const diffAmount = convertThresholdUnit(
|
|
25
|
-
{ failureThresholdType, width: baselineImage.width, height: baselineImage.height },
|
|
26
|
-
pixelDiff,
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
pass: diffAmount <= failureThreshold,
|
|
31
|
-
diffAmount,
|
|
32
|
-
diffImage,
|
|
33
|
-
}
|
|
34
|
-
}
|