Skip to content

Commit

Permalink
Merge pull request #7395 from cjcenizal/feature/compare-screenshots-u…
Browse files Browse the repository at this point in the history
…tility

Add screenshot-comparison utility, to protect against visual regressions during CSS refactors.
  • Loading branch information
cjcenizal committed Jun 8, 2016
2 parents 5112880 + 9fa2e82 commit 207a481
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 24 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ target
.idea
*.iml
*.log
/test/output
/test/screenshots/diff
/test/screenshots/failure
/test/screenshots/session
/esvm
.htpasswd
.eslintcache
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
"makelogs": "makelogs",
"mocha": "mocha",
"mocha:debug": "mocha --debug-brk",
"sterilize": "grunt sterilize"
"sterilize": "grunt sterilize",
"compareScreenshots": "node utilities/compareScreenshots"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -171,6 +172,7 @@
"gruntify-eslint": "1.0.1",
"html-entities": "1.1.3",
"husky": "0.8.1",
"image-diff": "1.6.0",
"intern": "3.0.1",
"istanbul-instrumenter-loader": "0.1.3",
"karma": "0.13.9",
Expand Down
File renamed without changes.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/screenshots/baseline/screenshot-PieChart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/screenshots/baseline/screenshot-TileMap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 25 additions & 22 deletions test/support/pages/common.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { config, defaultTryTimeout, defaultFindTimeout, remote, shieldPage } from '../';
import fs from 'fs';
import mkdirp from 'mkdirp';
import { promisify } from 'bluebird';

const mkdirpAsync = promisify(mkdirp);
const writeFileAsync = promisify(fs.writeFile);

export default (function () {
var Promise = require('bluebird');
var moment = require('moment');
var testSubjSelector = require('@spalger/test-subj-selector');
var getUrl = require('../../utils/get_url');
var fs = require('fs');
var _ = require('lodash');
var parse = require('url').parse;
var format = require('url').format;
Expand Down Expand Up @@ -244,34 +249,32 @@ export default (function () {
.then(function () { self.debug('... sleep(' + sleepMilliseconds + ') end'); });
},

handleError: function (testObj) {
var self = this;
var testName = (testObj.parent) ? [testObj.parent.name, testObj.name].join('_') : testObj.name;

return function (reason) {
var now = Date.now();
var filename = ['failure', now, testName].join('_') + '.png';
handleError(testObj) {
const testName = (testObj.parent) ? [testObj.parent.name, testObj.name].join('_') : testObj.name;
return reason => {
const now = Date.now();
const fileName = `failure_${now}_${testName}.png`;

return self.saveScreenshot(filename)
return this.saveScreenshot(fileName, true)
.finally(function () {
throw reason;
});
};
},

saveScreenshot: function saveScreenshot(filename) {
var self = this;
var outDir = path.resolve('test', 'output');

return self.remote.takeScreenshot()
.then(function writeScreenshot(data) {
var filepath = path.resolve(outDir, filename);
self.debug('Taking screenshot "' + filepath + '"');
fs.writeFileSync(filepath, data);
})
.catch(function (err) {
self.log('SCREENSHOT FAILED: ' + err);
});
async saveScreenshot(fileName, isFailure = false) {
try {
const directoryName = isFailure ? 'failure' : 'session';
const directoryPath = path.resolve(`test/screenshots/${directoryName}`);
const filePath = path.resolve(directoryPath, fileName);
this.debug(`Taking screenshot "${filePath}"`);

const screenshot = await this.remote.takeScreenshot();
await mkdirpAsync(directoryPath);
await writeFileAsync(filePath, screenshot);
} catch (err) {
this.log(`SCREENSHOT FAILED: ${err}`);
}
},

findTestSubject: function findTestSubject(selector) {
Expand Down
43 changes: 43 additions & 0 deletions utilities/compareScreenshots.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

const fs = require('fs');
const path = require('path');
const imageDiff = require('image-diff');
const mkdirp = require('mkdirp');

function compareScreenshots() {
const SCREENSHOTS_DIR = 'test/screenshots';
const BASELINE_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'baseline');
const DIFF_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'diff');
const SESSION_SCREENSHOTS_DIR = path.resolve(SCREENSHOTS_DIR, 'session');

// We don't need to create the baseline dir because it's committed.
mkdirp.sync(DIFF_SCREENSHOTS_DIR);
mkdirp.sync(SESSION_SCREENSHOTS_DIR);

fs.readdir(SESSION_SCREENSHOTS_DIR, (readDirError, files) => {
const screenshots = files.filter(file => file.indexOf('.png') !== -1);

screenshots.forEach(screenshot => {
const sessionImagePath = path.resolve(SESSION_SCREENSHOTS_DIR, screenshot);
const baselineImagePath = path.resolve(BASELINE_SCREENSHOTS_DIR, screenshot);
const diffImagePath = path.resolve(DIFF_SCREENSHOTS_DIR, screenshot);

imageDiff.getFullResult({
actualImage: sessionImagePath,
expectedImage: baselineImagePath,
diffImage: diffImagePath,
shadow: true,
}, (comparisonError, result) => {
if (comparisonError) {
throw comparisonError;
}

const change = result.percentage;
const changePercentage = (change * 100).toFixed(2);
console.log(`${screenshot} has changed by ${changePercentage}%`);
});
});
});
}

compareScreenshots();

0 comments on commit 207a481

Please sign in to comment.