@brightspace-ui/testing 1.38.1 → 1.38.2
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 +1 -1
- package/src/server/visual-diff-plugin.js +103 -88
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@brightspace-ui/testing",
|
|
3
3
|
"description": "Utilities for testing front-end components and applications",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.38.
|
|
5
|
+
"version": "1.38.2",
|
|
6
6
|
"repository": "https://github.com/BrightspaceUI/testing.git",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"lint": "npm run lint:eslint && npm run lint:style",
|
|
@@ -51,24 +51,31 @@ async function clearDiffPaths(dir) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function getResizedPng(xName, yName, original, newSize) {
|
|
55
|
+
const xOffsets = {
|
|
56
|
+
left: 0,
|
|
57
|
+
center: Math.floor((newSize.width - original.width) / 2),
|
|
58
|
+
right: newSize.width - original.width
|
|
59
|
+
};
|
|
60
|
+
const yOffsets = {
|
|
61
|
+
top: 0,
|
|
62
|
+
center: Math.floor((newSize.height - original.height) / 2),
|
|
63
|
+
bottom: newSize.height - original.height
|
|
64
|
+
};
|
|
65
|
+
const resized = new PNG(newSize);
|
|
66
|
+
PNG.bitblt(original, resized, 0, 0, original.width, original.height, xOffsets[xName], yOffsets[yName]);
|
|
67
|
+
return resized;
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
async function createComparisonPNGs(original, newSize) {
|
|
55
71
|
const resizedPNGs = [];
|
|
56
|
-
[
|
|
57
|
-
|
|
58
|
-
{ name: 'center', coord: Math.floor((newSize.height - original.height) / 2) },
|
|
59
|
-
{ name: 'bottom', coord: newSize.height - original.height }
|
|
60
|
-
].forEach(y => {
|
|
61
|
-
[
|
|
62
|
-
{ name: 'left', coord: 0 },
|
|
63
|
-
{ name: 'center', coord: Math.floor((newSize.width - original.width) / 2) },
|
|
64
|
-
{ name: 'right', coord: newSize.width - original.width }
|
|
65
|
-
].forEach(x => { // TODO: position added for reports, remove/adjust as needed
|
|
72
|
+
[ 'top', 'center', 'bottom' ].forEach(y => {
|
|
73
|
+
['left', 'center', 'right'].forEach(x => {
|
|
66
74
|
if (original.width === newSize.width && original.height === newSize.height) {
|
|
67
|
-
resizedPNGs.push({ png: original, position: `${y
|
|
75
|
+
resizedPNGs.push({ png: original, position: `${y}-${x}` });
|
|
68
76
|
} else {
|
|
69
|
-
const resized =
|
|
70
|
-
|
|
71
|
-
resizedPNGs.push({ png: resized, position: `${y.name}-${x.name}` });
|
|
77
|
+
const resized = getResizedPng(x, y, original, newSize);
|
|
78
|
+
resizedPNGs.push({ png: resized, position: `${y}-${x}` });
|
|
72
79
|
}
|
|
73
80
|
});
|
|
74
81
|
});
|
|
@@ -76,6 +83,14 @@ async function createComparisonPNGs(original, newSize) {
|
|
|
76
83
|
return resizedPNGs;
|
|
77
84
|
}
|
|
78
85
|
|
|
86
|
+
function getPixelsDiff(screenshotImage, goldenImage) {
|
|
87
|
+
const diff = new PNG({ width: screenshotImage.width, height: screenshotImage.height });
|
|
88
|
+
const pixelsDiff = pixelmatch(
|
|
89
|
+
screenshotImage.data, goldenImage.data, diff.data, screenshotImage.width, screenshotImage.height, { diffMask: true, threshold: DEFAULT_TOLERANCE }
|
|
90
|
+
);
|
|
91
|
+
return { diff, pixelsDiff };
|
|
92
|
+
}
|
|
93
|
+
|
|
79
94
|
async function tryMoveFile(srcFileName, destFileName) {
|
|
80
95
|
await mkdir(dirname(destFileName), { recursive: true });
|
|
81
96
|
try {
|
|
@@ -151,15 +166,19 @@ export function visualDiff({ updateGoldens = false, runSubset = false } = {}) {
|
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
const screenshotOpts = {
|
|
154
|
-
animations: 'disabled'
|
|
155
|
-
path: updateGoldens ? goldenFileName : screenshotFileName
|
|
169
|
+
animations: 'disabled'
|
|
156
170
|
};
|
|
157
171
|
|
|
158
172
|
if (payload.fullPage) screenshotOpts.fullPage = true;
|
|
159
173
|
if (payload.rect) screenshotOpts.clip = payload.rect;
|
|
160
174
|
|
|
161
|
-
|
|
162
|
-
|
|
175
|
+
async function takeScreenshot() {
|
|
176
|
+
const path = updateGoldens ? goldenFileName : screenshotFileName;
|
|
177
|
+
const page = session.browser.getPage(session.id);
|
|
178
|
+
return await page.screenshot({ path, ...screenshotOpts });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const screenshotFileBuffer = await takeScreenshot();
|
|
163
182
|
|
|
164
183
|
if (updateGoldens) {
|
|
165
184
|
return { pass: true };
|
|
@@ -167,73 +186,72 @@ export function visualDiff({ updateGoldens = false, runSubset = false } = {}) {
|
|
|
167
186
|
|
|
168
187
|
const rootLength = join(rootDir, PATHS.VDIFF_ROOT).length + 1;
|
|
169
188
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const goldenExists = await checkFileExists(goldenFileName);
|
|
182
|
-
if (!goldenExists) {
|
|
183
|
-
return { pass: false, message: 'No golden exists. Use the "--golden" CLI flag to re-run and re-generate goldens.' };
|
|
184
|
-
}
|
|
189
|
+
async function runCompareTest() {
|
|
190
|
+
const screenshotImage = PNG.sync.read(screenshotFileBuffer);
|
|
191
|
+
infoManager.set({
|
|
192
|
+
slowDuration: payload.slowDuration,
|
|
193
|
+
new: {
|
|
194
|
+
height: screenshotImage.height,
|
|
195
|
+
path: screenshotFileName.substring(rootLength),
|
|
196
|
+
width: screenshotImage.width
|
|
197
|
+
}
|
|
198
|
+
});
|
|
185
199
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
golden: {
|
|
190
|
-
height: goldenImage.height,
|
|
191
|
-
path: goldenFileName.substring(rootLength),
|
|
192
|
-
width: goldenImage.width
|
|
200
|
+
const goldenExists = await checkFileExists(goldenFileName);
|
|
201
|
+
if (!goldenExists) {
|
|
202
|
+
return { pass: false, message: 'No golden exists. Use the "--golden" CLI flag to re-run and re-generate goldens.' };
|
|
193
203
|
}
|
|
194
|
-
});
|
|
195
204
|
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
205
|
+
const goldenFileBuffer = await readFile(goldenFileName);
|
|
206
|
+
const goldenImage = PNG.sync.read(goldenFileBuffer);
|
|
207
|
+
infoManager.set({
|
|
208
|
+
golden: {
|
|
209
|
+
height: goldenImage.height,
|
|
210
|
+
path: goldenFileName.substring(rootLength),
|
|
211
|
+
width: goldenImage.width
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
if (screenshotImage.width === goldenImage.width && screenshotImage.height === goldenImage.height) {
|
|
216
|
+
const goldenSize = (await stat(goldenFileName)).size;
|
|
217
|
+
const screenshotSize = (await stat(screenshotFileName)).size;
|
|
218
|
+
if (goldenSize === screenshotSize && screenshotFileBuffer.equals(goldenFileBuffer)) {
|
|
219
|
+
const success = await tryMoveFile(screenshotFileName, passFileName);
|
|
220
|
+
if (!success) return { pass: false, message: 'Problem moving file to "pass" directory.' };
|
|
221
|
+
infoManager.set({
|
|
222
|
+
new: {
|
|
223
|
+
path: passFileName.substring(rootLength)
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return { pass: true };
|
|
227
|
+
}
|
|
209
228
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
pixelsDiff
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
229
|
+
const { diff, pixelsDiff } = getPixelsDiff(screenshotImage, goldenImage);
|
|
230
|
+
|
|
231
|
+
if (pixelsDiff !== 0) {
|
|
232
|
+
infoManager.set({
|
|
233
|
+
diff: `${screenshotFile.substring(rootLength)}-diff.png`,
|
|
234
|
+
pixelsDiff
|
|
235
|
+
});
|
|
236
|
+
await writeFile(`${screenshotFile}-diff.png`, PNG.sync.write(diff));
|
|
237
|
+
return { pass: false, message: `Image does not match golden. ${pixelsDiff} pixels are different.` };
|
|
238
|
+
} else {
|
|
239
|
+
infoManager.set({
|
|
240
|
+
golden: {
|
|
241
|
+
byteSize: goldenSize
|
|
242
|
+
},
|
|
243
|
+
new: {
|
|
244
|
+
byteSize: screenshotSize
|
|
245
|
+
},
|
|
246
|
+
pixelsDiff
|
|
247
|
+
});
|
|
248
|
+
return { pass: false, message: 'Image diff is clean but the images do not have the same bytes.' };
|
|
249
|
+
}
|
|
222
250
|
} else {
|
|
223
|
-
|
|
224
|
-
golden: {
|
|
225
|
-
byteSize: goldenSize
|
|
226
|
-
},
|
|
227
|
-
new: {
|
|
228
|
-
byteSize: screenshotSize
|
|
229
|
-
},
|
|
230
|
-
pixelsDiff
|
|
231
|
-
});
|
|
232
|
-
return { pass: false, message: 'Image diff is clean but the images do not have the same bytes.' };
|
|
251
|
+
return { resizeRequired: true };
|
|
233
252
|
}
|
|
234
|
-
} else {
|
|
235
|
-
return { resizeRequired: true };
|
|
236
253
|
}
|
|
254
|
+
return await runCompareTest();
|
|
237
255
|
} else if (command === 'brightspace-visual-diff-compare-resize') {
|
|
238
256
|
const screenshotImage = PNG.sync.read(await readFile(screenshotFileName));
|
|
239
257
|
const goldenImage = PNG.sync.read(await readFile(goldenFileName));
|
|
@@ -247,17 +265,14 @@ export function visualDiff({ updateGoldens = false, runSubset = false } = {}) {
|
|
|
247
265
|
|
|
248
266
|
let bestIndex = -1;
|
|
249
267
|
let bestDiffImage = null;
|
|
250
|
-
let
|
|
268
|
+
let bestPixelsDiff = Number.MAX_SAFE_INTEGER;
|
|
251
269
|
for (let i = 0; i < newScreenshots.length; i++) {
|
|
252
|
-
const
|
|
253
|
-
const currentPixelsDiff = pixelmatch(
|
|
254
|
-
newScreenshots[i].png.data, newGoldens[i].png.data, currentDiff.data, currentDiff.width, currentDiff.height, { diffMask: true, threshold: DEFAULT_TOLERANCE }
|
|
255
|
-
);
|
|
270
|
+
const { diff, pixelsDiff } = getPixelsDiff(newScreenshots[i].png, newGoldens[i].png);
|
|
256
271
|
|
|
257
|
-
if (
|
|
272
|
+
if (pixelsDiff < bestPixelsDiff) {
|
|
258
273
|
bestIndex = i;
|
|
259
|
-
bestDiffImage =
|
|
260
|
-
|
|
274
|
+
bestDiffImage = diff;
|
|
275
|
+
bestPixelsDiff = pixelsDiff;
|
|
261
276
|
}
|
|
262
277
|
}
|
|
263
278
|
|
|
@@ -274,10 +289,10 @@ export function visualDiff({ updateGoldens = false, runSubset = false } = {}) {
|
|
|
274
289
|
new: {
|
|
275
290
|
path: `${screenshotFile.substring(rootLength)}-resized-screenshot.png`
|
|
276
291
|
},
|
|
277
|
-
pixelsDiff
|
|
292
|
+
pixelsDiff: bestPixelsDiff
|
|
278
293
|
});
|
|
279
294
|
|
|
280
|
-
return { pass: false, message: `Images are not the same size. When resized, ${
|
|
295
|
+
return { pass: false, message: `Images are not the same size. When resized, ${bestPixelsDiff} pixels are different.` };
|
|
281
296
|
}
|
|
282
297
|
|
|
283
298
|
}
|