From 919865c1035f11e95789e68f0817783849b0f759 Mon Sep 17 00:00:00 2001 From: adrianjost <22987140+adrianjost@users.noreply.github.com> Date: Wed, 15 Apr 2020 21:15:57 +0200 Subject: [PATCH] feat(options): add option to pass on size missmatch if the option `allowSizeMismatch` is set, a build will not allways fail on images with different sizes. Missing or Added Pixel will be counted as a missmatch and respected by the set threshold. Related #83, #85 --- README.md | 1 + __tests__/diff-snapshot.spec.js | 38 ++++++++++++++++++++ src/diff-snapshot.js | 62 +++++++++++++++++++++++++-------- 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5635f90..f895c6e 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ See [the examples](./examples/README.md) for more detailed usage or read about a * `blur`: (default `0`) Applies Gaussian Blur on compared images, accepts radius in pixels as value. Useful when you have noise after scaling images per different resolutions on your target website, usually setting its value to 1-2 should be enough to solve that problem. * `runInProcess`: (default `false`) Runs the diff in process without spawning a child process. * `dumpDiffToConsole`: (default `false`) Will output base64 string of a diff image to console in case of failed tests (in addition to creating a diff image). This string can be copy-pasted to a browser address string to preview the diff for a failed test. +* `allowSizeMismatch`: (default `false`) If set to true, the build will not fail when the screenshots to compare have different sizes. ```javascript it('should demonstrate this matcher`s usage with a custom pixelmatch config', () => { diff --git a/__tests__/diff-snapshot.spec.js b/__tests__/diff-snapshot.spec.js index 7270668..59d3501 100644 --- a/__tests__/diff-snapshot.spec.js +++ b/__tests__/diff-snapshot.spec.js @@ -244,6 +244,44 @@ describe('diff-snapshot', () => { expect(result.diffRatio).toBe(0.025); }); + it('should pass with allowSizeMismatch: true if image passed is a different size but <= failureThreshold pixel', () => { + const diffImageToSnapshot = setupTest({ snapshotExists: true, pixelmatchResult: 250 }); + const result = diffImageToSnapshot({ + receivedImageBuffer: mockBigImageBuffer, + snapshotIdentifier: mockSnapshotIdentifier, + snapshotsDir: mockSnapshotsDir, + diffDir: mockDiffDir, + updateSnapshot: false, + failureThreshold: 250, + failureThresholdType: 'pixel', + allowSizeMismatch: true, + }); + + expect(result.pass).toBe(true); + expect(result.diffSize).toBe(true); + expect(result.diffPixelCount).toBe(250); + expect(result.diffRatio).toBe(0.1 / 9); + }); + + it('should fail with allowSizeMismatch: true if image passed is a different size but > failureThreshold pixel', () => { + const diffImageToSnapshot = setupTest({ snapshotExists: true, pixelmatchResult: 250 }); + const result = diffImageToSnapshot({ + receivedImageBuffer: mockBigImageBuffer, + snapshotIdentifier: mockSnapshotIdentifier, + snapshotsDir: mockSnapshotsDir, + diffDir: mockDiffDir, + updateSnapshot: false, + failureThreshold: 0, + failureThresholdType: 'pixel', + allowSizeMismatch: true, + }); + + expect(result.pass).toBe(false); + expect(result.diffSize).toBe(true); + expect(result.diffPixelCount).toBe(250); + expect(result.diffRatio).toBe(0.1 / 9); + }); + it('should pass = image checksums', () => { const diffImageToSnapshot = setupTest({ snapshotExists: true, pixelmatchResult: 0 }); const result = diffImageToSnapshot({ diff --git a/src/diff-snapshot.js b/src/diff-snapshot.js index 245eaf9..fd83fcb 100644 --- a/src/diff-snapshot.js +++ b/src/diff-snapshot.js @@ -83,6 +83,38 @@ const shouldUpdate = ({ pass, updateSnapshot, updatePassedSnapshot }) => ( (!pass && updateSnapshot) || (pass && updatePassedSnapshot) ); +const shouldFail = ({ + totalPixels, + diffPixelCount, + hasSizeMismatch, + allowSizeMismatch, + failureThresholdType, + failureThreshold, +}) => { + let pass = false; + let diffSize = false; + const diffRatio = diffPixelCount / totalPixels; + if (hasSizeMismatch) { + // do not fail if allowSizeMismatch is set + pass = allowSizeMismatch; + diffSize = true; + } + if (!diffSize || pass === true) { + if (failureThresholdType === 'pixel') { + pass = diffPixelCount <= failureThreshold; + } else if (failureThresholdType === 'percent') { + pass = diffRatio <= failureThreshold; + } else { + throw new Error(`Unknown failureThresholdType: ${failureThresholdType}. Valid options are "pixel" or "percent".`); + } + } + return { + pass, + diffSize, + diffRatio, + }; +}; + function diffImageToSnapshot(options) { const { receivedImageBuffer, @@ -96,6 +128,7 @@ function diffImageToSnapshot(options) { failureThreshold, failureThresholdType, blur, + allowSizeMismatch = false, } = options; let result = {}; @@ -140,9 +173,6 @@ function diffImageToSnapshot(options) { const diffImage = new PNG({ width: imageWidth, height: imageHeight }); - let pass = false; - let diffSize = false; - let diffRatio = 0; let diffPixelCount = 0; diffPixelCount = pixelmatch( @@ -155,18 +185,19 @@ function diffImageToSnapshot(options) { ); const totalPixels = imageWidth * imageHeight; - diffRatio = diffPixelCount / totalPixels; - // Always fail test on image size mismatch - if (hasSizeMismatch) { - pass = false; - diffSize = true; - } else if (failureThresholdType === 'pixel') { - pass = diffPixelCount <= failureThreshold; - } else if (failureThresholdType === 'percent') { - pass = diffRatio <= failureThreshold; - } else { - throw new Error(`Unknown failureThresholdType: ${failureThresholdType}. Valid options are "pixel" or "percent".`); - } + + const { + pass, + diffSize, + diffRatio, + } = shouldFail({ + totalPixels, + diffPixelCount, + hasSizeMismatch, + allowSizeMismatch, + failureThresholdType, + failureThreshold, + }); if (isFailure({ pass, updateSnapshot })) { mkdirp.sync(diffDir); @@ -213,6 +244,7 @@ function diffImageToSnapshot(options) { } else { result = { pass, + diffSize, diffRatio, diffPixelCount, diffOutputPath,