diff --git a/lib/image-diff.js b/lib/image-diff.js index 1c6441e..1dce48d 100644 --- a/lib/image-diff.js +++ b/lib/image-diff.js @@ -73,7 +73,7 @@ ImageDiff.createDiff = function (options, cb) { // DEV: According to http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=17284 // DEV: These values are the total square root mean square (RMSE) pixel difference across all pixels and its percentage // TODO: This is not very multi-lengual =( - var resultInfo = stderr.match(/all: (\d+\.?\d*) \((\d+\.?\d*)\)/); + var resultInfo = stderr.match(/all: (\d+\.?\d*) \((\d+\.?\d*e?\-?\d*)\)/); // If there was no resultInfo, throw a fit if (!resultInfo) { @@ -81,8 +81,12 @@ ImageDiff.createDiff = function (options, cb) { } // Callback with pass/fail - var totalDifference = resultInfo[1]; - return cb(null, totalDifference === '0'); + var percentDifference = parseFloat(resultInfo[2], 10); + var threshold = options.threshold || 0; + if (isNaN(percentDifference)) { + return cb(new Error('Attempted to parse percentage difference from `image-diff\'s stderr` but got `NaN` from "' + resultInfo[2] + '"')); + } + return cb(null, percentDifference <= threshold); }); }; ImageDiff.prototype = { @@ -91,6 +95,7 @@ ImageDiff.prototype = { var actualPath = options.actualImage; var expectedPath = options.expectedImage; var diffPath = options.diffImage; + var threshold = options.threshold; // Assert our options are passed in if (!actualPath) { @@ -187,7 +192,8 @@ ImageDiff.prototype = { ImageDiff.createDiff({ actualPath: actualTmpPath, expectedPath: expectedTmpPath, - diffPath: diffPath + diffPath: diffPath, + threshold: threshold }, function saveResult (err, _imagesAreSame) { imagesAreSame = _imagesAreSame; cb(err); diff --git a/test/image-diff_test.js b/test/image-diff_test.js index 5dc829f..8032728 100644 --- a/test/image-diff_test.js +++ b/test/image-diff_test.js @@ -23,6 +23,7 @@ rimraf.sync(__dirname + '/actual-files'); // DEV: This is re-used at end to make sure we clean up tmp files var tmpDir = os.tmpdir ? os.tmpdir() : '/tmp'; before(function () { + this.timeout(5000); this.expectedTmpFiles = fs.readdirSync(tmpDir); }); @@ -104,6 +105,44 @@ describe('image-diff', function () { assert.deepEqual(this.actualPixels, this.expectedPixels); }); }); + + describe('diffing different images over a threshold', function () { + runImageDiff({ + actualImage: __dirname + '/test-files/checkerboard.png', + expectedImage: __dirname + '/test-files/white.png', + diffImage: __dirname + '/actual-files/over-threshold.png', + threshold: 0.2 + }); + imageUtils.loadActual('over-threshold.png'); + imageUtils.loadExpected('different.png'); + + it('asserts images are different', function () { + assert.strictEqual(this.imagesAreSame, false); + }); + + it('writes a highlighted image diff to disk', function () { + assert.deepEqual(this.actualPixels, this.expectedPixels); + }); + }); + + describe('diffing different images under a threshold', function () { + runImageDiff({ + actualImage: __dirname + '/test-files/checkerboard.png', + expectedImage: __dirname + '/test-files/white.png', + diffImage: __dirname + '/actual-files/under-threshold.png', + threshold: 0.9 + }); + imageUtils.loadActual('under-threshold.png'); + imageUtils.loadExpected('different.png'); + + it('asserts images are similar enough', function () { + assert.strictEqual(this.imagesAreSame, true); + }); + + it('writes a highlighted image diff to disk', function () { + assert.deepEqual(this.actualPixels, this.expectedPixels); + }); + }); }); describe('After running the tests', function () {