vitest-plugin-vis 1.0.2 → 1.0.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../../../src/server/browser_provider/playwright.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wBAAgB,UAAU,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAYrE"}
1
+ {"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../../../src/server/browser_provider/playwright.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wBAAgB,UAAU,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAWrE"}
@@ -3,11 +3,10 @@ export function playwright(context) {
3
3
  async takeScreenshot(filePath, selector, options) {
4
4
  // The `Locator` type from `vitest` has less props than the `Locator` in `playwright`
5
5
  const subject = context.iframe.locator(selector ?? 'body');
6
- const buffer = await subject.screenshot({
6
+ return subject.screenshot({
7
7
  timeout: options?.timeout,
8
8
  path: filePath,
9
9
  });
10
- return buffer.toString('base64');
11
10
  },
12
11
  };
13
12
  }
@@ -1,6 +1,6 @@
1
1
  export interface BrowserApi {
2
2
  takeScreenshot(filePath: string, selector: string, options: {
3
3
  timeout?: number | undefined;
4
- } | undefined): Promise<string>;
4
+ } | undefined): Promise<Buffer>;
5
5
  }
6
6
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webdriverio.d.ts","sourceRoot":"","sources":["../../../src/server/browser_provider/webdriverio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAStE"}
1
+ {"version":3,"file":"webdriverio.d.ts","sourceRoot":"","sources":["../../../src/server/browser_provider/webdriverio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAQtE"}
@@ -3,8 +3,7 @@ export function webdriverio(context) {
3
3
  return {
4
4
  async takeScreenshot(filePath, selector) {
5
5
  const element = await page.$(`${selector ?? 'body'}`);
6
- const buffer = await element.saveScreenshot(filePath);
7
- return buffer.toString('base64');
6
+ return element.saveScreenshot(filePath);
8
7
  },
9
8
  };
10
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"match_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/match_image_snapshot.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAyB,MAAM,aAAa,CAAA;AAIxE,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,CA2DlF,CAAA"}
1
+ {"version":3,"file":"match_image_snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/commands/match_image_snapshot.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAyB,MAAM,aAAa,CAAA;AAIxE,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,CA6DlF,CAAA"}
@@ -19,17 +19,20 @@ export const matchImageSnapshot = async (context, taskId, subject, options) => {
19
19
  options = {};
20
20
  options.timeout = options.timeout ?? (ci ? 30000 : 5000);
21
21
  const info = visContext.getSnapshotInfo(context.testPath, taskId, options);
22
- const baselineBase64 = await file.tryReadFileBase64(info.baselinePath);
23
- if (!baselineBase64) {
24
- await takeSnapshot(context, subject, info.baselinePath, options);
22
+ const baselineBuffer = await file.tryReadFile(info.baselinePath);
23
+ if (!baselineBuffer) {
24
+ if (isBase64String(subject)) {
25
+ await writeSnapshot(subject, info.baselinePath);
26
+ }
27
+ else {
28
+ await takeSnapshotByBrowser(context, subject, info.baselinePath, options);
29
+ }
25
30
  return;
26
31
  }
27
- const resultBase64 = await takeSnapshot(context, subject, info.resultPath, options);
28
- const baselineImage = PNG.sync.read(Buffer.from(baselineBase64, 'base64'));
29
- const resultImage = PNG.sync.read(Buffer.from(resultBase64, 'base64'));
30
- const [baselineAlignedImage, resultAlignedImage] = isSameSize(baselineImage, resultImage)
31
- ? [baselineImage, resultImage]
32
- : alignImageSizes(baselineImage, resultImage);
32
+ const resultBuffer = await takeSnapshot(context, subject, info.resultPath, options);
33
+ const baselineImage = PNG.sync.read(baselineBuffer, { skipRescale: true, checkCRC: false });
34
+ const resultImage = PNG.sync.read(resultBuffer, { skipRescale: true, checkCRC: false });
35
+ const [baselineAlignedImage, resultAlignedImage] = alignImageSizes(baselineImage, resultImage);
33
36
  const { pass, diffAmount, diffImage } = compareImage(baselineAlignedImage, resultAlignedImage, options);
34
37
  if (pass) {
35
38
  if (sizeNotChanged(baselineImage, baselineAlignedImage) && sizeNotChanged(resultImage, resultAlignedImage)) {
@@ -60,8 +63,11 @@ export const matchImageSnapshot = async (context, taskId, subject, options) => {
60
63
  };
61
64
  async function takeSnapshot(context, subject, filePath, options) {
62
65
  if (isBase64String(subject)) {
63
- return writeSnapshot(subject, filePath);
66
+ return Buffer.from(await writeSnapshot(subject, filePath), 'base64');
64
67
  }
68
+ return takeSnapshotByBrowser(context, subject, filePath, options);
69
+ }
70
+ async function takeSnapshotByBrowser(context, subject, filePath, options) {
65
71
  await mkdirp(dirname(filePath));
66
72
  const browser = browserApi(context);
67
73
  return browser.takeScreenshot(filePath, subject, {
@@ -74,16 +80,14 @@ async function writeSnapshot(subject, filePath) {
74
80
  return subject;
75
81
  }
76
82
  function alignImageSizes(baseline, result) {
83
+ if (isSameSize(baseline, result))
84
+ return [baseline, result];
77
85
  const size = getMaxSize(baseline, result);
78
- if (baseline.width !== size.width || baseline.height !== size.height) {
79
- baseline = resizeImage(baseline, size);
80
- }
81
- if (result.width !== size.width || result.height !== size.height) {
82
- result = resizeImage(result, size);
83
- }
84
- return [baseline, result];
86
+ return [resizeImage(baseline, size), resizeImage(result, size)];
85
87
  }
86
88
  function resizeImage(image, size) {
89
+ if (isSameSize(image, size))
90
+ return image;
87
91
  const resized = new PNG(size);
88
92
  PNG.bitblt(image, resized, 0, 0, image.width, image.height);
89
93
  return resized;
@@ -1,5 +1,5 @@
1
1
  export declare const file: {
2
- tryReadFileBase64(filePath: string): Promise<string | undefined>;
2
+ tryReadFile(filePath: string): Promise<Buffer | undefined>;
3
3
  writeFileBase64(filePath: string, data: string): Promise<void>;
4
4
  existFile(filePath: string): Promise<boolean>;
5
5
  };
@@ -1 +1 @@
1
- {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/server/file.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,IAAI;gCACkB,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;8BAG5C,MAAM,QAAQ,MAAM;wBAG1B,MAAM;CAK1B,CAAA"}
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/server/file.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,IAAI;0BACY,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;8BAGtC,MAAM,QAAQ,MAAM;wBAG1B,MAAM;CAK1B,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { readFile, stat, writeFile } from 'node:fs/promises';
2
2
  export const file = {
3
- async tryReadFileBase64(filePath) {
4
- return readFile(filePath, { encoding: 'base64' }).catch(() => undefined);
3
+ async tryReadFile(filePath) {
4
+ return readFile(filePath).catch(() => undefined);
5
5
  },
6
6
  writeFileBase64(filePath, data) {
7
7
  return writeFile(filePath, data, { encoding: 'base64' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-plugin-vis",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Vitest visual testing plugin",
5
5
  "keywords": [
6
6
  "image-snapshot",
@@ -6,11 +6,10 @@ export function playwright(context: BrowserCommandContext): BrowserApi {
6
6
  async takeScreenshot(filePath, selector, options) {
7
7
  // The `Locator` type from `vitest` has less props than the `Locator` in `playwright`
8
8
  const subject = context.iframe.locator(selector ?? 'body')
9
- const buffer = await subject.screenshot({
9
+ return subject.screenshot({
10
10
  timeout: options?.timeout,
11
11
  path: filePath,
12
12
  })
13
- return buffer.toString('base64')
14
13
  },
15
14
  }
16
15
  }
@@ -7,5 +7,5 @@ export interface BrowserApi {
7
7
  timeout?: number | undefined
8
8
  }
9
9
  | undefined,
10
- ): Promise<string>
10
+ ): Promise<Buffer>
11
11
  }
@@ -6,8 +6,7 @@ export function webdriverio(context: BrowserCommandContext): BrowserApi {
6
6
  return {
7
7
  async takeScreenshot(filePath, selector) {
8
8
  const element = await page.$(`${selector ?? 'body'}`)
9
- const buffer = await element.saveScreenshot(filePath)
10
- return buffer.toString('base64')
9
+ return element.saveScreenshot(filePath)
11
10
  },
12
11
  }
13
12
  }
@@ -47,18 +47,20 @@ export const matchImageSnapshot: BrowserCommand<
47
47
  options.timeout = options.timeout ?? (ci ? 30000 : 5000)
48
48
 
49
49
  const info = visContext.getSnapshotInfo(context.testPath, taskId, options)
50
- const baselineBase64 = await file.tryReadFileBase64(info.baselinePath)
51
- if (!baselineBase64) {
52
- await takeSnapshot(context, subject, info.baselinePath, options)
50
+ const baselineBuffer = await file.tryReadFile(info.baselinePath)
51
+ if (!baselineBuffer) {
52
+ if (isBase64String(subject)) {
53
+ await writeSnapshot(subject, info.baselinePath)
54
+ } else {
55
+ await takeSnapshotByBrowser(context, subject, info.baselinePath, options)
56
+ }
53
57
  return
54
58
  }
55
59
 
56
- const resultBase64 = await takeSnapshot(context, subject, info.resultPath, options)
57
- const baselineImage = PNG.sync.read(Buffer.from(baselineBase64, 'base64'))
58
- const resultImage = PNG.sync.read(Buffer.from(resultBase64, 'base64'))
59
- const [baselineAlignedImage, resultAlignedImage] = isSameSize(baselineImage, resultImage)
60
- ? [baselineImage, resultImage]
61
- : alignImageSizes(baselineImage, resultImage)
60
+ const resultBuffer = await takeSnapshot(context, subject, info.resultPath, options)
61
+ const baselineImage = PNG.sync.read(baselineBuffer, { skipRescale: true, checkCRC: false })
62
+ const resultImage = PNG.sync.read(resultBuffer, { skipRescale: true, checkCRC: false })
63
+ const [baselineAlignedImage, resultAlignedImage] = alignImageSizes(baselineImage, resultImage)
62
64
 
63
65
  const { pass, diffAmount, diffImage } = compareImage(baselineAlignedImage, resultAlignedImage, options)
64
66
  if (pass) {
@@ -104,9 +106,17 @@ async function takeSnapshot(
104
106
  options: ImageSnapshotTimeoutOptions | undefined,
105
107
  ) {
106
108
  if (isBase64String(subject)) {
107
- return writeSnapshot(subject, filePath)
109
+ return Buffer.from(await writeSnapshot(subject, filePath), 'base64')
108
110
  }
111
+ return takeSnapshotByBrowser(context, subject, filePath, options)
112
+ }
109
113
 
114
+ async function takeSnapshotByBrowser(
115
+ context: BrowserCommandContext,
116
+ subject: string,
117
+ filePath: string,
118
+ options: ImageSnapshotTimeoutOptions | undefined,
119
+ ) {
110
120
  await mkdirp(dirname(filePath))
111
121
  const browser = browserApi(context)
112
122
  return browser.takeScreenshot(filePath, subject, {
@@ -121,20 +131,15 @@ async function writeSnapshot(subject: string, filePath: string) {
121
131
  }
122
132
 
123
133
  function alignImageSizes(baseline: PNG, result: PNG) {
124
- const size = getMaxSize(baseline, result)
125
-
126
- if (baseline.width !== size.width || baseline.height !== size.height) {
127
- baseline = resizeImage(baseline, size)
128
- }
134
+ if (isSameSize(baseline, result)) return [baseline, result] as const
129
135
 
130
- if (result.width !== size.width || result.height !== size.height) {
131
- result = resizeImage(result, size)
132
- }
133
-
134
- return [baseline, result] as const
136
+ const size = getMaxSize(baseline, result)
137
+ return [resizeImage(baseline, size), resizeImage(result, size)] as const
135
138
  }
136
139
 
137
140
  function resizeImage(image: PNG, size: { width: number; height: number }) {
141
+ if (isSameSize(image, size)) return image
142
+
138
143
  const resized = new PNG(size)
139
144
  PNG.bitblt(image, resized, 0, 0, image.width, image.height)
140
145
  return resized
@@ -1,8 +1,8 @@
1
1
  import { readFile, stat, writeFile } from 'node:fs/promises'
2
2
 
3
3
  export const file = {
4
- async tryReadFileBase64(filePath: string): Promise<string | undefined> {
5
- return readFile(filePath, { encoding: 'base64' }).catch(() => undefined)
4
+ async tryReadFile(filePath: string): Promise<Buffer | undefined> {
5
+ return readFile(filePath).catch(() => undefined)
6
6
  },
7
7
  writeFileBase64(filePath: string, data: string) {
8
8
  return writeFile(filePath, data, { encoding: 'base64' })