artes 1.5.6 → 1.5.8

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.
@@ -309,6 +309,12 @@
309
309
  - User expects `{string}` should have `{string}` id
310
310
  - User expects `{string}` should have `{string}` JavaScript property with `{string}` value
311
311
  - User expects `{string}` should have `{string}` role
312
+ - User expects that full page match with `{string}` screenshot
313
+ - User expects that full page match with `{string}` screenshot with {float}% difference
314
+ - User expects that page match with `{string}` screenshot
315
+ - User expects that page match with `{string}` screenshot with `{float}`% difference
316
+ - User expects that `{string}` element match with `{string}` screenshot
317
+ - User expects that `{string}` element match with `{string}` screenshot with `{float}`% difference
312
318
  - User expects `{string}` should have a screenshot
313
319
  - User expects `{string}` should match `{string}` text
314
320
  - User expects `{string}` should have `{string}` value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artes",
3
- "version": "1.5.6",
3
+ "version": "1.5.8",
4
4
  "description": "The simplest way to automate UI and API tests using Cucumber-style steps.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -30,7 +30,10 @@
30
30
  "deasync": "^0.1.31",
31
31
  "playwright": "^1.58.2",
32
32
  "ffmpeg-static": "^5.3.0",
33
- "ffprobe-static": "^3.1.0"
33
+ "ffprobe-static": "^3.1.0",
34
+ "pixelmatch": "^5.3.0",
35
+ "pngjs": "^7.0.0",
36
+ "sharp": "^0.34.5"
34
37
  },
35
38
  "repository": {
36
39
  "type": "git",
@@ -0,0 +1,85 @@
1
+
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ require("allure-cucumberjs");
5
+ const allure = require("allure-js-commons");
6
+ const sharp = require("sharp");
7
+ const pixelmatch = require("pixelmatch");
8
+ const { PNG } = require('pngjs');
9
+ const { moduleConfig } = require('artes/src/helper/imports/commons');
10
+
11
+
12
+ async function screenComparer(baselineFilename, screenshotFn, options = {}) {
13
+ const {
14
+ maxDiffPercent = 0.01,
15
+ threshold = 0.1,
16
+ } = options;
17
+
18
+ const baselinePath = path.join(moduleConfig.projectPath, baselineFilename);
19
+ const actualPath = path.join(moduleConfig.projectPath,"visualComparison", `actual_${baselineFilename}`);
20
+ const diffPath = path.join(moduleConfig.projectPath,"visualComparison", `diff_${baselineFilename}`);
21
+
22
+ await screenshotFn(actualPath);
23
+
24
+ const baselineMeta = await sharp(baselinePath).metadata();
25
+ const actualMeta = await sharp(actualPath).metadata();
26
+
27
+ // if (baselineMeta.width !== actualMeta.width || baselineMeta.height !== actualMeta.height) {
28
+ // console.warn(`⚠️ Dimension mismatch! Baseline: ${baselineMeta.width}x${baselineMeta.height} | Actual: ${actualMeta.width}x${actualMeta.height}`);
29
+ // }
30
+
31
+ const width = actualMeta.width;
32
+ const height = actualMeta.height;
33
+
34
+ const baselineBuffer = await sharp(baselinePath)
35
+ .resize(width, height, { fit: "fill" })
36
+ .ensureAlpha()
37
+ .raw()
38
+ .toBuffer();
39
+
40
+ const actualBuffer = await sharp(actualPath)
41
+ .resize(width, height, { fit: "fill" })
42
+ .ensureAlpha()
43
+ .raw()
44
+ .toBuffer();
45
+
46
+ const diffImg = new PNG({ width, height });
47
+
48
+ const mismatchedPixels = pixelmatch(
49
+ baselineBuffer,
50
+ actualBuffer,
51
+ diffImg.data,
52
+ width,
53
+ height,
54
+ { threshold, includeAA: false }
55
+ );
56
+
57
+ fs.writeFileSync(diffPath, PNG.sync.write(diffImg));
58
+
59
+ const totalPixels = width * height;
60
+ const mismatchRatio = mismatchedPixels / totalPixels;
61
+
62
+ const expectedBase64 = (await sharp(baselinePath).resize(width, height, { fit: "fill" }).png().toBuffer()).toString("base64");
63
+ const actualBase64 = (await sharp(actualPath).png().toBuffer()).toString("base64");
64
+ const diffBase64 = (await sharp(diffPath).png().toBuffer()).toString("base64");
65
+
66
+ const content = JSON.stringify({
67
+ expected: `data:image/png;base64,${expectedBase64}`,
68
+ actual: `data:image/png;base64,${actualBase64}`,
69
+ diff: `data:image/png;base64,${diffBase64}`,
70
+ });
71
+
72
+ await allure.attachment("Screenshot diff details", ` Mismatched pixels: ${mismatchedPixels} / ${totalPixels} (${(mismatchRatio * 100).toFixed(2)}%) Max allowed: ${(maxDiffPercent * 100)}%`, "text/plain" )
73
+ await allure.attachment("Screenshot diff", content, "application/vnd.allure.image.diff");
74
+
75
+ if (fs.existsSync(path.join(moduleConfig.projectPath,"visualComparison"))) fs.rmSync(path.join(moduleConfig.projectPath,"visualComparison"), {recursive: true, force: true});
76
+
77
+ if (mismatchRatio > maxDiffPercent) {
78
+ throw new Error(
79
+ `Screenshot mismatch: ${(mismatchRatio * 100).toFixed(2)}% pixels differ (max allowed: ${(maxDiffPercent * 100)}%)`
80
+ );
81
+ }
82
+
83
+ }
84
+
85
+ module.exports= { screenComparer}
@@ -186,13 +186,6 @@ const assert = {
186
186
  typeof selector === "string" ? element(selector) : await selector,
187
187
  ).toHaveRole(role, options);
188
188
  },
