├── .DS_Store ├── .gitignore ├── README.md ├── config.js ├── config.test.js ├── functions.js ├── package.json ├── screenshots └── .DS_Store └── snapandcompare.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/craigtaub/snapandcompare/13b60adfa9e3e2ff7717d3519a007887025088af/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | screenshots 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Snap And Compare 2 | 3 | SnapAndCompare is an easy to use screenshot comparison tool used for CSS Visual Regression Testing built using NodeJS. 4 | 5 | NO CODE...JUST CONFIGS. 6 | 7 | It can compare against a single environment or dual and will produce visuals and equality stats on image comparisons. 8 | 9 | Run in standalone mode or if you give a `watchFile` will run everytime that is updated/saved (useful for SASS development). 10 | 11 | ## Examples: 12 | 13 | ![Master image](http://i866.photobucket.com/albums/ab227/craigtaub/about_zpsec20c088.jpg "Master image") 14 | 15 | ## Setup: 16 | 17 | ### Download and install NodeJS 18 | http://nodejs.org/download/ 19 | 20 | ### Download and install GraphicMagick (gm) 21 | brew install graphicsmagick 22 | 23 | Or if that doesn't work install from source (http://www.graphicsmagick.org/download.html). 24 | 25 | ./configure 26 | make 27 | sudo make install 28 | 29 | ### Download app dependencies 30 | npm install 31 | 32 | ## Usage: 33 | Update the `config.js` file to hold the `masterUrl` and `diffUrl` you need (they are often the same but not always) 34 | Run (first builds initial snapshot, second builds diff and compares): 35 | 36 | node snapandcompare.js 37 | node snapandcompare.js 38 | 39 | ## How does the logic work: 40 | 41 | ### Without a `watchFile`: 42 | 43 | First run : 44 | For all Breakpoints will check if a master image exists, if not will create one. 45 | 46 | Second run: 47 | For all Breakpoints will find the master image, create a new .diff image and run a comparison on the two producing a .fail image and flagging up if the images differ. 48 | 49 | After that: 50 | For each Breakpoint it will either compare against the diff or download a new Master image (depending on what already exists in `/screenshots`). 51 | 52 | ### With a `watchFile`: 53 | It will continually run on save of the file. It will flag up the status of each Breakpoint as PASS or FAIL. 54 | 55 | First run: 56 | On save of `watchFile` it will create the Master files after that will run the comparison evertime it detects a change. 57 | 58 | ## Testing: 59 | - Swap the config files and run the program to test. `('./config')` for `('./config.test')`. 60 | 61 | ## Research: 62 | - found here https://gist.github.com/craigtaub/8450909416482d594058ce88dbbeaf08 63 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | breakpoints : [400, 600, 900, 1300], 3 | screens : "screenshots/bp-", 4 | siteType : "", 5 | cookies : [{ 6 | "domain": "", 7 | "name": "", 8 | "value": "" 9 | }], 10 | masterUrl : "https://www.google.co.uk", 11 | diffUrl : "https://www.google.es", 12 | watchFile : "" 13 | }; 14 | 15 | module.exports = config; 16 | -------------------------------------------------------------------------------- /config.test.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | bps : [400, 600, 1000, 1300], 3 | screens : "screenshots/bp-", 4 | siteType : "html", 5 | cookies : [{ 6 | name: "foo", 7 | value: "bar", 8 | domain: "localhost" 9 | }], 10 | masterUrl : '
Hello World
Whats new?
', 11 | diffUrl : '
Hello World
Whats new?
', 12 | watchFile : "" 13 | } 14 | 15 | module.exports = config; 16 | -------------------------------------------------------------------------------- /functions.js: -------------------------------------------------------------------------------- 1 | var config = require('./config'), 2 | colors = require('colors'), 3 | gm = require('gm'); //GraphicMagick 4 | 5 | var functions = { 6 | runComparison : function(item, err) { 7 | //compare Master with diff 8 | gm.compare(config.screens+item+".jpg", config.screens+item+".diff.jpg", function (err, isEqual, equality, raw) { 9 | if (err) throw err; 10 | if (equality > 0) { 11 | //images not the same, FAIL. 12 | console.log("FAILED Diff bp:". red , item); 13 | console.log("FAILED equality rate:" . red , equality , "%" . red); 14 | //create .fail 15 | functions.createFail(item); 16 | } else { 17 | //no change, PASS. 18 | console.log("PASSED Diff bp:" . green , item); 19 | } 20 | }); 21 | }, 22 | createFail : function(item) { 23 | var options = { 24 | highlightColor: 'yellow', 25 | file: config.screens+item+'.fail.jpg' 26 | }; 27 | //will overwrite current .fail if necessary. 28 | gm.compare(config.screens+item+".jpg", config.screens+item+".diff.jpg", options, function (err) { 29 | if (err) throw err; 30 | }); 31 | } 32 | } 33 | 34 | module.exports = functions; 35 | 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "snapandcompare", 3 | "version": "1.0.1", 4 | "description": "Screenshot comparison tool used for CSS regression testing.", 5 | "main": "./snapandcompare.js", 6 | "keywords": [ 7 | "util", 8 | "server", 9 | "client", 10 | "browser", 11 | "canvas", 12 | "diff", 13 | "imagediff" 14 | ], 15 | "author": "Craig Taub ", 16 | "license": "ISC", 17 | "repository": { 18 | "type": "git", 19 | "url": "http://github.com/craigtaub/snapandcompare.git" 20 | }, 21 | "dependencies": { 22 | "webshot": "~0.7", 23 | "gm": "~1.13", 24 | "colors": "~0.6" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /screenshots/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/craigtaub/snapandcompare/13b60adfa9e3e2ff7717d3519a007887025088af/screenshots/.DS_Store -------------------------------------------------------------------------------- /snapandcompare.js: -------------------------------------------------------------------------------- 1 | //node modules 2 | var config = require('./config'), 3 | functions = require('./functions'), 4 | webshot = require('webshot'), 5 | colors = require('colors'), 6 | gm = require('gm'), //GraphicMagick 7 | fs = require('fs'); //filesystem 8 | 9 | if(config.watchFile) { 10 | console.log('Watching ' . green , config.watchFile . yellow ); 11 | fs.watch(config.watchFile, function() { 12 | console.log('Change detected, run app.' . green); 13 | //Bind to changes in watchFile 14 | runApplication(); 15 | }); 16 | } else { 17 | runApplication(); 18 | } 19 | 20 | function runApplication() { 21 | //foreach breakpoint 22 | config.breakpoints.forEach(function(item) { 23 | //set breakpoint options 24 | var options = { 25 | screenSize: { 26 | width: item, height: 1080 27 | }, 28 | siteType: config.siteType, 29 | cookies: config.cookies 30 | }; 31 | fs.exists(config.screens+item+".jpg", function(exists) { 32 | if (exists) { 33 | //master exists. Create snapshot .diff 34 | webshot(config.diffUrl, config.screens+item+'.diff.jpg', options, function(err) { 35 | //screenshot now saved .diff...will overwrite if necessary. 36 | functions.runComparison(item, err); 37 | }); 38 | } else { 39 | //master doesnt exist. Create snapshot master. 40 | webshot(config.masterUrl, config.screens+item+'.jpg', options, function(err) { 41 | //master screenshot now stored. 42 | console.log("MASTER Stored bp:" . green , item); 43 | }); 44 | } 45 | }); 46 | }); 47 | } 48 | --------------------------------------------------------------------------------