Comparing version 1.0.11 to 1.0.12
Changelog | ||
========= | ||
v1.0.11 - Merged PR #19 to add cucumber support | ||
v1.0.12 - Added baseline option for auto saving not found images #21 (01/09/2016 | ||
v1.0.11 - Merged PR #19 to add cucumber support (credit to wswebcreation) | ||
v1.0.10 - Fix not resolving path to framework during initialisation #14 | ||
@@ -6,0 +8,0 @@ - Update dependencies |
180
index.js
@@ -23,2 +23,3 @@ 'use strict'; | ||
* @property {string} basePath | ||
* @property {bool} baseline | ||
* @property {int} width | ||
@@ -40,2 +41,4 @@ * @property {int} height | ||
this.baseline = options.baseline || false; | ||
this.width = options.width || 1280; | ||
@@ -59,2 +62,3 @@ this.height = options.height || 1024; | ||
assert.ok(this.capabilities.browserName, 'Browser name is undefined.'); | ||
this.browserName = this.capabilities.browserName.toLowerCase(); | ||
// Require PixDiff matchers for jasmine(2)/mocha | ||
@@ -64,6 +68,8 @@ if (data.framework !== 'custom') { | ||
} | ||
return browser.driver.executeScript('return window.devicePixelRatio;'); | ||
if (!this.isFirefox()) { | ||
return this.getPixelDeviceRatio(); | ||
} | ||
}.bind(this)) | ||
.then(function (ratio) { | ||
this.devicePixelRatio = Math.floor(ratio); | ||
this.devicePixelRatio = ratio; | ||
}.bind(this)); | ||
@@ -86,5 +92,5 @@ } | ||
Object.keys(optionsB).forEach(function (option) { | ||
if (!optionsA.hasOwnProperty(option)) { | ||
optionsA[option] = optionsB[option]; | ||
Object.keys(optionsB).forEach(function (value) { | ||
if (!optionsA.hasOwnProperty(value)) { | ||
optionsA[value] = optionsB[value]; | ||
} | ||
@@ -107,3 +113,3 @@ }); | ||
'tag': camelCase(description), | ||
'browserName': this.capabilities.browserName, | ||
'browserName': this.browserName, | ||
'width': this.width, | ||
@@ -115,4 +121,4 @@ 'height': this.height | ||
Object.keys(defaults).forEach(function (option) { | ||
formatString = formatString.replace('{' + option + '}', defaults[option]); | ||
Object.keys(defaults).forEach(function (value) { | ||
formatString = formatString.replace('{' + value + '}', defaults[value]); | ||
}); | ||
@@ -123,2 +129,119 @@ return formatString + '.png'; | ||
/** | ||
* Check if browser is firefox | ||
* | ||
* @method isFirefox | ||
* @return {boolean} | ||
* @private | ||
*/ | ||
isFirefox: function () { | ||
return this.browserName === 'firefox'; | ||
}, | ||
/** | ||
* Check if browser is internet explorer | ||
* | ||
* @method isFirefox | ||
* @return {boolean} | ||
* @private | ||
*/ | ||
isInternetExplorer: function () { | ||
return this.browserName === 'internet explorer'; | ||
}, | ||
/** | ||
* Return the device pixel ratio | ||
* | ||
* @method getPixelDeviceRatio | ||
* @return {integer} | ||
* @private | ||
*/ | ||
getPixelDeviceRatio: function () { | ||
return this.flow.execute(function () { | ||
return browser.executeScript('return window.devicePixelRatio;') | ||
.then(function (devicePixelRatio) { | ||
return Math.floor(devicePixelRatio); | ||
}.bind(this)); | ||
}.bind(this)); | ||
}, | ||
/** | ||
* Get the position of the element | ||
* Firefox and IE make a screenshot of the complete page, not of the visbile part. The rest of the browsers make a | ||
* screenshot of the visible part | ||
* | ||
* @method getElementPosition | ||
* @param {promise} element | ||
* @return {promise} | ||
* @private | ||
*/ | ||
getElementPosition: function (element) { | ||
if (this.isFirefox() || this.isInternetExplorer()) { | ||
return this.getElementPositionTopPage(element); | ||
} | ||
return this.getElementPositionTopWindow(element); | ||
}, | ||
/** | ||
* Get the position of a given element according to the TOP of the PAGE | ||
* | ||
* @method getElementPositionTopPage | ||
* @param {promise} element | ||
* @returns {promise} | ||
* @private | ||
*/ | ||
getElementPositionTopPage: function (element) { | ||
return element.getLocation().then(function (point) { | ||
return { | ||
x: point.x, | ||
y: point.y | ||
}; | ||
}); | ||
}, | ||
/** | ||
* Get the position of a given element according to the TOP of the WINDOW | ||
* | ||
* @method getElementPositionTopWindow | ||
* @param {promise} element | ||
* @returns {promise} | ||
* @private | ||
*/ | ||
getElementPositionTopWindow: function (element) { | ||
return browser.executeScript('return arguments[0].getBoundingClientRect();', element.getWebElement()) | ||
.then(function (position) { | ||
return { | ||
x: position.left, | ||
y: position.top | ||
}; | ||
}); | ||
}, | ||
/** | ||
* Checks if image exists as baseline | ||
* | ||
* @method checkImageExists | ||
* @param {string} tag | ||
* @return {promise} | ||
* @private | ||
*/ | ||
checkImageExists: function (tag) { | ||
var deferred = protractor.promise.defer(); | ||
fs.access(path.join(this.basePath, this.format(this.formatString, tag)), fs.F_OK, function (err) { | ||
if (err) { | ||
if (!this.baseline) { | ||
deferred.reject(new Error(err.message)); | ||
} | ||
else { | ||
deferred.reject(new Error('Image not found, saving current image as new baseline.')); | ||
} | ||
} else { | ||
deferred.fulfill(); | ||
} | ||
}.bind(this)); | ||
return deferred.promise; | ||
}, | ||
/** | ||
* Saves an image of the screen | ||
@@ -164,4 +287,4 @@ * | ||
size = elementSize; | ||
return element.getLocation(); | ||
}) | ||
return this.getElementPosition(element); | ||
}.bind(this)) | ||
.then(function (point) { | ||
@@ -202,3 +325,14 @@ rect = {height: size.height, width: size.width, x: Math.floor(point.x), y: Math.floor(point.y)}; | ||
return this.flow.execute(function () { | ||
return browser.takeScreenshot() | ||
return this.checkImageExists(tag) | ||
.catch(function (err) { | ||
if (this.baseline) { | ||
this.saveScreen(tag); | ||
} | ||
else { | ||
throw err; | ||
} | ||
}.bind(this)) | ||
.then(function () { | ||
return browser.takeScreenshot(); | ||
}) | ||
.then(function (image) { | ||
@@ -239,7 +373,18 @@ tag = this.format(this.formatString, tag); | ||
return this.flow.execute(function () { | ||
return element.getSize() | ||
return this.checkImageExists(tag) | ||
.catch(function (err) { | ||
if (this.baseline) { | ||
this.saveRegion(element, tag); | ||
} | ||
else { | ||
throw err; | ||
} | ||
}.bind(this)) | ||
.then(function () { | ||
return element.getSize(); | ||
}) | ||
.then(function (elementSize) { | ||
size = elementSize; | ||
return element.getLocation(); | ||
}) | ||
return this.getElementPosition(element); | ||
}.bind(this)) | ||
.then(function (point) { | ||
@@ -250,2 +395,7 @@ rect = {height: size.height, width: size.width, x: Math.floor(point.x), y: Math.floor(point.y)}; | ||
.then(function (image) { | ||
if (this.devicePixelRatio > 1) { | ||
Object.keys(rect).forEach(function (item) { | ||
rect[item] *= this.devicePixelRatio; | ||
}.bind(this)); | ||
} | ||
tag = this.format(this.formatString, tag); | ||
@@ -268,2 +418,2 @@ defaults = { | ||
module.exports = PixDiff; | ||
module.exports = PixDiff; |
{ | ||
"name": "pix-diff", | ||
"version": "1.0.11", | ||
"version": "1.0.12", | ||
"description": "Protractor plugin for image comparison", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -127,2 +127,3 @@ Pix-Diff | ||
* ```basePath``` Defines the path to the reference images that are to be compared. | ||
* ```baseline``` Toggles saving the screen when not found in reference images (default: false) | ||
* ```width``` Browser width (default: 1280) | ||
@@ -143,2 +144,6 @@ * ```height``` Browser height (default: 1024) | ||
####Different webdriver implementation | ||
There is a difference in the webdriver implementation in taking screenshots. Firefox and Internet Explorer (not tested Edge yet) take a screenshot of the complete page, even if the page needs to be scrolled. Chrome and Safari only take a screenshot of the visible portion of the page. | ||
Keep this in mind when comparing screenshots of screens with each other. | ||
## Conventions | ||
@@ -145,0 +150,0 @@ There are directory and naming conventions that must be met. |
@@ -71,3 +71,3 @@ 'use strict'; | ||
return browser.pixDiff.checkScreen('imagenotexst', {threshold: 1}) | ||
return browser.pixDiff.checkScreen('imageNotExist', {threshold: 1}) | ||
.then(function () { | ||
@@ -77,3 +77,2 @@ fail('must not do a comparison.'); | ||
.catch(function () { | ||
// good | ||
errorThrown = true; | ||
@@ -80,0 +79,0 @@ }) |
@@ -7,4 +7,6 @@ 'use strict'; | ||
describe('Pix-Diff', function() { | ||
describe('Pix-Diff', function () { | ||
var browserName = browser.browserName; | ||
beforeEach(function () { | ||
@@ -14,3 +16,3 @@ browser.get(browser.baseUrl); | ||
describe('mathod matchers', function() { | ||
describe('method matchers', function () { | ||
@@ -29,3 +31,3 @@ beforeEach(function () { | ||
browser.pixDiff.saveScreen(tagName).then(function () { | ||
expect(fs.existsSync(__dirname + '/screenshots/' + tagName + '-chrome-800x600.png')).toBe(true); | ||
expect(fs.existsSync(__dirname + '/screenshots/' + tagName + '-' + browserName + '-800x600.png')).toBe(true); | ||
}); | ||
@@ -38,3 +40,3 @@ }); | ||
browser.pixDiff.saveRegion(element(by.css('div h1')), tagName).then(function () { | ||
expect(fs.existsSync(__dirname + '/screenshots/' + tagName + '-chrome-800x600.png')).toBe(true); | ||
expect(fs.existsSync(__dirname + '/screenshots/' + tagName + '-' + browserName + '-800x600.png')).toBe(true); | ||
}); | ||
@@ -65,6 +67,5 @@ }); | ||
var errorThrown = false; | ||
browser.pixDiff.checkScreen('imagenotexst', {threshold: 1}).then(function () { | ||
browser.pixDiff.checkScreen('imageNotExist', {threshold: 1}).then(function () { | ||
fail('must not do a comparison.'); | ||
}).catch(function () { | ||
// good | ||
errorThrown = true; | ||
@@ -77,3 +78,3 @@ }).then(function () { | ||
describe('format image name', function() { | ||
describe('format image name', function () { | ||
@@ -94,6 +95,71 @@ beforeEach(function () { | ||
browser.pixDiff.saveScreen(tagName).then(function () { | ||
expect(fs.existsSync(__dirname + '/screenshots/TEST_' + tagName + '_chrome_800-600.png')).toBe(true); | ||
expect(fs.existsSync(__dirname + '/screenshots/TEST_' + tagName + '_' + browserName + '_800-600.png')).toBe(true); | ||
}); | ||
}); | ||
}); | ||
describe('scroll into view', function () { | ||
beforeEach(function () { | ||
browser.pixDiff = new PixDiff({ | ||
basePath: 'test/screenshots', | ||
width: 800, | ||
height: 200 | ||
}); | ||
}); | ||
it('should save a scrolled screen', function () { | ||
var tagName = 'scrolledPage', | ||
headerElement = element(by.css('div h1')); | ||
browser.executeScript('arguments[0].scrollIntoView();', headerElement.getWebElement()) | ||
.then(function () { | ||
browser.pixDiff.saveScreen(tagName); | ||
}); | ||
}); | ||
it('should save a scrolled screen region', function () { | ||
var tagName = 'scrolledPageRegion', | ||
headerElement = element(by.css('div h1')); | ||
browser.executeScript('arguments[0].scrollIntoView();', headerElement.getWebElement()) | ||
.then(function () { | ||
browser.pixDiff.saveRegion(element(by.css('div h1')), tagName); | ||
}); | ||
}); | ||
}); | ||
describe('baseline', function () { | ||
beforeEach(function () { | ||
browser.pixDiff = new PixDiff({ | ||
basePath: 'test/screenshots', | ||
baseline: true, | ||
width: 800, | ||
height: 600 | ||
}); | ||
}); | ||
it('should save a screen when baseline image not found', function () { | ||
browser.pixDiff.checkScreen('baselineScreen').catch(function (err) { | ||
expect(err.message).toContain('Image not found'); | ||
}); | ||
}); | ||
it('should use existing baseline image', function () { | ||
expect(browser.pixDiff.checkScreen('baselineScreen')).toMatchScreen(); | ||
}); | ||
it('should save a screen region when baseline image not found', function () { | ||
var headerElement = element(by.css('div h1')); | ||
browser.pixDiff.checkRegion(headerElement, 'baselineRegion').catch(function (err) { | ||
expect(err.message).toContain('Image not found'); | ||
}); | ||
}); | ||
it('should use existing baseline image', function () { | ||
var headerElement = element(by.css('div h1')); | ||
expect(browser.pixDiff.checkRegion(headerElement, 'baselineRegion')).toMatchScreen(); | ||
}); | ||
}); | ||
}); |
@@ -62,6 +62,5 @@ 'use strict'; | ||
var errorThrown = false; | ||
browser.pixDiff.checkScreen('imagenotexst', {threshold: 1}).then(function () { | ||
browser.pixDiff.checkScreen('imageNotExist', {threshold: 1}).then(function () { | ||
expect.fail(); | ||
}).catch(function () { | ||
// good | ||
errorThrown = true; | ||
@@ -68,0 +67,0 @@ }).then(function () { |
@@ -11,13 +11,22 @@ 'use strict'; | ||
capabilities: { | ||
browserName: 'chrome', | ||
chromeOptions: { | ||
args: ['--no-sandbox'] | ||
} | ||
}, | ||
multiCapabilities: [ | ||
{ | ||
browserName: 'chrome', | ||
chromeOptions: { | ||
args: ['--no-sandbox'] | ||
} | ||
}, | ||
{ | ||
browserName: 'firefox' | ||
}], | ||
directConnect: true, | ||
onPrepare: function() { | ||
onPrepare: function () { | ||
browser.ignoreSynchronization = true; | ||
return browser.getProcessedConfig() | ||
.then(function(config){ | ||
browser.browserName = config.capabilities.browserName.toLowerCase(); | ||
}); | ||
}, | ||
@@ -24,0 +33,0 @@ |
Sorry, the diff of this file is not supported yet
47228
824
219