ftmocks-utils 1.4.7 → 1.4.9
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/package.json +4 -2
- package/src/event-run-utils.js +89 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ftmocks-utils",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.9",
|
|
4
4
|
"description": "Util functions for FtMocks",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"homepage": "https://github.com/SodhanaLibrary/ftmocks-utils#readme",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"uui": "^1.0.7",
|
|
22
|
-
"uuid": "^11.1.0"
|
|
22
|
+
"uuid": "^11.1.0",
|
|
23
|
+
"pixelmatch": "^5.3.1",
|
|
24
|
+
"pngjs": "^7.0.1"
|
|
23
25
|
}
|
|
24
26
|
}
|
package/src/event-run-utils.js
CHANGED
|
@@ -2,9 +2,80 @@ const path = require("path");
|
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
const { getMockDir, nameToFolder } = require("./common-utils");
|
|
4
4
|
|
|
5
|
+
const createDiffImage = async (img1, img2, diffPath) => {
|
|
6
|
+
const pixelmatch = (await import("pixelmatch")).default;
|
|
7
|
+
const { PNG } = (await import("pngjs")).default;
|
|
8
|
+
|
|
9
|
+
const { width, height } = img1;
|
|
10
|
+
|
|
11
|
+
const diff = new PNG({ width, height });
|
|
12
|
+
|
|
13
|
+
const numDiffPixels = pixelmatch(
|
|
14
|
+
img1.data,
|
|
15
|
+
img2.data,
|
|
16
|
+
diff.data,
|
|
17
|
+
width,
|
|
18
|
+
height,
|
|
19
|
+
{
|
|
20
|
+
threshold: 0.1, // sensitivity
|
|
21
|
+
diffColor: [255, 0, 0], // highlight color (red)
|
|
22
|
+
diffMask: false,
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
fs.writeFileSync(diffPath, PNG.sync.write(diff));
|
|
27
|
+
|
|
28
|
+
return numDiffPixels;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const matchAndReplaceScreenshot = async (page, event, screenshotsDir) => {
|
|
32
|
+
const pixelmatch = (await import("pixelmatch")).default;
|
|
33
|
+
const { PNG } = (await import("pngjs")).default;
|
|
34
|
+
|
|
35
|
+
const file = path.join(screenshotsDir, `${event.id}.png`);
|
|
36
|
+
const newFile = path.join(screenshotsDir, `__temp_${event.id}.png`);
|
|
37
|
+
|
|
38
|
+
await page.screenshot({ path: newFile, fullPage: false });
|
|
39
|
+
|
|
40
|
+
if (!fs.existsSync(file)) {
|
|
41
|
+
fs.renameSync(newFile, file);
|
|
42
|
+
return {
|
|
43
|
+
replaced: true,
|
|
44
|
+
diffPath: null,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const img1 = PNG.sync.read(fs.readFileSync(file));
|
|
49
|
+
const img2 = PNG.sync.read(fs.readFileSync(newFile));
|
|
50
|
+
|
|
51
|
+
const diff = pixelmatch(img1.data, img2.data, null, img1.width, img1.height, {
|
|
52
|
+
threshold: 0.1,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (diff > 0) {
|
|
56
|
+
console.log(`Screenshot changed → replacing: ${file}`);
|
|
57
|
+
fs.renameSync(newFile, file); // overwrite only when mismatch
|
|
58
|
+
await createDiffImage(
|
|
59
|
+
img1,
|
|
60
|
+
img2,
|
|
61
|
+
path.join(screenshotsDir, `diff_${event.id}.png`)
|
|
62
|
+
);
|
|
63
|
+
return {
|
|
64
|
+
replaced: true,
|
|
65
|
+
diffPath: `diff_${event.id}.png`,
|
|
66
|
+
};
|
|
67
|
+
} else {
|
|
68
|
+
console.log(`Screenshot did not change → removing temp file: ${newFile}`);
|
|
69
|
+
fs.unlinkSync(newFile); // no change → remove temp file
|
|
70
|
+
return {
|
|
71
|
+
replaced: false,
|
|
72
|
+
diffPath: null,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
5
77
|
const getLocator = async (page, event) => {
|
|
6
78
|
// Check if the event.target exists on the page before returning it.
|
|
7
|
-
console.log("➡ Getting locator for event", event);
|
|
8
79
|
if (event && event.target && typeof page !== "undefined" && page.locator) {
|
|
9
80
|
let locator = null;
|
|
10
81
|
while (!locator) {
|
|
@@ -32,7 +103,6 @@ const getLocator = async (page, event) => {
|
|
|
32
103
|
} catch (error) {
|
|
33
104
|
console.error("Error getting locator", error, selector);
|
|
34
105
|
}
|
|
35
|
-
console.log("➡ Waiting for locator", event);
|
|
36
106
|
await page.waitForTimeout(500);
|
|
37
107
|
}
|
|
38
108
|
return locator;
|
|
@@ -102,20 +172,26 @@ const runEvent = async ({
|
|
|
102
172
|
healSelectors = false,
|
|
103
173
|
}) => {
|
|
104
174
|
try {
|
|
105
|
-
console.log("➡ Running event", event);
|
|
106
175
|
const beforeEvent = async () => {
|
|
107
176
|
await page.waitForTimeout(delay);
|
|
108
177
|
if (screenshots) {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
178
|
+
const res = await matchAndReplaceScreenshot(
|
|
179
|
+
page,
|
|
180
|
+
event,
|
|
181
|
+
screenshotsDir
|
|
182
|
+
);
|
|
183
|
+
if (res.replaced) {
|
|
184
|
+
const locator = await getLocator(page, event);
|
|
185
|
+
const position = await getSelectorPosition(page, locator);
|
|
186
|
+
event.screenshotInfo = {
|
|
187
|
+
name: `${event.id}.png`,
|
|
188
|
+
position,
|
|
189
|
+
time: new Date().toISOString(),
|
|
190
|
+
diffPath: res.diffPath
|
|
191
|
+
? res.diffPath
|
|
192
|
+
: event.screenshotInfo?.diffPath,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
119
195
|
}
|
|
120
196
|
if (healSelectors) {
|
|
121
197
|
const locator = await getLocator(page, event);
|
|
@@ -207,7 +283,6 @@ const runEvent = async ({
|
|
|
207
283
|
|
|
208
284
|
const isValidEvent = (event) => {
|
|
209
285
|
try {
|
|
210
|
-
console.log("➡ Validating event", event);
|
|
211
286
|
switch (event?.type) {
|
|
212
287
|
case "click":
|
|
213
288
|
return true;
|
|
@@ -285,9 +360,7 @@ const runEventsInPresentationMode = async (page, ftmocksConifg, testName) => {
|
|
|
285
360
|
|
|
286
361
|
// Expose Node function
|
|
287
362
|
await page.exposeFunction("nextEvent", async () => {
|
|
288
|
-
console.log("➡ Next event triggered!");
|
|
289
363
|
if (currentEventIndex === events.length) {
|
|
290
|
-
console.log("➡ No more events to run!");
|
|
291
364
|
return false;
|
|
292
365
|
}
|
|
293
366
|
let result = await runEvent({ page, event: events[currentEventIndex] });
|