189
- shouldHaveScreenshot: async (selector, options) => {
190
- options = options ?? {};
191
-
192
- await expect(
193
- typeof selector === "string" ? element(selector) : await selector,
194
- ).toHaveScreenshot(options);
195
- },
196
189
  shouldHaveText: async (selector, text, options) => {
197
190
  options = options ?? {};
198
191
 
@@ -7,6 +7,7 @@ const {
7
7
  context,
8
8
  resolveVariable
9
9
  } = require("../helper/imports/commons");
10
+ const { screenComparer } = require("artes/src/helper/controller/screenComparer");
10
11
  const { assert, frame } = require("../helper/stepFunctions/exporter");
11
12
  const Ajv = require("ajv");
12
13
 
@@ -266,13 +267,50 @@ Then("User expects {int} th of {string} should have {string} role", async functi
266
267
  await assert.shouldHaveId(nthElement, role);
267
268
  });
268
269
 
269
- // Check if a selector should have a screenshot
270
- Then(
271
- "User expects {string} should have a screenshot",
272
- async function (selector) {
273
- await assert.shouldHaveScreenshot(selector);
274
- },
275
- );
270
+
271
+ Then('User expects that full page match with {string} screenshot', async function (baselineFilename) {
272
+ await screenComparer( baselineFilename,
273
+ (actualPath) => context.page.screenshot({ path: actualPath, fullPage: true }),
274
+ { maxDiffPercent: 0.01 }
275
+ );
276
+ });
277
+
278
+ Then('User expects that full page match with {string} screenshot with {float}% difference', async function (baselineFilename, maxDiff) {
279
+ await screenComparer( baselineFilename,
280
+ (actualPath) => context.page.screenshot({ path: actualPath, fullPage: true }),
281
+ { maxDiffPercent: maxDiff / 100 }
282
+ );
283
+ });
284
+
285
+
286
+ Then('User expects that page match with {string} screenshot', async function (baselineFilename) {
287
+ await screenComparer(baselineFilename,
288
+ (actualPath) => context.page.screenshot({ path: actualPath, fullPage: false }),
289
+ { maxDiffPercent: 0.01 }
290
+ );
291
+ });
292
+
293
+ Then('User expects that page match with {string} screenshot with {float}% difference', async function (baselineFilename, maxDiff) {
294
+ await screenComparer( baselineFilename,
295
+ (actualPath) => context.page.screenshot({ path: actualPath, fullPage: false }),
296
+ { maxDiffPercent: maxDiff / 100 }
297
+ );
298
+ });
299
+
300
+
301
+ Then('User expects that {string} element match with {string} screenshot', async function (selector, baselineFilename) {
302
+ await screenComparer( baselineFilename,
303
+ (actualPath) => element(selector).screenshot({ path: actualPath }),
304
+ { maxDiffPercent: 0.01 }
305
+ );
306
+ });
307
+
308
+ Then('User expects that {string} element match with {string} screenshot with {float}% difference', async function (selector, baselineFilename, maxDiff) {
309
+ await screenComparer( baselineFilename,
310
+ (actualPath) => element(selector).screenshot({ path: actualPath }),
311
+ { maxDiffPercent: maxDiff / 100 }
312
+ );
313
+ });
276
314
 
277
315
  // Check if a selector should have specific text
278
316
  Then(