diff --git a/README.md b/README.md index ba64554..7a44f5f 100644 --- a/README.md +++ b/README.md @@ -28,55 +28,48 @@ Example: } ``` To use the Helper, users must provide the three parameters: + `screenshotFolder` : This will always have the same value as `output` in Codecept configuration, this is the folder where webdriverIO saves a screenshot when using `I.saveScreenshot` method `baseFolder`: This is the folder for base images, which will be used with screenshot for comparison `diffFolder`: This will the folder where resemble would try to store the difference image, which can be viewed later, -Please remember to create empty folder if you don't have one already Usage, these are major functions that help in visual testing -First one is the `verifyMisMatchPercentage` which basically takes several parameters including tolerance and PrepareBase +First one is the `seeVisualDiff` which basically takes two parameters +1) `baseImage` Name of the base image, this will be the image used for comparison with the screenshot image, +it is mandatory to have the same image file names for base and screenshot image +2) `options` options can be passed which include `prepaseBaseImage` and `tolerance` + ```js /** - * Mis Match Percentage Verification + * Check Visual Difference for Base and Screenshot Image * @param baseImage Name of the Base Image (Base Image path is taken from Configuration) - * @param screenShotImage Name of the screenshot Image (Screenshot Image Path is taken from Configuration) - * @param diffImageName Name of the Diff Image which will be saved after comparison (Diff Image path is taken from Configuration) - * @param tolerance Tolerance Percentage, default value 10 - * @param prepareBase True | False, depending on the requirement if the base images are missing - * @param selector CSS|XPath|id, If provided locator will be used to fetch Bounding Box of the element and only that element is compared on two images - * @param options Resemble JS Options, read more here: https://github.com/rsmbl/Resemble.js + * @param options Options ex {prepareBaseImage: true, tolerance: 5} along with Resemble JS Options, read more here: https://github.com/rsmbl/Resemble.js * @returns {Promise} */ - async verifyMisMatchPercentage(baseImage, screenShotImage, diffImageName, tolerance = 10, prepareBase = false, selector, options){ -``` -Second one is the `PrepareBase` which basically prepares all the base images in case they are not available -```js - /** - * Function to prepare Base Images from Screenshots - * - * @param baseImage Name of the Base Image (Base Image path is taken from Configuration) - * @param screenShotImage Name of the screenshot Image (Screenshot Image Path is taken from Configuration) - */ - prepareBaseImage(baseImage, screenShotImage) {} + async seeVisualDiff(baseImage, options) {} ``` -Third function is to fetch the boundingBox of an element using selector, this boundingBox is then provided to resemble -so that only that element is compared on the images. +Second one is the `seeVisualDiffForElement` which basically compares elements on the screenshot, Selector for element must be provided +It is exactly same as `seeVisualDiff` function, only an additional `selector` CSS|XPath|ID locators is provided ```js /** - * Function to fetch Bounding box for an element, fetched using selector + * See Visual Diff for an Element on a Page * - * @param selector CSS|XPath|ID locators - * @returns {Promise<{boundingBox: {left: *, top: *, right: *, bottom: *}}>} + * @param selector Selector which has to be compared, CSS|XPath|ID + * @param baseImage Base Image for comparison + * @param options Options ex {prepareBaseImage: true, tolerance: 5} along with Resemble JS Options, read more here: https://github.com/rsmbl/Resemble.js + * @returns {Promise} */ - async getBoundingBox(selector){ + async seeVisualDiffForElement(selector, baseImage, options){} ``` -Users can make use of the boundingBox feature by providing a selector to `verifyMisMatchPercentage` function, it will internally -check if a locator is provided, fetch it's bounding-box and compare only that element on both the images. +> Note: +`seeVisualDiffForElement` only works when the page for baseImage is open in the browser, so that webdriver can fetch coordinates of the provided selector + + Finally to use the helper in your test, you can write something like this: @@ -85,17 +78,21 @@ Feature('to verify monitoried Remote Db instances'); Scenario('Open the System Overview Dashboard', async (I, adminPage, loginPage) => { adminPage.navigateToDashboard("OS", "System Overview"); + I.saveScreenshot("Complete_Dashboard_Image.png"); adminPage.applyTimer("1m"); adminPage.viewMetric("CPU Usage"); - I.saveScreenshot("System_Overview_CPU_Usage.png"); + I.saveScreenshot("Complete_Metric_Image.png"); }); Scenario('Compare CPU Usage Images', async (I) => { - // passing TRUE to let the helper know to prepare base images - I.verifyMisMatchPercentage("System_Overview_CPU_Usage.png", "System_Overview_CPU_Usage.png", "DiffImage_SystemOverview_CPU_USAGE_Dashboard", 10, true); + // setting tolerance and prepareBaseImage in the options array + I.seeVisualDiff("Complete_Metric_Image.png", {prepareBaseImage: false, tolerance: 5}); // passing a selector, to only compare that element on both the images now - I.verifyMisMatchPercentage("System_Overview_CPU_Usage.png", "System_Overview_CPU_Usage.png", "DiffImage_SystemOverview_CPU_USAGE_Panel", 10, false, "//div[@class='panel-container']"); + + // We need to navigate to that page first, so that webdriver can fetch coordinates for the selector + adminPage.navigateToDashboard("OS", "System Overview"); + I.seeVisualDiffForElement("//div[@class='panel-container']", "Complete_Dashboard_Image.png", {prepareBaseImage: false, tolerance: 3}); }); ``` \ No newline at end of file diff --git a/index.js b/index.js index 5b0d76c..eececac 100644 --- a/index.js +++ b/index.js @@ -6,10 +6,12 @@ const fs = require('fs'); let assert = require('assert'); const mkdirp = require('mkdirp'); const getDirName = require('path').dirname; + /** * Resemble.js helper class for CodeceptJS, this allows screen comparison * @author Puneet Kala */ + class ResembleHelper extends Helper { constructor(config) { @@ -17,25 +19,30 @@ class ResembleHelper extends Helper { } /** - * + * Compare Images * @param image1 * @param image2 * @param diffImage - * @param tolerance * @param options * @returns {Promise} */ - async _compareImages (image1, image2, diffImage, tolerance, options) { + async _compareImages (image1, image2, diffImage, options) { image1 = this.config.baseFolder + image1; image2 = this.config.screenshotFolder + image2; return new Promise((resolve, reject) => { - if (options !== undefined) + if (options.boundingBox !== undefined) { resemble.outputSettings({ boundingBox: options.boundingBox }); } + + if (options.tolerance !== undefined) + { + console.log("Tolerance Level Provided " + options.tolerance); + var tolerance = options.tolerance; + } resemble.compare(image1, image2, options, (err, data) => { if (err) { reject(err); @@ -61,63 +68,82 @@ class ResembleHelper extends Helper { /** * * @param image1 - * @param image2 - * @param diffImage - * @param tolerance * @param options * @returns {Promise<*>} */ - async _fetchMisMatchPercentage (image1, image2, diffImage, tolerance, options) { - var result = this._compareImages(image1, image2, diffImage, tolerance, options); + async _fetchMisMatchPercentage (image1, options) { + var image2 = image1; + var diffImage = "Diff_" + image1.split(".")[0]; + var result = this._compareImages(image1, image2, diffImage, options); var data = await Promise.resolve(result); return data.misMatchPercentage; } /** - * Mis Match Percentage Verification + * Check Visual Difference for Base and Screenshot Image * @param baseImage Name of the Base Image (Base Image path is taken from Configuration) - * @param screenShotImage Name of the screenshot Image (Screenshot Image Path is taken from Configuration) - * @param diffImageName Name of the Diff Image which will be saved after comparison (Diff Image path is taken from Configuration) - * @param tolerance Tolerance Percentage, default value 10 - * @param prepareBase True | False, depending on the requirement if the base images are missing - * @param selector If set, passed selector will be used to fetch Bouding Box and compared on two images - * @param options Resemble JS Options, read more here: https://github.com/rsmbl/Resemble.js + * @param options Options ex {prepareBaseImage: true, tolerance: 5} along with Resemble JS Options, read more here: https://github.com/rsmbl/Resemble.js * @returns {Promise} */ - async verifyMisMatchPercentage(baseImage, screenShotImage, diffImageName, tolerance = 10, prepareBase = false, selector, options){ - if (prepareBase) + async seeVisualDiff(baseImage, options) { + if (options == undefined) + { + options = {}; + options.tolerance = 0; + } + + if (options.prepareBaseImage !== undefined && options.prepareBaseImage) { - await this.prepareBaseImage(baseImage, screenShotImage); + await this._prepareBaseImage(baseImage); } + var misMatch = await this._fetchMisMatchPercentage(baseImage, options); + console.log("MisMatch Percentage Calculated is " + misMatch); + assert(misMatch <= options.tolerance, "MissMatch Percentage " + misMatch); + } + + /** + * See Visual Diff for an Element on a Page + * + * @param selector Selector which has to be compared expects these -> CSS|XPath|ID + * @param baseImage Base Image for comparison + * @param options Options ex {prepareBaseImage: true, tolerance: 5} along with Resemble JS Options, read more here: https://github.com/rsmbl/Resemble.js + * @returns {Promise} + */ + async seeVisualDiffForElement(selector, baseImage, options){ + if (selector !== undefined) { - if (options !== undefined) + if (options == undefined) { - options.boundingBox = await this.getBoundingBox(selector); + options = {}; + options.tolerance = 0; } - else + + if (options.prepareBaseImage !== undefined && options.prepareBaseImage) { - var options = {}; - options.boundingBox = await this.getBoundingBox(selector); + await this._prepareBaseImage(baseImage); } - } - var misMatch = await this._fetchMisMatchPercentage(baseImage, screenShotImage, diffImageName, tolerance, options); - console.log("MisMatch Percentage Calculated is " + misMatch); - assert.ok(misMatch < tolerance, "MissMatch Percentage " + misMatch); + options.boundingBox = await this._getBoundingBox(selector); + var misMatch = await this._fetchMisMatchPercentage(baseImage, options); + console.log("MisMatch Percentage Calculated is " + misMatch); + assert(misMatch <= options.tolerance, "MissMatch Percentage " + misMatch); + } + else { + return null; + } } /** * Function to prepare Base Images from Screenshots * - * @param baseImage Name of the Base Image (Base Image path is taken from Configuration) * @param screenShotImage Name of the screenshot Image (Screenshot Image Path is taken from Configuration) */ - async prepareBaseImage(baseImage, screenShotImage) { + async _prepareBaseImage(screenShotImage) { var configuration = this.config; - await this._createDir(configuration.baseFolder + baseImage); + await this._createDir(configuration.baseFolder + screenShotImage); fs.access(configuration.screenshotFolder + screenShotImage, fs.constants.F_OK | fs.constants.W_OK, (err) => { if (err) { @@ -133,7 +159,7 @@ class ResembleHelper extends Helper { } }); - fs.copyFileSync(configuration.screenshotFolder + screenShotImage, configuration.baseFolder + baseImage); + fs.copyFileSync(configuration.screenshotFolder + screenShotImage, configuration.baseFolder + screenShotImage); } /** @@ -152,7 +178,7 @@ class ResembleHelper extends Helper { * @param selector CSS|XPath|ID selector * @returns {Promise<{boundingBox: {left: *, top: *, right: *, bottom: *}}>} */ - async getBoundingBox(selector){ + async _getBoundingBox(selector){ const browser = this._getBrowser(); var ele = await browser.element(selector) diff --git a/package.json b/package.json index 72dde23..3f73cf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeceptjs-resemblehelper", - "version": "1.2.1", + "version": "1.4.0", "description": "Resemble Js helper for CodeceptJS, with WebdriverIO", "repository": { "type": "git",