protractor-image-comparison
Advanced tools
Comparing version 1.4.0 to 1.5.0
@@ -0,1 +1,8 @@ | ||
<a name="1.5.0"></a> | ||
# [1.5.0](https://github.com/wswebcreation/protractor-image-comparison/compare/v1.4.0...v1.5.0) (2017-12-17) | ||
### Features | ||
* Remove temporary saving (fullpage)screenshots by saving them to a buffer array. This should prevent an overkill of temp screenshots | ||
<a name="1.4.0"></a> | ||
@@ -19,4 +26,2 @@ # [1.4.0](https://github.com/wswebcreation/protractor-image-comparison/compare/v1.3.0...v1.4.0) (2017-11-17) | ||
<a name="1.2.5"></a> | ||
@@ -23,0 +28,0 @@ ## [1.2.5](https://github.com/wswebcreation/protractor-image-comparison/compare/v1.2.4...v1.2.5) (2017-05-18) |
Contributing | ||
============ | ||
#Tests | ||
# Tests | ||
There are several test that need to be executed to be able to test the module. When adding a PR all tests must at least pass the local tests. | ||
@@ -10,7 +10,7 @@ Each PR is automatically tested against Sauce Labs, see [Travis-ci with Sauce Labs](#travis-ci-with-sauce-labs). | ||
## Local | ||
**Make sure a local webdriver is installed, see [How to run a local webdriver](#how-to-run-a-local-webdriver) and start your webdriver.** | ||
**Make sure a local webdriver is installed, see [How to run a local webdriver](#how-to-run-a-local-webdriver) and start your webdriver.** | ||
(*DirectConnect from protractor itself is not stable enough to run our tests, that's why we we use a local webdriver*). | ||
First a local baseline needs to be created. This can be done with `npm run test.init`. This command will create a folder called `localBaseline` that will hold all the baseline images. | ||
Then run `npm run test.local`. This will run all tests on a local machine on Chrome (job uses direct connect, first run `npm run wd-update` to update the webdriver. | ||
Then run `npm run test.local`. This will run all tests on a local machine on Chrome (job uses direct connect, first run `npm run wd-update` to update the webdriver. | ||
This needs to be done once after install). | ||
@@ -44,6 +44,6 @@ | ||
`npm run test.perfecto`: Run all tests on a real: | ||
- Apple iOS device on Safari in the cloud | ||
- Samsung Android on Chrom in the cloud | ||
**Credentials are needed to be able to test this** | ||
@@ -58,2 +58,2 @@ | ||
All PR's are automatically checked against Sauce Labs. | ||
All PR's are automatically checked against Sauce Labs. |
@@ -1,5 +0,5 @@ | ||
#Conventions | ||
# Conventions | ||
There are directory and naming conventions that must be met. | ||
##Directory structure | ||
## Directory structure | ||
```text | ||
@@ -37,2 +37,2 @@ path | ||
* `mobile` This will add `_app`, of `browserName` after the deviceName to distinguish app screenshots from browser screenshots | ||
* `name` The name from capabilities | ||
* `name` The name from capabilities |
Examples | ||
======== | ||
##Configuration file setup: | ||
## Configuration file setup: | ||
Load it from the configuration file of *protractor* | ||
@@ -22,3 +22,3 @@ | ||
##Jasmine Example: | ||
## Jasmine Example: | ||
Load it in a *spec* file | ||
@@ -59,3 +59,3 @@ | ||
##Cucumber Example: | ||
## Cucumber Example: | ||
Load it in a *step* file | ||
@@ -68,3 +68,3 @@ | ||
function CucumberSteps() { | ||
browser.protractorImageComparison = new protractorImageComparison({ | ||
@@ -74,3 +74,3 @@ baselineFolder: './baseline/', | ||
}); | ||
this.Given(/^I load the url$/, function () { | ||
@@ -103,2 +103,2 @@ return browser.get('http://www.example.com/'); | ||
For more examples / usage see the [desktop](../test/desktop.spec.js) or [mobile](../test/desktop.spec.js) testcases. | ||
For more examples / usage see the [desktop](../test/desktop.spec.js) or [mobile](../test/desktop.spec.js) testcases. |
@@ -1,4 +0,4 @@ | ||
#Methods | ||
# Methods | ||
##saveScreen or checkScreen | ||
## saveScreen or checkScreen | ||
The methods `saveScreen` and `checkScreen` create a screenshot of the visible viewport. Be aware that there are different webdriver implementations in creating complete screenshots. | ||
@@ -18,3 +18,3 @@ For example: | ||
##saveElement or checkElement | ||
## saveElement or checkElement | ||
Images are cropped from the complete screenshot by using the `saveElement` or `checkElement` function. | ||
@@ -25,3 +25,3 @@ The method will calculate the correct dimensions based upon the webdriver element selector. | ||
##NEW saveFullPageScreens or checkFullPageScreen | ||
## NEW saveFullPageScreens or checkFullPageScreen | ||
The methods `saveFullPageScreens` and `checkFullPageScreen` create a screenshot of the **complete** page. Basically it will device the complete page into multiple viewports. | ||
@@ -33,3 +33,3 @@ Then it will scroll to each viewport, waits a given timeout (default 1000 milliseconds) and takes a screenshot. When all the viewports have been captured it will compose a new complete fullpage screenshot. | ||
##protractor-image-comparison parameters: | ||
## protractor-image-comparison parameters: | ||
@@ -74,3 +74,3 @@ * `baselineFolder` Defines the path to the reference images that are to be compared. | ||
##Method options: | ||
## Method options: | ||
### blockOut | ||
@@ -94,2 +94,2 @@ Sometimes, it is necessary to block-out some specific areas in an image that should be ignored for comparisons. For example, this can be IDs or even time-labels that change with the time. Adding block-outs to images may decrease false positives and therefore stabilizes these comparisons (see the [examples](./examples.md)). | ||
### More options | ||
For more method options and example usage see [here](./index.md). | ||
For more method options and example usage see [here](./index.md). |
86
index.js
@@ -127,3 +127,6 @@ 'use strict'; | ||
fs.ensureDirSync(this.diffFolder); | ||
fs.ensureDirSync(this.tempFullScreenFolder); | ||
if(this.debug) { | ||
fs.ensureDirSync(this.tempFullScreenFolder); | ||
} | ||
} | ||
@@ -158,27 +161,23 @@ | ||
/** | ||
* Compose a full page screenshot and save it | ||
* Save a full page screenshot | ||
* @param {string} tag The tag that is used | ||
* @param {number} amountOfScreenshots The amount of amountOfScreenshots that need to be processed | ||
* @param {number} currentScreenshotNumber The current currentScreenshotNumber of the screenshot that is being processed | ||
* @param {string} image The current image output that needs to be saved | ||
* @param {Array} screens An array full of buffered screenshots | ||
* @returns {Promise} | ||
* @private | ||
*/ | ||
_composeAndSaveFullScreenshot(tag, amountOfScreenshots, currentScreenshotNumber, image) { | ||
const imageHeight = this.fullPageHeight * this.devicePixelRatio; | ||
const imageWidth = this.viewPortWidth * this.devicePixelRatio; | ||
const stitchHeightCoordinate = (this.viewPortHeight - this.addressBarShadowPadding - this.toolBarShadowPadding) * (currentScreenshotNumber - 1) * this.devicePixelRatio; | ||
_saveFullScreenshot(tag, screens) { | ||
// Calculate total canvas size | ||
const imageHeight = screens.reduce((previous, current) => (previous instanceof Buffer ? previous.readUInt32BE(20) : previous) + current.readUInt32BE(20)); | ||
const imageWidth = screens[0].readUInt32BE(16); | ||
const imageOutput = PNGJSImage.createImage(imageWidth, imageHeight); | ||
let offsetY = 0; | ||
let imageOutput = image || null; | ||
if (currentScreenshotNumber === 1) { | ||
imageOutput = PNGJSImage.createImage(imageWidth, imageHeight); | ||
} else if (currentScreenshotNumber > amountOfScreenshots) { | ||
return Promise.resolve(imageOutput.writeImageSync(path.join(this.actualFolder, this._formatFileName(tag)))); | ||
// Compose PNG | ||
for (let screen of screens) { | ||
let height = screen.readUInt32BE(20); | ||
PNGJSImage.loadImageSync(screen).getImage().bitblt(imageOutput.getImage(), 0, 0, imageWidth, height, 0, offsetY); | ||
offsetY += height; | ||
} | ||
const stitchImage = PNGJSImage.readImageSync(path.join(this.tempFullScreenFolder, this._formatFileName(`${tag}-${currentScreenshotNumber}`))); | ||
stitchImage.getImage().bitblt(imageOutput.getImage(), 0, 0, stitchImage.getWidth(), stitchImage.getHeight(), 0, stitchHeightCoordinate); | ||
return this._composeAndSaveFullScreenshot(tag, amountOfScreenshots, currentScreenshotNumber + 1, imageOutput) | ||
return Promise.resolve(imageOutput.writeImageSync(path.join(this.actualFolder, this._formatFileName(tag)))); | ||
} | ||
@@ -311,3 +310,3 @@ | ||
mobileCropData.cropHeight = this.fullPageHeight - ((this.viewPortHeight - this.addressBarShadowPadding - this.toolBarShadowPadding) * (cropParameters.currentScreenshotNumber - 1)); | ||
mobileCropData.cropTopPosition = statusPlusAddressBarHeight + (this.viewPortHeight- this.toolBarShadowPadding) - mobileCropData.cropHeight; | ||
mobileCropData.cropTopPosition = statusPlusAddressBarHeight + (this.viewPortHeight - this.toolBarShadowPadding) - mobileCropData.cropHeight; | ||
} else { | ||
@@ -327,3 +326,3 @@ mobileCropData.cropHeight = this.viewPortHeight - this.addressBarShadowPadding - this.toolBarShadowPadding; | ||
mobileCropData.cropHeight = this.fullPageHeight - ((this.viewPortHeight - this.addressBarShadowPadding - this.toolBarShadowPadding) * (cropParameters.currentScreenshotNumber - 1)); | ||
mobileCropData.cropTopPosition = safariHeights.addressBarCurrentHeight + (this.viewPortHeight- this.toolBarShadowPadding) - mobileCropData.cropHeight; | ||
mobileCropData.cropTopPosition = safariHeights.addressBarCurrentHeight + (this.viewPortHeight - this.toolBarShadowPadding) - mobileCropData.cropHeight; | ||
} else { | ||
@@ -754,2 +753,30 @@ mobileCropData.cropHeight = this.viewPortHeight - this.addressBarShadowPadding - this.toolBarShadowPadding; | ||
/** | ||
* Create a new cropped buffered image | ||
* @param {object} bufferedScreenshot a new Buffer screenshot | ||
* @param {object} rectangles x, y, height and width data to determine the crop | ||
* @returns {Buffer} The image buffer | ||
* @private | ||
*/ | ||
_getCroppedBufferedScreenshot(bufferedScreenshot, rectangles) { | ||
let imageHeight; | ||
const image = PNGJSImage.loadImageSync(bufferedScreenshot); | ||
// When coordinates have decimals they are `round`ed. This means that the total amount can be bigger | ||
// than the image. That's why we need to resize it. | ||
if ((rectangles.height + rectangles.y) > image.getHeight()) { | ||
imageHeight = rectangles.height - ((rectangles.height + rectangles.y) - image.getHeight()); | ||
} else { | ||
imageHeight = rectangles.height; | ||
} | ||
const imageWidth = rectangles.width; | ||
// Create the canvas | ||
const imageOutput = PNGJSImage.createImage(imageWidth, imageHeight); | ||
// Create the image | ||
image.getImage().bitblt(imageOutput.getImage(), rectangles.x, rectangles.y, imageWidth, imageHeight, 0, 0); | ||
return imageOutput.toBlobSync(); | ||
} | ||
/** | ||
* Scroll to static horizontal and a given vertical coordinate on the page and wait a given time. | ||
@@ -771,6 +798,7 @@ * @param {number} verticalCoordinate The y-coordinate that needs to be scrolled to | ||
* @param {number} currentScreenshotNumber The currentScreenshotNumber of the screen that is being processed | ||
* @param {Array} screens An array full of buffered screenshots | ||
* @returns {Promise} | ||
* @private | ||
*/ | ||
_scrollAndSave(newVerticalCoordinate, tag, currentScreenshotNumber) { | ||
_scrollAndSave(newVerticalCoordinate, tag, currentScreenshotNumber, screens) { | ||
const previousVerticalCoordinate = (currentScreenshotNumber - 1) * this.viewPortHeight; | ||
@@ -821,11 +849,13 @@ | ||
console.log('####################################################\n'); | ||
this._saveCroppedScreenshot(bufferedScreenshot, this.tempFullScreenFolder, rectangles, `${tag}-${currentScreenshotNumber}`); | ||
} | ||
return this._getCroppedBufferedScreenshot(bufferedScreenshot, rectangles); | ||
}) | ||
.then((screen) => { | ||
screens.push(screen); | ||
return this._saveCroppedScreenshot(bufferedScreenshot, this.tempFullScreenFolder, rectangles, `${tag}-${currentScreenshotNumber}`); | ||
}) | ||
.then(() => { | ||
if (this.isLastScreenshot) { | ||
return this._composeAndSaveFullScreenshot(tag, currentScreenshotNumber, 1); | ||
return this._saveFullScreenshot(tag, screens); | ||
} else { | ||
return this._scrollAndSave((this.viewPortHeight - this.addressBarShadowPadding - this.toolBarShadowPadding) * currentScreenshotNumber, tag, currentScreenshotNumber + 1); | ||
return this._scrollAndSave((this.viewPortHeight - this.addressBarShadowPadding - this.toolBarShadowPadding) * currentScreenshotNumber, tag, currentScreenshotNumber + 1, screens); | ||
} | ||
@@ -1057,3 +1087,3 @@ }); | ||
return this._getInstanceData() | ||
.then(() => this._scrollAndSave(0, tag, 1)); | ||
.then(() => this._scrollAndSave(0, tag, 1, [])); | ||
} | ||
@@ -1060,0 +1090,0 @@ |
{ | ||
"name": "protractor-image-comparison", | ||
"version": "1.4.0", | ||
"version": "1.5.0", | ||
"description": "npm-module to compare images with protractor", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
protractor-image-comparison | ||
========== | ||
[![dependencies Status](https://david-dm.org/wswebcreation/protractor-image-comparison/status.svg)](https://david-dm.org/wswebcreation/protractor-image-comparison) [![Build Status](https://travis-ci.org/wswebcreation/protractor-image-comparison.svg?branch=master)](https://travis-ci.org/wswebcreation/protractor-image-comparison) [![Sauce Test Status](https://saucelabs.com/buildstatus/wswebcreation-nl)](https://saucelabs.com/u/wswebcreation-nl) | ||
[![Join the chat at https://gitter.im/wswebcreation/protractor-image-comparison](https://badges.gitter.im/wswebcreation/protractor-image-comparison.svg)](https://gitter.im/wswebcreation/protractor-image-comparison?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![dependencies Status](https://david-dm.org/wswebcreation/protractor-image-comparison/status.svg)](https://david-dm.org/wswebcreation/protractor-image-comparison) [![Build Status](https://travis-ci.org/wswebcreation/protractor-image-comparison.svg?branch=master)](https://travis-ci.org/wswebcreation/protractor-image-comparison) [![Sauce Test Status](https://saucelabs.com/buildstatus/wswebcreation-nl)](https://saucelabs.com/u/wswebcreation-nl) | ||
@@ -23,2 +23,3 @@ [![NPM](https://nodei.co/npm/protractor-image-comparison.png)](https://nodei.co/npm/protractor-image-comparison/) | ||
- **NEW** ignore regions by making them transparent in the base image (all) thanks to [tharders](https://github.com/tharders) | ||
- **NEW** parameter to hide / show scrollbars [pnad](https://github.com/pnad) | ||
- increase the element dimenisions screenshots (all) | ||
@@ -25,0 +26,0 @@ - provide custom iOS and Android offsets for status-/address-/toolbar (mobile only) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
799279
1360
92