Skip to content

Commit 109d3b0

Browse files
authored
feature(diff): getDiff even on dimensions missmatch (#114)
1 parent c0016f5 commit 109d3b0

File tree

3 files changed

+96
-34
lines changed

3 files changed

+96
-34
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ POSTGRES_DB=vrt_db_dev
1818

1919
# features
2020
AUTO_APPROVE_BASED_ON_HISTORY=true
21+
ALLOW_DIFF_DIMENSIONS=true

src/test-runs/test-runs.service.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ describe('TestRunsService', () => {
604604
});
605605

606606
it('diff image dimensions mismatch', async () => {
607+
delete process.env.ALLOW_DIFF_DIMENSIONS;
607608
const baseline = new PNG({
608609
width: 10,
609610
height: 10,
@@ -625,6 +626,52 @@ describe('TestRunsService', () => {
625626
});
626627
});
627628

629+
it('diff image dimensions mismatch ALLOWED', async () => {
630+
process.env.ALLOW_DIFF_DIMENSIONS = 'true';
631+
const baseline = new PNG({
632+
width: 20,
633+
height: 10,
634+
});
635+
const image = new PNG({
636+
width: 10,
637+
height: 20,
638+
});
639+
const diffName = 'diff name';
640+
const saveImageMock = jest.fn().mockReturnValueOnce(diffName);
641+
mocked(Pixelmatch).mockReturnValueOnce(200);
642+
service = await initService({ saveImageMock });
643+
644+
const result = service.getDiff(baseline, image, baseTestRun);
645+
646+
expect(mocked(Pixelmatch)).toHaveBeenCalledWith(
647+
new PNG({
648+
width: 20,
649+
height: 20,
650+
}).data,
651+
new PNG({
652+
width: 20,
653+
height: 20,
654+
}).data,
655+
new PNG({
656+
width: 20,
657+
height: 20,
658+
}).data,
659+
20,
660+
20,
661+
{
662+
includeAA: true,
663+
}
664+
);
665+
expect(saveImageMock).toHaveBeenCalledTimes(1);
666+
expect(result).toStrictEqual({
667+
status: TestStatus.unresolved,
668+
diffName,
669+
pixelMisMatchCount: 200,
670+
diffPercent: 50,
671+
isSameDimension: false,
672+
});
673+
});
674+
628675
it('diff not found', async () => {
629676
const baseline = new PNG({
630677
width: 10,

src/test-runs/test-runs.service.ts

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,15 @@ export class TestRunsService {
271271
});
272272
}
273273

274+
private scaleImageToSize(image: PNG, width: number, height: number): PNG {
275+
if (width > image.width || height > image.height) {
276+
const preparedImage = new PNG({ width, height, fill: true });
277+
PNG.bitblt(image, preparedImage, 0, 0, image.width, image.height);
278+
return preparedImage;
279+
}
280+
return image;
281+
}
282+
274283
getDiff(baseline: PNG, image: PNG, testRun: TestRun): DiffResult {
275284
const result: DiffResult = {
276285
status: undefined,
@@ -280,42 +289,47 @@ export class TestRunsService {
280289
isSameDimension: undefined,
281290
};
282291

283-
if (baseline) {
284-
result.isSameDimension = baseline.width === image.width && baseline.height === image.height;
285-
286-
if (result.isSameDimension) {
287-
const diff = new PNG({
288-
width: baseline.width,
289-
height: baseline.height,
290-
});
291-
292-
const ignoreAreas = this.getIgnoteAreas(testRun);
293-
// compare
294-
result.pixelMisMatchCount = Pixelmatch(
295-
this.applyIgnoreAreas(baseline, ignoreAreas),
296-
this.applyIgnoreAreas(image, ignoreAreas),
297-
diff.data,
298-
baseline.width,
299-
baseline.height,
300-
{
301-
includeAA: true,
302-
}
303-
);
304-
result.diffPercent = (result.pixelMisMatchCount * 100) / (image.width * image.height);
305-
306-
if (result.diffPercent > testRun.diffTollerancePercent) {
307-
// save diff
308-
result.diffName = this.staticService.saveImage('diff', PNG.sync.write(diff));
309-
result.status = TestStatus.unresolved;
310-
} else {
311-
result.status = TestStatus.ok;
312-
}
313-
} else {
314-
// diff dimensions
315-
result.status = TestStatus.unresolved;
316-
}
292+
if (!baseline) {
293+
// no baseline
294+
return result;
295+
}
296+
297+
result.isSameDimension = baseline.width === image.width && baseline.height === image.height;
298+
299+
if (!result.isSameDimension && !process.env.ALLOW_DIFF_DIMENSIONS) {
300+
// diff dimensions
301+
result.status = TestStatus.unresolved;
302+
return result;
317303
}
304+
// scale image to max size
305+
const maxWidth = Math.max(baseline.width, image.width);
306+
const maxHeight = Math.max(baseline.height, image.height);
307+
const scaledBaseline = this.scaleImageToSize(baseline, maxWidth, maxHeight);
308+
const scaledImage = this.scaleImageToSize(image, maxWidth, maxHeight);
309+
310+
// apply ignore areas
311+
const ignoreAreas = this.getIgnoteAreas(testRun);
312+
const baselineData = this.applyIgnoreAreas(scaledBaseline, ignoreAreas);
313+
const imageData = this.applyIgnoreAreas(scaledImage, ignoreAreas);
314+
315+
// compare
316+
const diff = new PNG({
317+
width: maxWidth,
318+
height: maxHeight,
319+
});
320+
result.pixelMisMatchCount = Pixelmatch(baselineData, imageData, diff.data, maxWidth, maxHeight, {
321+
includeAA: true,
322+
});
323+
result.diffPercent = (result.pixelMisMatchCount * 100) / (scaledImage.width * scaledImage.height);
318324

325+
// process result
326+
if (result.diffPercent > testRun.diffTollerancePercent) {
327+
// save diff
328+
result.diffName = this.staticService.saveImage('diff', PNG.sync.write(diff));
329+
result.status = TestStatus.unresolved;
330+
} else {
331+
result.status = TestStatus.ok;
332+
}
319333
return result;
320334
}
321335

0 commit comments

Comments
 (0)