From 552a1860ff8ccd037c76a7d890636965200b4b7e Mon Sep 17 00:00:00 2001 From: humphreyn Date: Mon, 19 Oct 2020 16:57:25 +0100 Subject: [PATCH 1/9] Resolved url-regex DOS vulnerability (https://www.npmjs.com/advisories/1550) which is a dependency of jimp v0.2.28 by upgrading jimp to 0.16.1 updated test to be platform agnostic (work on windows) updated the following npm dependency packages to the latest versions: - jimp: 0.16.1 - lodash: 4.17.20 - eslint: 7.11.0 - eslint-config-crunch: 1.8.0 - eslint-plugin-react: 7.21.4 - http-server: 0.12.3 - jest: 26.6.0 - nightwatch: 1.4.3 - npm-run-all: 4.1.5 - phantomjs-prebuilt: 2.1.16 - rimraf: 3.0.2 - selenium-standalone: 6.20.1 --- package.json | 24 +++++++++---------- .../lib/generate-screenshot-file-path-test.js | 14 +++++------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 0fe8710..02c6706 100644 --- a/package.json +++ b/package.json @@ -56,19 +56,19 @@ ] }, "dependencies": { - "jimp": "^0.2.28", - "lodash": "^4.17.4" + "jimp": "^0.16.1", + "lodash": "^4.17.20" }, "devDependencies": { - "eslint": "^4.3.0", - "eslint-config-crunch": "^1.1.3", - "eslint-plugin-react": "^7.3.0", - "http-server": "^0.10.0", - "jest": "^20.0.4", - "nightwatch": "^1.0.14", - "npm-run-all": "^4.0.2", - "phantomjs-prebuilt": "^2.1.15", - "rimraf": "^2.6.1", - "selenium-standalone": "^6.7.0" + "eslint": "^7.11.0", + "eslint-config-crunch": "^1.8.0", + "eslint-plugin-react": "^7.21.4", + "http-server": "^0.12.3", + "jest": "^26.6.0", + "nightwatch": "^1.4.3", + "npm-run-all": "^4.1.5", + "phantomjs-prebuilt": "^2.1.16", + "rimraf": "^3.0.2", + "selenium-standalone": "^6.20.1" } } diff --git a/tests/lib/generate-screenshot-file-path-test.js b/tests/lib/generate-screenshot-file-path-test.js index 9171d5d..f385c30 100644 --- a/tests/lib/generate-screenshot-file-path-test.js +++ b/tests/lib/generate-screenshot-file-path-test.js @@ -18,12 +18,12 @@ describe('generateScreenshotFilePath', () => { it('should generate a file path by using the basePath parameter, and the current test name and module', () => { expect(generateScreenshotFilePath(getNightwatchClient(), 'baseline')) - .toEqual(`${process.cwd()}/baseline/visualizations/bar-plots.png`) + .toEqual(path.resolve(`${process.cwd()}/baseline/visualizations/bar-plots.png`)) }) it('should generate a file path by using the basePath parameter, and a custom filename', () => { expect(generateScreenshotFilePath(getNightwatchClient(), 'baseline', 'foo-test')) - .toEqual(`${process.cwd()}/baseline/visualizations/foo-test.png`) + .toEqual(path.resolve(`${process.cwd()}/baseline/visualizations/foo-test.png`)) }) it('should pass the correct filename to the custom naming function', () => { @@ -34,10 +34,10 @@ describe('generateScreenshotFilePath', () => { set(nightwatchClient, 'globals.test_settings.visual_regression_settings.generate_screenshot_path', testFn) const result = generateScreenshotFilePath(nightwatchClient, 'baseline', 'foo-test') + const expected = path.resolve(`${process.cwd()}/baseline/visualizations/test-setting-custom-foo-test.png`) expect(testFn).toHaveBeenCalled() - expect(result) - .toEqual(`${process.cwd()}/baseline/visualizations/test-setting-custom-foo-test.png`) + expect(result).toEqual(expected) }) it('should use the base global setting for generate_screenshot_path if a test_setting exists', () => { @@ -46,7 +46,7 @@ describe('generateScreenshotFilePath', () => { path.join(process.cwd(), basePath, client.currentTest.module, `test-setting-custom-${fileName}`)) set(nightwatchClient, 'globals.test_settings.visual_regression_settings.generate_screenshot_path', testFn) - + const customFn = jest.fn((client, basePath, fileName) => path.join(process.cwd(), basePath, client.currentTest.module, `custom-${fileName}`)) @@ -54,8 +54,8 @@ describe('generateScreenshotFilePath', () => { set(nightwatchClient, 'globals.test_settings.visual_regression_settings.generate_screenshot_path', testFn) const result = generateScreenshotFilePath(nightwatchClient, 'baseline', 'foo-test') + const expected = path.resolve(`${process.cwd()}/baseline/visualizations/custom-foo-test.png`) - expect(result, 'baseline', 'foo-test') - .toEqual(`${process.cwd()}/baseline/visualizations/custom-foo-test.png`) + expect(result).toEqual(expected) }) }) From 52f5447523792f032d1096639d989c971fd1c738 Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 01:55:57 +0000 Subject: [PATCH 2/9] updated eslint config added prettier and husky updated dependencies to latest --- .editorconfig | 21 -- .eslintrc | 8 - .eslintrc.json | 19 ++ .gitignore | 62 +++- .husky/pre-commit | 4 + .npmrc | 1 + .prettierignore | 6 + .prettierrc.json | 17 + assertions/screenshotIdenticalToBaseline.js | 74 ++--- commands/captureElementScreenshot.js | 134 ++++---- demo/demo1/index.html | 18 +- demo/demo2/index.html | 18 +- demo/nightwatch.conf.js | 302 ++++++++++-------- demo/tests/demo.e2e.js | 20 +- lib/cleanup-screenshots.js | 25 +- lib/compare-with-baseline.js | 214 ++++++------- lib/generate-screenshot-file-path.js | 50 +-- lib/get-baseline-screenshot-or-create.js | 43 ++- lib/get-vrt-settings.js | 52 +-- lib/override-baseline.js | 31 +- lib/promisify-command.js | 24 +- lib/prompt-screenshot-override.js | 79 +++-- lib/save-screenshot.js | 22 +- package.json | 146 ++++----- .../lib/generate-screenshot-file-path-test.js | 174 ++++++---- tests/lib/get-vrt-settings-test.js | 164 +++++----- tests/lib/promisify-command-test.js | 79 ++--- tests/lib/save-screenshot-test.js | 52 ++- 28 files changed, 1003 insertions(+), 856 deletions(-) delete mode 100644 .editorconfig delete mode 100644 .eslintrc create mode 100644 .eslintrc.json create mode 100644 .husky/pre-commit create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc.json diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 8a80734..0000000 --- a/.editorconfig +++ /dev/null @@ -1,21 +0,0 @@ -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# editorconfig.org - -root = true - - -[*] - -# Change these settings to your own preference -indent_style = space -indent_size = 4 - -# We recommend you to keep these unchanged -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 077fbd4..0000000 --- a/.eslintrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": [ - "crunch" - ], - "globals": { - "process": true - } -} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bc98fbf --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "plugins": ["prettier"], + "extends": ["plugin:prettier/recommended"], + "env": { + "node": true, + "es6": true, + "browser": true + }, + "rules": { + "no-unused-vars": "off", + "no-console": "off", + "prettier/prettier": "error", + "quote-props": ["error", "always"], + "semi": "error" + }, + "parserOptions": { + "ecmaVersion": 2021 + } +} diff --git a/.gitignore b/.gitignore index eda6fe4..2008cf6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,62 @@ -node_modules yarn.lock -reports -package-lock.json selenium-debug.log .DS_Store + + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# Husky +.husky/_ + +# Project +.idea/ +*.iml +tasks.xml + diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..d24fdfc --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..214c29d --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmjs.org/ diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e16b913 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +# Project +.eslintcache +.husky/ +.idea/ +node_modules +package-lock.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..28acf99 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,17 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "quoteProps": "preserve", + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "none", + "useTabs": true, + "xmlWhitespaceSensitivity": "strict", + "overrides": [ + { + "files": "*.json", + "options": { "parser": "json" } + } + ] +} diff --git a/assertions/screenshotIdenticalToBaseline.js b/assertions/screenshotIdenticalToBaseline.js index 9934c59..16db660 100644 --- a/assertions/screenshotIdenticalToBaseline.js +++ b/assertions/screenshotIdenticalToBaseline.js @@ -1,6 +1,6 @@ -'use strict' +"use strict"; -const compareWithBaseline = require('../lib/compare-with-baseline') +const compareWithBaseline = require("../lib/compare-with-baseline"); /** * Asserts if a screenshot that captures the visual representation of @@ -22,44 +22,44 @@ const compareWithBaseline = require('../lib/compare-with-baseline') * @param {String} message Optional message for `nightwatch` to log upon completion */ exports.assertion = function screenshotIdenticalToBaseline( - elementId, - fileName = elementId, - settings, - message + elementId, + fileName = elementId, + settings, + message ) { + this.message = + message || `Visual regression test results for element <${elementId}>.`; + this.expected = true; - this.message = message || `Visual regression test results for element <${elementId}>.` - this.expected = true + this.pass = function pass(value) { + return value === this.expected; + }; - this.pass = function pass(value) { - return value === this.expected - } + this.value = function value(result) { + return result; + }; - this.value = function value(result) { - return result - } + this.command = function command(callback) { + let screenshot, comparisonResult; - this.command = function command(callback) { - let screenshot, - comparisonResult + this.api + .waitForElementVisible(elementId, 5000) + .captureElementScreenshot(elementId, (elementScreenshot) => { + screenshot = elementScreenshot; + }) + .perform((done) => { + compareWithBaseline(this.api, screenshot, fileName, settings).then( + (result) => { + comparisonResult = result; + done(); + } + ); + }) + .perform((done) => { + callback(comparisonResult); + done(); + }); - this - .api - .waitForElementVisible(elementId, 5000) - .captureElementScreenshot(elementId, (elementScreenshot) => { - screenshot = elementScreenshot - }) - .perform((done) => { - compareWithBaseline(this.api, screenshot, fileName, settings).then((result) => { - comparisonResult = result - done() - }) - }) - .perform((done) => { - callback(comparisonResult) - done() - }) - - return this - } -} + return this; + }; +}; diff --git a/commands/captureElementScreenshot.js b/commands/captureElementScreenshot.js index a24d098..3470187 100644 --- a/commands/captureElementScreenshot.js +++ b/commands/captureElementScreenshot.js @@ -1,85 +1,99 @@ -'use strict' +"use strict"; -const EventEmitter = require('events').EventEmitter, - util = require('util'), - Jimp = require('jimp'), - Buffer = require('buffer').Buffer, - promisifyCommand = require('../lib/promisify-command') +const EventEmitter = require("events").EventEmitter, + util = require("util"), + Jimp = require("jimp"), + Buffer = require("buffer").Buffer, + promisifyCommand = require("../lib/promisify-command"); /** * Takes a screenshot of the visible region encompassed by the bounding rectangle * of an element. -* + * * @link * @param {string} id ID of the element to route the command to. * @param {function} callback Callback function which is called with the captured screenshot as an argument. * @returns {Object} The captured screenshot. This object is a Jimp (library) image instance. */ function CaptureElementScreenshot() { - EventEmitter.call(this) + EventEmitter.call(this); } -util.inherits(CaptureElementScreenshot, EventEmitter) +util.inherits(CaptureElementScreenshot, EventEmitter); CaptureElementScreenshot.prototype.command = function command( - selector, - callback = () => {} // eslint-disable-line no-empty-function + selector, + callback = () => {} // eslint-disable-line no-empty-function ) { - const api = this.client.api + const api = this.client.api; - Promise.all([ - promisifyCommand(api, 'getLocationInView', [selector]), - promisifyCommand(api, 'getElementSize', [selector]), - promisifyCommand(api, 'screenshot', [false]) - ]).then(([location, size, screenshotEncoded]) => { - let { x, y } = location - let { width, height } = size + Promise.all([ + promisifyCommand(api, "getLocationInView", [selector]), + promisifyCommand(api, "getElementSize", [selector]), + promisifyCommand(api, "screenshot", [false]) + ]) + .then(([location, size, screenshotEncoded]) => { + let { x, y } = location; + let { width, height } = size; - /* - * Here we get the pixel density of the window and - * ensure that we adjust the width and height accordingly - */ - api.execute(function () { - return window.devicePixelRatio - }, [], function (devicePixelRatio) { - x *= devicePixelRatio.value - y *= devicePixelRatio.value - width *= devicePixelRatio.value - height *= devicePixelRatio.value - }); + /* + * Here we get the pixel density of the window and + * ensure that we adjust the width and height accordingly + */ + api.execute( + function () { + return window.devicePixelRatio; + }, + [], + function (devicePixelRatio) { + x *= devicePixelRatio.value; + y *= devicePixelRatio.value; + width *= devicePixelRatio.value; + height *= devicePixelRatio.value; + } + ); - if (width === 0 || height === 0) { - this.api.assert.fail(`The element identified by the selector <${selector}> is not visible or its dimensions equals 0. width: ${width}, height: ${height}`) // eslint-disable-line max-len); - } + if (width === 0 || height === 0) { + this.api.assert.fail( + `The element identified by the selector <${selector}> is not visible` + + ` or its dimensions equals 0. width: ${width}, height: ${height}` + ); + } - Jimp.read(new Buffer(screenshotEncoded, 'base64')).then((screenshot) => { - /** - * https://www.w3.org/TR/webdriver/#take-screenshot - * "The Take Screenshot command takes a screenshot of the top-level browsing context’s viewport." - * - * If the target element extends outside of the viewport, the expected - * dimentions will exceed the actual dimensions, resulting in a - * "RangeError: out of range index" exception (from Buffer) - */ - if ((y + height) > screenshot.bitmap.height) { - height = (screenshot.bitmap.height - y) - } + Jimp.read(new Buffer(screenshotEncoded, "base64")).then((screenshot) => { + /** + * https://www.w3.org/TR/webdriver/#take-screenshot + * "The Take Screenshot command takes a screenshot of the top-level browsing context’s viewport." + * + * If the target element extends outside of the viewport, the expected + * dimentions will exceed the actual dimensions, resulting in a + * "RangeError: out of range index" exception (from Buffer) + */ + if (y + height > screenshot.bitmap.height) { + height = screenshot.bitmap.height - y; + } - if ((x + width) > screenshot.bitmap.width) { - width = (screenshot.bitmap.width - x) - } + if (x + width > screenshot.bitmap.width) { + width = screenshot.bitmap.width - x; + } - screenshot.crop(x, y, width, height) + screenshot.crop(x, y, width, height); - this.api.assert.ok(true, `The screenshot for selector <${selector}> was captured successfully.`); + this.api.assert.ok( + true, + `The screenshot for selector <${selector}> was captured successfully.` + ); - callback(screenshot) - this.emit('complete', screenshot) - }) - }).catch((errorMessage) => { - this.api.assert.fail(`The screenshot for selector <${selector}> could not be captured.`); - this.emit('complete', errorMessage, this) - }) -} + callback(screenshot); + this.emit("complete", screenshot); + }); + }) + .catch((errorMessage) => { + this.api.assert.fail( + `The screenshot for selector <${selector}> could not be captured.` + ); + this.emit("complete", errorMessage, this); + }); +}; -module.exports = CaptureElementScreenshot +module.exports = CaptureElementScreenshot; diff --git a/demo/demo1/index.html b/demo/demo1/index.html index 8edd70b..d02bf3f 100644 --- a/demo/demo1/index.html +++ b/demo/demo1/index.html @@ -1,12 +1,12 @@ - - - - - <%= htmlWebpackPlugin.options.title %> - - -

Hello, world!

- + + + + + <%= htmlWebpackPlugin.options.title %> + + +

Hello, world!

+ diff --git a/demo/demo2/index.html b/demo/demo2/index.html index 7537c52..2d70429 100644 --- a/demo/demo2/index.html +++ b/demo/demo2/index.html @@ -1,12 +1,12 @@ - - - - - <%= htmlWebpackPlugin.options.title %> - - -

Hello, earth!

- + + + + + <%= htmlWebpackPlugin.options.title %> + + +

Hello, earth!

+ diff --git a/demo/nightwatch.conf.js b/demo/nightwatch.conf.js index c65327e..c80853f 100644 --- a/demo/nightwatch.conf.js +++ b/demo/nightwatch.conf.js @@ -1,152 +1,170 @@ -'use strict' +"use strict"; -const fs = require('fs') -const path = require('path') -const rimraf = require('rimraf') -const seleniumStandAlone = require('selenium-standalone') +const fs = require("fs"); +const path = require("path"); +const rimraf = require("rimraf"); +const seleniumStandAlone = require("selenium-standalone"); -const DEVELOPMENT = process.env.NODE_ENV === 'development' +const DEVELOPMENT = process.env.NODE_ENV === "development"; -const REPORTS_PATH = path.join(__dirname, 'reports', 'e2e') -const SCREENSHOT_PATH = path.join(__dirname, 'reports', 'screenshots') -const BINPATH = path.join(process.cwd(), 'node_modules', 'nightwatch', 'bin') +const REPORTS_PATH = path.join(__dirname, "reports", "e2e"); +const SCREENSHOT_PATH = path.join(__dirname, "reports", "screenshots"); +const BINPATH = path.join(process.cwd(), "node_modules", "nightwatch", "bin"); -const SELENIUM_VERSION = '3.5.1' // https://selenium-release.storage.googleapis.com/index.html -const SELENIUM_PATH = path.join(BINPATH, 'selenium-server', SELENIUM_VERSION + '-' + 'server.jar') -const CHROME_DRIVER_VERSION = '2.31' // https://chromedriver.storage.googleapis.com/index.html -const CHROME_PATH = path.join(BINPATH, 'chromedriver', CHROME_DRIVER_VERSION + '-' + process.arch + '-' + 'chromedriver') -const IE_DRIVER_VERSION = SELENIUM_VERSION // https://selenium-release.storage.googleapis.com/index.html -const GECKO_DRIVER_VERSION = '0.18.0' // https://github.com/mozilla/geckodriver/releases -const GECKO_PATH = path.join(BINPATH, 'geckodriver', GECKO_DRIVER_VERSION + '-' + process.arch + '-' + 'geckodriver') -const GHOST_DRIVER_VERSION = '2.1.0' // https://github.com/detro/ghostdriver/releases -const GHOST_PATH = '2.1.0' -const PHANTOMJS_PATH = path.join(__dirname, 'node_modules', 'phantomjs-prebuilt', 'bin', 'phantomjs') +const SELENIUM_VERSION = "3.5.1"; // https://selenium-release.storage.googleapis.com/index.html +const SELENIUM_PATH = path.join( + BINPATH, + "selenium-server", + SELENIUM_VERSION + "-" + "server.jar" +); +const CHROME_DRIVER_VERSION = "2.31"; // https://chromedriver.storage.googleapis.com/index.html +const CHROME_PATH = path.join( + BINPATH, + "chromedriver", + CHROME_DRIVER_VERSION + "-" + process.arch + "-" + "chromedriver" +); +const IE_DRIVER_VERSION = SELENIUM_VERSION; // https://selenium-release.storage.googleapis.com/index.html +const GECKO_DRIVER_VERSION = "0.18.0"; // https://github.com/mozilla/geckodriver/releases +const GECKO_PATH = path.join( + BINPATH, + "geckodriver", + GECKO_DRIVER_VERSION + "-" + process.arch + "-" + "geckodriver" +); +const GHOST_DRIVER_VERSION = "2.1.0"; // https://github.com/detro/ghostdriver/releases +const GHOST_PATH = "2.1.0"; +const PHANTOMJS_PATH = path.join( + __dirname, + "node_modules", + "phantomjs-prebuilt", + "bin", + "phantomjs" +); function defaultScreenshotPath(nightwatchClient, basePath, fileName) { - return path.join( - nightwatchClient.options.screenshotsPath || basePath || ('reports/screenshots'), - nightwatchClient.options.desiredCapabilities.platform || 'ANY', - (nightwatchClient.options.desiredCapabilities.browserName || 'UNKNOWN'), - (nightwatchClient.options.desiredCapabilities.version || 'UNKNOWN'), - nightwatchClient.currentTest.name, - fileName.replace(/ /g, '_') - ) + return path.join( + nightwatchClient.options.screenshotsPath || + basePath || + "reports/screenshots", + nightwatchClient.options.desiredCapabilities.platform || "ANY", + nightwatchClient.options.desiredCapabilities.browserName || "UNKNOWN", + nightwatchClient.options.desiredCapabilities.version || "UNKNOWN", + nightwatchClient.currentTest.name, + fileName.replace(/ /g, "_") + ); } module.exports = { - "src_folders": [ - "demo/tests" - ], - "custom_assertions_path": [ - path.join(process.cwd(), "assertions") - ], - "custom_commands_path": [ - path.join(process.cwd(), "commands") - ], - "output_folder": REPORTS_PATH, - "selenium": { - "start_process": true, - "server_path": SELENIUM_PATH, - "host": "127.0.0.1", - "port": 4444, - "cli_args": { - "webdriver.chrome.driver": CHROME_PATH, - "webdriver.gecko.driver": GECKO_PATH, - "webdriver.ghost.driver": GHOST_PATH - } - }, - "test_settings": { - "default": { - "silent": true, - "visual_regression_settings": { - "generate_screenshot_path": defaultScreenshotPath, - //"latest_screenshots_path": '', - "latest_suffix": '.latest', - //"baseline_screenshots_path": '', - "baseline_suffix": '.baseline', - //"diff_screenshots_path": '' - "diff_suffix": '.diff', - "threshold": 0.01, - "prompt": true, - "always_save_diff_screenshot": false - }, - "screenshots": { - "enabled": true, - "path": SCREENSHOT_PATH, - "on_failure": false, - "on_error": false - }, - "globals": { - "prompt": DEVELOPMENT, - "waitForConditionTimeout": 5000 - }, - "desiredCapabilities": { - "platform": "LINUX", - "version": "latest", - "browserName": "phantomjs" - } - }, - "phantomjs": { - "desiredCapabilities": { - "browserName": "phantomjs", - "javascriptEnabled": true, - "acceptSslCerts": true, - "phantomjs.binary.path": PHANTOMJS_PATH, - "phantomjs.cli.args": [] - } - }, - "chrome": { - "desiredCapabilities": { - "browserName": "chrome", - "javascriptEnabled": true, - "acceptSslCerts": true, - "chromeOptions": { - "args": ["--start-fullscreen"] - } - } - }, - "firefox": { - "desiredCapabilities": { - "browserName": "firefox", - "javascriptEnabled": true, - "acceptSslCerts": true, - "marionette": true, - } - } - } -} + "src_folders": ["demo/tests"], + "custom_assertions_path": [path.join(process.cwd(), "assertions")], + "custom_commands_path": [path.join(process.cwd(), "commands")], + "output_folder": REPORTS_PATH, + "selenium": { + "start_process": true, + "server_path": SELENIUM_PATH, + "host": "127.0.0.1", + "port": 4444, + "cli_args": { + "webdriver.chrome.driver": CHROME_PATH, + "webdriver.gecko.driver": GECKO_PATH, + "webdriver.ghost.driver": GHOST_PATH + } + }, + "test_settings": { + "default": { + "silent": true, + "visual_regression_settings": { + "generate_screenshot_path": defaultScreenshotPath, + //"latest_screenshots_path": '', + "latest_suffix": ".latest", + //"baseline_screenshots_path": '', + "baseline_suffix": ".baseline", + //"diff_screenshots_path": '' + "diff_suffix": ".diff", + "threshold": 0.01, + "prompt": true, + "always_save_diff_screenshot": false + }, + "screenshots": { + "enabled": true, + "path": SCREENSHOT_PATH, + "on_failure": false, + "on_error": false + }, + "globals": { + "prompt": DEVELOPMENT, + "waitForConditionTimeout": 5000 + }, + "desiredCapabilities": { + "platform": "LINUX", + "version": "latest", + "browserName": "phantomjs" + } + }, + "phantomjs": { + "desiredCapabilities": { + "browserName": "phantomjs", + "javascriptEnabled": true, + "acceptSslCerts": true, + "phantomjs.binary.path": PHANTOMJS_PATH, + "phantomjs.cli.args": [] + } + }, + "chrome": { + "desiredCapabilities": { + "browserName": "chrome", + "javascriptEnabled": true, + "acceptSslCerts": true, + "chromeOptions": { + "args": ["--start-fullscreen"] + } + } + }, + "firefox": { + "desiredCapabilities": { + "browserName": "firefox", + "javascriptEnabled": true, + "acceptSslCerts": true, + "marionette": true + } + } + } +}; -fs.stat(SELENIUM_PATH, function(err, stat) { - if (err || !stat || stat.size < 1) { - rimraf(path.join(BINPATH, 'chromedriver'), function(rmerr) { - if (rmerr) throw new Error(rmerr) - seleniumStandAlone.install({ - basePath: BINPATH, - version: SELENIUM_VERSION, - baseURL: 'https://selenium-release.storage.googleapis.com', - drivers: { - chrome: { - version: CHROME_DRIVER_VERSION, - arch: process.arch, - baseURL: 'https://chromedriver.storage.googleapis.com' - }, - ie: { - version: IE_DRIVER_VERSION, - arch: process.arch, - baseURL: 'https://selenium-release.storage.googleapis.com' - }, - firefox: { - version: GECKO_DRIVER_VERSION, - arch: process.arch, - baseURL: 'https://github.com/mozilla/geckodriver/releases/download' - } - }, - logger: function(message) {}, - progressCb: function(totalLength, progressLength, chunkLength) {} - }, function(error, child) { - if (error) throw new Error(error) - console.log(' \x1b[32m✔\x1b[0m Drivers downloaded to:', BINPATH) - }) - }) - } -}) +fs.stat(SELENIUM_PATH, function (err, stat) { + if (err || !stat || stat.size < 1) { + rimraf(path.join(BINPATH, "chromedriver"), function (rmerr) { + if (rmerr) throw new Error(rmerr); + seleniumStandAlone.install( + { + "basePath": BINPATH, + "version": SELENIUM_VERSION, + "baseURL": "https://selenium-release.storage.googleapis.com", + "drivers": { + "chrome": { + "version": CHROME_DRIVER_VERSION, + "arch": process.arch, + "baseURL": "https://chromedriver.storage.googleapis.com" + }, + "ie": { + "version": IE_DRIVER_VERSION, + "arch": process.arch, + "baseURL": "https://selenium-release.storage.googleapis.com" + }, + "firefox": { + "version": GECKO_DRIVER_VERSION, + "arch": process.arch, + "baseURL": + "https://github.com/mozilla/geckodriver/releases/download" + } + }, + "logger": function (message) {}, + "progressCb": function (totalLength, progressLength, chunkLength) {} + }, + function (error, child) { + if (error) throw new Error(error); + console.log(" \x1b[32m✔\x1b[0m Drivers downloaded to:", BINPATH); + } + ); + }); + } +}); diff --git a/demo/tests/demo.e2e.js b/demo/tests/demo.e2e.js index e95f6b1..9f9f949 100644 --- a/demo/tests/demo.e2e.js +++ b/demo/tests/demo.e2e.js @@ -1,12 +1,12 @@ -'use strict' +"use strict"; module.exports = { - 'Render test': function (browser) { - browser - .url('http://localhost:8080/demo2/') - .waitForElementVisible('body', 1000) - .resizeWindow(1024, 768) - .assert.screenshotIdenticalToBaseline('body h1') - .end() - } -} + "Render test": function (browser) { + browser + .url("http://localhost:8080/demo2/") + .waitForElementVisible("body", 1000) + .resizeWindow(1024, 768) + .assert.screenshotIdenticalToBaseline("body h1") + .end(); + } +}; diff --git a/lib/cleanup-screenshots.js b/lib/cleanup-screenshots.js index d3d0728..8625e27 100644 --- a/lib/cleanup-screenshots.js +++ b/lib/cleanup-screenshots.js @@ -1,6 +1,6 @@ -'use strict' +"use strict"; -const { unlink } = require('fs') +const { unlink } = require("fs"); /** * Removes any leftover latest screenshots or diffs. @@ -9,15 +9,12 @@ const { unlink } = require('fs') * @param {String} diffPath Path to the saved diff screenshot. * @return {Promise} A promise that resolves successfully once the images are removed */ -module.exports = function cleanupScreenshots( - latestPath, - diffPath -) { - return new Promise((resolve) => { - unlink(latestPath, () => { - unlink(diffPath, () => { - resolve(true) - }) - }) - }) -} +module.exports = function cleanupScreenshots(latestPath, diffPath) { + return new Promise((resolve) => { + unlink(latestPath, () => { + unlink(diffPath, () => { + resolve(true); + }); + }); + }); +}; diff --git a/lib/compare-with-baseline.js b/lib/compare-with-baseline.js index 919dcb7..927836a 100644 --- a/lib/compare-with-baseline.js +++ b/lib/compare-with-baseline.js @@ -1,13 +1,13 @@ -'use strict' +"use strict"; -const Jimp = require('jimp'), - getBaselineScreenshotOrCreate = require('./get-baseline-screenshot-or-create'), - saveScreenshot = require('./save-screenshot'), - generateScreenshotFilePath = require('./generate-screenshot-file-path'), - getVrtSettings = require('./get-vrt-settings'), - promptScreenshotOverride = require('./prompt-screenshot-override'), - overrideBaseline = require('./override-baseline'), - cleanupScreenshots = require('./cleanup-screenshots') +const Jimp = require("jimp"), + getBaselineScreenshotOrCreate = require("./get-baseline-screenshot-or-create"), + saveScreenshot = require("./save-screenshot"), + generateScreenshotFilePath = require("./generate-screenshot-file-path"), + getVrtSettings = require("./get-vrt-settings"), + promptScreenshotOverride = require("./prompt-screenshot-override"), + overrideBaseline = require("./override-baseline"), + cleanupScreenshots = require("./cleanup-screenshots"); /** * Compares a screenshot against the baseline screenshot. If the baseline screenshot @@ -20,113 +20,95 @@ const Jimp = require('jimp'), * @param {Object} overrideSettings Optional override settings */ module.exports = function compareWithBaseline( - nightwatchClient, - screenshot, - fileName, - overrideSettings + nightwatchClient, + screenshot, + fileName, + overrideSettings ) { - const { - latest_screenshots_path, - latest_suffix, - baseline_screenshots_path, - baseline_suffix, - diff_screenshots_path, - diff_suffix, - threshold, - prompt, - always_save_diff_screenshot - } = getVrtSettings(nightwatchClient, overrideSettings), - completeLatestPath = generateScreenshotFilePath( - nightwatchClient, - latest_screenshots_path, - `${fileName}${latest_suffix}` - ), - completeBaselinePath = generateScreenshotFilePath( - nightwatchClient, - baseline_screenshots_path, - `${fileName}${baseline_suffix}` - ), - completeDiffPath = generateScreenshotFilePath( - nightwatchClient, - diff_screenshots_path, - `${fileName}${diff_suffix}` - ) + const { + latest_screenshots_path, + latest_suffix, + baseline_screenshots_path, + baseline_suffix, + diff_screenshots_path, + diff_suffix, + threshold, + prompt, + always_save_diff_screenshot + } = getVrtSettings(nightwatchClient, overrideSettings), + completeLatestPath = generateScreenshotFilePath( + nightwatchClient, + latest_screenshots_path, + `${fileName}${latest_suffix}` + ), + completeBaselinePath = generateScreenshotFilePath( + nightwatchClient, + baseline_screenshots_path, + `${fileName}${baseline_suffix}` + ), + completeDiffPath = generateScreenshotFilePath( + nightwatchClient, + diff_screenshots_path, + `${fileName}${diff_suffix}` + ); - return new Promise((resolve, reject) => { - getBaselineScreenshotOrCreate( - nightwatchClient, - screenshot, - completeBaselinePath - ).then((baseline) => { - const diff = Jimp.diff(screenshot, baseline), - identical = diff.percent <= (Number.isFinite(threshold) ? threshold : 0.0) + return new Promise((resolve, reject) => { + getBaselineScreenshotOrCreate( + nightwatchClient, + screenshot, + completeBaselinePath + ).then((baseline) => { + const diff = Jimp.diff(screenshot, baseline), + identical = + diff.percent <= (Number.isFinite(threshold) ? threshold : 0.0); - if (!identical && prompt === true) { - saveScreenshot( - completeLatestPath, - screenshot - ) - .then(() => saveScreenshot( - completeDiffPath, - diff.image - ), resolve) - .then(() => promptScreenshotOverride( - completeLatestPath, - completeBaselinePath, - completeDiffPath - ), resolve) - .then( - () => overrideBaseline( - completeLatestPath, - completeBaselinePath - ).then(() => cleanupScreenshots( - completeLatestPath, - completeDiffPath - ), resolve), - resolve - ) - .then( - resolve - ) - } else if (!identical && always_save_diff_screenshot === true) { - nightwatchClient.assert.ok(true, 'Settings enforced overriding baseline screenshot.') // eslint-disable-line max-len - saveScreenshot( - completeBaselinePath, - screenshot - ) - .then(() => { - resolve(true) - }) - .catch(() => resolve(false)) - } else if (!identical && !prompt && !always_save_diff_screenshot) { - saveScreenshot( - completeLatestPath, - screenshot - ) - .then(() => saveScreenshot( - completeDiffPath, - diff.image - ), resolve) - .then(() => ( - completeLatestPath, - completeBaselinePath, - completeDiffPath - ), resolve) - .then( - resolve - ) - } else if (identical) { - // Cleanup here in case user fixed bug and reran tests - cleanupScreenshots( - completeLatestPath, - completeDiffPath - ) - .then(() => { - resolve(identical) - }) - } else { - resolve(identical) - } - }, reject) - }) -} + if (!identical && prompt === true) { + saveScreenshot(completeLatestPath, screenshot) + .then(() => saveScreenshot(completeDiffPath, diff.image), resolve) + .then( + () => + promptScreenshotOverride( + completeLatestPath, + completeBaselinePath, + completeDiffPath + ), + resolve + ) + .then( + () => + overrideBaseline(completeLatestPath, completeBaselinePath).then( + () => cleanupScreenshots(completeLatestPath, completeDiffPath), + resolve + ), + resolve + ) + .then(resolve); + } else if (!identical && always_save_diff_screenshot === true) { + nightwatchClient.assert.ok( + true, + "Settings enforced overriding baseline screenshot." + ); // eslint-disable-line max-len + saveScreenshot(completeBaselinePath, screenshot) + .then(() => { + resolve(true); + }) + .catch(() => resolve(false)); + } else if (!identical && !prompt && !always_save_diff_screenshot) { + saveScreenshot(completeLatestPath, screenshot) + .then(() => saveScreenshot(completeDiffPath, diff.image), resolve) + .then( + () => (completeLatestPath, completeBaselinePath, completeDiffPath), + resolve + ) + .then(resolve); + } else if (identical) { + // Cleanup here in case user fixed bug and reran tests + cleanupScreenshots(completeLatestPath, completeDiffPath).then(() => { + resolve(identical); + }); + } else { + resolve(identical); + } + }, reject); + }); +}; diff --git a/lib/generate-screenshot-file-path.js b/lib/generate-screenshot-file-path.js index 33c841b..8a5a0fd 100644 --- a/lib/generate-screenshot-file-path.js +++ b/lib/generate-screenshot-file-path.js @@ -1,13 +1,12 @@ -'use strict' - -const kebabCase = require('lodash/kebabCase'), - path = require('path'), - get = require('lodash/get'), - getVrtSettings = require('./get-vrt-settings') +"use strict"; +const kebabCase = require("lodash/kebabCase"), + path = require("path"), + get = require("lodash/get"), + getVrtSettings = require("./get-vrt-settings"); function appendExtensionToFilename(fileName) { - return fileName ? `${fileName}.png` : undefined + return fileName ? `${fileName}.png` : undefined; } /** @@ -24,12 +23,12 @@ function appendExtensionToFilename(fileName) { * @param {String} [fileName] A custom filename for the screenshot */ function defaultScreenshotFilePath(nightwatchClient, basePath, fileName) { - const moduleName = nightwatchClient.currentTest.module, - testName = nightwatchClient.currentTest.name, - kebabName = `${kebabCase(testName)}`, - screenShotName = appendExtensionToFilename(fileName || kebabName) + const moduleName = nightwatchClient.currentTest.module, + testName = nightwatchClient.currentTest.name, + kebabName = `${kebabCase(testName)}`, + screenShotName = appendExtensionToFilename(fileName || kebabName); - return path.join(process.cwd(), basePath, moduleName, screenShotName) + return path.join(process.cwd(), basePath, moduleName, screenShotName); } /** @@ -41,13 +40,20 @@ function defaultScreenshotFilePath(nightwatchClient, basePath, fileName) { * the location where the screenshot will be stored or read from. * @param {String} [fileName] A custom filename for the screenshot */ -module.exports = function generateScreenshotFilePath(nightwatchClient, basePath, fileName) { - const globalSettings = getVrtSettings(nightwatchClient) - - if (globalSettings && globalSettings.generate_screenshot_path) { - return globalSettings.generate_screenshot_path( - nightwatchClient, basePath, appendExtensionToFilename(fileName)) - } - - return defaultScreenshotFilePath(nightwatchClient, basePath, fileName) -} +module.exports = function generateScreenshotFilePath( + nightwatchClient, + basePath, + fileName +) { + const globalSettings = getVrtSettings(nightwatchClient); + + if (globalSettings && globalSettings.generate_screenshot_path) { + return globalSettings.generate_screenshot_path( + nightwatchClient, + basePath, + appendExtensionToFilename(fileName) + ); + } + + return defaultScreenshotFilePath(nightwatchClient, basePath, fileName); +}; diff --git a/lib/get-baseline-screenshot-or-create.js b/lib/get-baseline-screenshot-or-create.js index cf499ce..d9963cf 100644 --- a/lib/get-baseline-screenshot-or-create.js +++ b/lib/get-baseline-screenshot-or-create.js @@ -1,8 +1,8 @@ -'use strict' +"use strict"; -const saveScreenshot = require('./save-screenshot'), - fs = require('fs'), - Jimp = require('jimp') +const saveScreenshot = require("./save-screenshot"), + fs = require("fs"), + Jimp = require("jimp"); /** * Retrieves the baseline screenshot for the running test. If the baseline @@ -17,22 +17,21 @@ const saveScreenshot = require('./save-screenshot'), * @return {Promise} A promise that resolves with the baseline screenshot */ module.exports = function getBaselineScreenshotOrCreate( - nightwatchClient, - screenshot, - baselinePath + nightwatchClient, + screenshot, + baselinePath ) { - return new Promise((resolve, reject) => { - fs.stat(baselinePath, (err, stat) => { - if (!err && stat.isFile()) { - Jimp.read(baselinePath).then(resolve, reject) - } else { - nightwatchClient.assert.ok(true, 'Baseline screenshot does not exist; saving current screenshot to the baseline directory.') // eslint-disable-line max-len - saveScreenshot( - baselinePath, - screenshot - ) - .then(resolve, resolve) - } - }) - }) -} + return new Promise((resolve, reject) => { + fs.stat(baselinePath, (err, stat) => { + if (!err && stat.isFile()) { + Jimp.read(baselinePath).then(resolve, reject); + } else { + nightwatchClient.assert.ok( + true, + "Baseline screenshot does not exist; saving current screenshot to the baseline directory." + ); // eslint-disable-line max-len + saveScreenshot(baselinePath, screenshot).then(resolve, resolve); + } + }); + }); +}; diff --git a/lib/get-vrt-settings.js b/lib/get-vrt-settings.js index ff3e4db..ed0b625 100644 --- a/lib/get-vrt-settings.js +++ b/lib/get-vrt-settings.js @@ -1,7 +1,7 @@ -'use strict' +"use strict"; -const get = require('lodash/get') -const isEmpty = require('lodash/isEmpty') +const get = require("lodash/get"); +const isEmpty = require("lodash/isEmpty"); /** * Get the visual regression tests settings from the nightwatch configuration file. @@ -11,28 +11,28 @@ const isEmpty = require('lodash/isEmpty') * @return {NightwatchVRTSettings} An object containing the visual regression test settings. */ module.exports = function getVrtSettings(nightwatchClient, overrideSettings) { - const visualRegressionSettingsPaths = [ - 'globals.visual_regression_settings', - 'globals.test_settings.visual_regression_settings' - ] + const visualRegressionSettingsPaths = [ + "globals.visual_regression_settings", + "globals.test_settings.visual_regression_settings" + ]; - const settings = visualRegressionSettingsPaths.map((settingPath) => - get(nightwatchClient, settingPath, null) - ).filter((result) => !isEmpty(result))[0] + const settings = visualRegressionSettingsPaths + .map((settingPath) => get(nightwatchClient, settingPath, null)) + .filter((result) => !isEmpty(result))[0]; - return Object.assign( - { - latest_screenshots_path: 'vrt/latest', - latest_suffix: '', - baseline_screenshots_path: 'vrt/baseline', - baseline_suffix: '', - diff_screenshots_path: 'vrt/diff', - diff_suffix: '', - threshold: 0.0, - prompt: false, - always_save_diff_screenshot: false - }, - settings, - overrideSettings - ) -} + return Object.assign( + { + "latest_screenshots_path": "vrt/latest", + "latest_suffix": "", + "baseline_screenshots_path": "vrt/baseline", + "baseline_suffix": "", + "diff_screenshots_path": "vrt/diff", + "diff_suffix": "", + "threshold": 0.0, + "prompt": false, + "always_save_diff_screenshot": false + }, + settings, + overrideSettings + ); +}; diff --git a/lib/override-baseline.js b/lib/override-baseline.js index e61a26e..287309e 100644 --- a/lib/override-baseline.js +++ b/lib/override-baseline.js @@ -1,6 +1,6 @@ -'use strict' +"use strict"; -const { rename } = require('fs') +const { rename } = require("fs"); /** * Overrides the baseline screenshot with the latest @@ -10,21 +10,14 @@ const { rename } = require('fs') * @return {Promise} A promise that resolves successfully once the baseline has * been overridden. */ -module.exports = function overrideBaseline( - latestPath, - baselinePath -) { - return new Promise((resolve, reject) => { - rename( - latestPath, - baselinePath, - (error) => { - if (error) { - reject(error) - } +module.exports = function overrideBaseline(latestPath, baselinePath) { + return new Promise((resolve, reject) => { + rename(latestPath, baselinePath, (error) => { + if (error) { + reject(error); + } - resolve(true) - } - ) - }) -} + resolve(true); + }); + }); +}; diff --git a/lib/promisify-command.js b/lib/promisify-command.js index 91ae1ef..c04ace6 100644 --- a/lib/promisify-command.js +++ b/lib/promisify-command.js @@ -1,4 +1,4 @@ -'use strict' +"use strict"; /** * Wraps a nightwatch api command in a promise @@ -10,13 +10,15 @@ * @return {Promise} */ module.exports = function promisifyCommand(api, commandName, args = []) { - return new Promise((resolve, reject) => { - api[commandName](...args.concat((result) => { - if (result.status === 0) { - resolve(result.value) - } else { - reject(result.state) - } - })) - }) -} + return new Promise((resolve, reject) => { + api[commandName]( + ...args.concat((result) => { + if (result.status === 0) { + resolve(result.value); + } else { + reject(result.state); + } + }) + ); + }); +}; diff --git a/lib/prompt-screenshot-override.js b/lib/prompt-screenshot-override.js index 367ee22..e07453d 100644 --- a/lib/prompt-screenshot-override.js +++ b/lib/prompt-screenshot-override.js @@ -1,21 +1,30 @@ -'use strict' +"use strict"; -const readline = require('readline') +const readline = require("readline"); -const GREEN = '\x1b[32m', - RED = '\x1b[31m', - YELLOW = '\x1b[33m', - BLUE = '\x1b[34m', - RESET = '\x1b[0m', - BRIGHT = '\x1b[1m' +const GREEN = "\x1b[32m", + RED = "\x1b[31m", + YELLOW = "\x1b[33m", + BLUE = "\x1b[34m", + RESET = "\x1b[0m", + BRIGHT = "\x1b[1m"; function error_screenshots_differ(latestPath, expectedPath, diffPath) { - return `\ + return `\ ${RED}✗${RESET} Latest screenshot does not match baseline - ${RED}├${RESET} ${RED}Latest${RESET}: file://${latestPath.replace(/ /g, '%20')} - ${RED}├${RESET} ${GREEN}Expected${RESET}: file://${expectedPath.replace(/ /g, '%20')} - ${RED}└${RESET} ${YELLOW}Difference${RESET}: file://${diffPath.replace(/ /g, '%20')} - ${BLUE}?${RESET} Override baseline? ${BRIGHT}(y,N)${RESET} ` + ${RED}├${RESET} ${RED}Latest${RESET}: file://${latestPath.replace( + / /g, + "%20" + )} + ${RED}├${RESET} ${GREEN}Expected${RESET}: file://${expectedPath.replace( + / /g, + "%20" + )} + ${RED}└${RESET} ${YELLOW}Difference${RESET}: file://${diffPath.replace( + / /g, + "%20" + )} + ${BLUE}?${RESET} Override baseline? ${BRIGHT}(y,N)${RESET} `; } /** @@ -29,27 +38,27 @@ function error_screenshots_differ(latestPath, expectedPath, diffPath) { * override, or false otherwise. Default response is no. */ module.exports = function promptScreenshotOverride( - latestPath, - expectedPath, - diffPath + latestPath, + expectedPath, + diffPath ) { - return new Promise((resolve, reject) => { - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }) + return new Promise((resolve, reject) => { + const rl = readline.createInterface({ + "input": process.stdin, + "output": process.stdout + }); - rl.question( - error_screenshots_differ(latestPath, expectedPath, diffPath), - (response) => { - if (response.toUpperCase().includes('Y')) { - rl.close() - resolve(true) - } else { - rl.close() - reject(new Error('User refused to override baseline')) - } - } - ) - }) -} + rl.question( + error_screenshots_differ(latestPath, expectedPath, diffPath), + (response) => { + if (response.toUpperCase().includes("Y")) { + rl.close(); + resolve(true); + } else { + rl.close(); + reject(new Error("User refused to override baseline")); + } + } + ); + }); +}; diff --git a/lib/save-screenshot.js b/lib/save-screenshot.js index 4c14e53..0f52e90 100644 --- a/lib/save-screenshot.js +++ b/lib/save-screenshot.js @@ -1,4 +1,4 @@ -'use strict' +"use strict"; /** * Saves a screenshot image to disk. @@ -10,13 +10,13 @@ * A rejected promise indicates failure. */ module.exports = function saveScreenshot(path, screenshot) { - return new Promise((resolve, reject) => { - screenshot.write(path, (error) => { - if (error) { - reject(error) - } else { - resolve(screenshot) - } - }) - }) -} + return new Promise((resolve, reject) => { + screenshot.write(path, (error) => { + if (error) { + reject(error); + } else { + resolve(screenshot); + } + }); + }); +}; diff --git a/package.json b/package.json index 02c6706..25a3d45 100644 --- a/package.json +++ b/package.json @@ -1,74 +1,76 @@ { - "name": "nightwatch-vrt", - "version": "0.2.8", - "description": "Nightwatch Visual Regression Testing tools", - "license": "MIT", - "author": "Crunch.io ", - "contributors": [ - { - "name": "Connor Schlesiger", - "email": "connor@schlesiger.ca" - }, - { - "name": "Matt Steitle", - "email": "msteitle@crunch.io" - } - ], - "keywords": [ - "selenium", - "selenium-webdriver", - "css-testing", - "nightwatchjs", - "e2e-tests", - "visual-regression-testing", - "nightwatch" - ], - "homepage": "https://github.com/Crunch-io/nightwatch-vrt", - "repository": { - "type": "git", - "url": "git+https://github.com/Crunch-io/nightwatch-vrt.git" - }, - "bugs": { - "url": "https://github.com/Crunch-io/nightwatch-vrt/issues" - }, - "types": "index", - "scripts": { - "lint": "eslint lib assertions commands", - "test:dev": "jest --watch --notify", - "test": "jest --coverage", - "clean": "rimraf node_modules package-lock.json reports", - "demo": "node demo/nightwatch.conf.js && run-p --race demo:start demo:nightwatch", - "demo:start": "http-server demo --silent", - "demo:nightwatch": "sleep 1 && nightwatch --config demo/nightwatch.conf.js --env phantomjs" - }, - "jest": { - "roots": [ - "lib", - "assertions", - "commands", - "tests" - ], - "testRegex": "-test\\.js$", - "coverageDirectory": "reports/coverage", - "coverageReporters": [ - "text-summary", - "html" - ] - }, - "dependencies": { - "jimp": "^0.16.1", - "lodash": "^4.17.20" - }, - "devDependencies": { - "eslint": "^7.11.0", - "eslint-config-crunch": "^1.8.0", - "eslint-plugin-react": "^7.21.4", - "http-server": "^0.12.3", - "jest": "^26.6.0", - "nightwatch": "^1.4.3", - "npm-run-all": "^4.1.5", - "phantomjs-prebuilt": "^2.1.16", - "rimraf": "^3.0.2", - "selenium-standalone": "^6.20.1" - } + "name": "nightwatch-vrt", + "version": "0.2.8", + "description": "Nightwatch Visual Regression Testing tools", + "license": "MIT", + "author": "Crunch.io ", + "contributors": [ + { + "name": "Connor Schlesiger", + "email": "connor@schlesiger.ca" + }, + { + "name": "Matt Steitle", + "email": "msteitle@crunch.io" + } + ], + "keywords": [ + "selenium", + "selenium-webdriver", + "css-testing", + "nightwatchjs", + "e2e-tests", + "visual-regression-testing", + "nightwatch" + ], + "homepage": "https://github.com/Crunch-io/nightwatch-vrt", + "repository": { + "type": "git", + "url": "git+https://github.com/Crunch-io/nightwatch-vrt.git" + }, + "bugs": { + "url": "https://github.com/Crunch-io/nightwatch-vrt/issues" + }, + "types": "index", + "scripts": { + "lint": "eslint . --fix", + "pretty": "prettier --write \"./**/*.{css,html,js,json,xml}\"", + "test:dev": "jest --watch --notify", + "test": "jest --coverage", + "clean": "rimraf node_modules package-lock.json reports", + "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\"", + "demo": "node demo/nightwatch.conf.js && run-p --race demo:start demo:nightwatch", + "demo:start": "http-server demo --silent", + "demo:nightwatch": "sleep 1 && nightwatch --config demo/nightwatch.conf.js --env phantomjs" + }, + "jest": { + "roots": ["lib", "assertions", "commands", "tests"], + "testRegex": "-test\\.js$", + "coverageDirectory": "reports/coverage", + "coverageReporters": ["text-summary", "html"] + }, + "dependencies": { + "jimp": "^0.16.2", + "lodash": "^4.17.21" + }, + "devDependencies": { + "@prettier/plugin-xml": "^2.2.0", + "eslint": "^8.19.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.2.1", + "http-server": "^14.1.1", + "husky": "^8.0.3", + "jest": "^29.4.0", + "lint-staged": "^13.0.3", + "nightwatch": "^2.6.10", + "npm-run-all": "^4.1.5", + "phantomjs-prebuilt": "^2.1.16", + "prettier": "^2.8.3", + "rimraf": "^4.1.2", + "selenium-standalone": "^8.2.5" + }, + "lint-staged": { + "*.{js}": ["eslint --cache --fix", "prettier --write"], + "*.{css,html,json,xml}": "prettier --write" + } } diff --git a/tests/lib/generate-screenshot-file-path-test.js b/tests/lib/generate-screenshot-file-path-test.js index f385c30..2d6e730 100644 --- a/tests/lib/generate-screenshot-file-path-test.js +++ b/tests/lib/generate-screenshot-file-path-test.js @@ -1,61 +1,113 @@ -const generateScreenshotFilePath = require('../../lib/generate-screenshot-file-path') -const path = require('path') -const set = require('lodash/set') - -describe('generateScreenshotFilePath', () => { - function getNightwatchClient() { - return { - currentTest: { - module: 'visualizations', - name: 'barPlots' - }, - globals: { - visual_regression_settings: {}, - test_settings: { visual_regression_settings: {} } - } - } - } - - it('should generate a file path by using the basePath parameter, and the current test name and module', () => { - expect(generateScreenshotFilePath(getNightwatchClient(), 'baseline')) - .toEqual(path.resolve(`${process.cwd()}/baseline/visualizations/bar-plots.png`)) - }) - - it('should generate a file path by using the basePath parameter, and a custom filename', () => { - expect(generateScreenshotFilePath(getNightwatchClient(), 'baseline', 'foo-test')) - .toEqual(path.resolve(`${process.cwd()}/baseline/visualizations/foo-test.png`)) - }) - - it('should pass the correct filename to the custom naming function', () => { - const nightwatchClient = getNightwatchClient() - const testFn = jest.fn((client, basePath, fileName) => - path.join(process.cwd(), basePath, client.currentTest.module, `test-setting-custom-${fileName}`)) - - set(nightwatchClient, 'globals.test_settings.visual_regression_settings.generate_screenshot_path', testFn) - - const result = generateScreenshotFilePath(nightwatchClient, 'baseline', 'foo-test') - const expected = path.resolve(`${process.cwd()}/baseline/visualizations/test-setting-custom-foo-test.png`) - - expect(testFn).toHaveBeenCalled() - expect(result).toEqual(expected) - }) - - it('should use the base global setting for generate_screenshot_path if a test_setting exists', () => { - const nightwatchClient = getNightwatchClient() - const testFn = jest.fn((client, basePath, fileName) => - path.join(process.cwd(), basePath, client.currentTest.module, `test-setting-custom-${fileName}`)) - - set(nightwatchClient, 'globals.test_settings.visual_regression_settings.generate_screenshot_path', testFn) - - const customFn = jest.fn((client, basePath, fileName) => - path.join(process.cwd(), basePath, client.currentTest.module, `custom-${fileName}`)) - - set(nightwatchClient, 'globals.visual_regression_settings.generate_screenshot_path', customFn) - set(nightwatchClient, 'globals.test_settings.visual_regression_settings.generate_screenshot_path', testFn) - - const result = generateScreenshotFilePath(nightwatchClient, 'baseline', 'foo-test') - const expected = path.resolve(`${process.cwd()}/baseline/visualizations/custom-foo-test.png`) - - expect(result).toEqual(expected) - }) -}) +const generateScreenshotFilePath = require("../../lib/generate-screenshot-file-path"); +const path = require("path"); +const set = require("lodash/set"); + +describe("generateScreenshotFilePath", () => { + function getNightwatchClient() { + return { + "currentTest": { + "module": "visualizations", + "name": "barPlots" + }, + "globals": { + "visual_regression_settings": {}, + "test_settings": { "visual_regression_settings": {} } + } + }; + } + + it("should generate a file path by using the basePath parameter, and the current test name and module", () => { + expect( + generateScreenshotFilePath(getNightwatchClient(), "baseline") + ).toEqual( + path.resolve(`${process.cwd()}/baseline/visualizations/bar-plots.png`) + ); + }); + + it("should generate a file path by using the basePath parameter, and a custom filename", () => { + expect( + generateScreenshotFilePath(getNightwatchClient(), "baseline", "foo-test") + ).toEqual( + path.resolve(`${process.cwd()}/baseline/visualizations/foo-test.png`) + ); + }); + + it("should pass the correct filename to the custom naming function", () => { + const nightwatchClient = getNightwatchClient(); + const testFn = jest.fn((client, basePath, fileName) => + path.join( + process.cwd(), + basePath, + client.currentTest.module, + `test-setting-custom-${fileName}` + ) + ); + + set( + nightwatchClient, + "globals.test_settings.visual_regression_settings.generate_screenshot_path", + testFn + ); + + const result = generateScreenshotFilePath( + nightwatchClient, + "baseline", + "foo-test" + ); + const expected = path.resolve( + `${process.cwd()}/baseline/visualizations/test-setting-custom-foo-test.png` + ); + + expect(testFn).toHaveBeenCalled(); + expect(result).toEqual(expected); + }); + + it("should use the base global setting for generate_screenshot_path if a test_setting exists", () => { + const nightwatchClient = getNightwatchClient(); + const testFn = jest.fn((client, basePath, fileName) => + path.join( + process.cwd(), + basePath, + client.currentTest.module, + `test-setting-custom-${fileName}` + ) + ); + + set( + nightwatchClient, + "globals.test_settings.visual_regression_settings.generate_screenshot_path", + testFn + ); + + const customFn = jest.fn((client, basePath, fileName) => + path.join( + process.cwd(), + basePath, + client.currentTest.module, + `custom-${fileName}` + ) + ); + + set( + nightwatchClient, + "globals.visual_regression_settings.generate_screenshot_path", + customFn + ); + set( + nightwatchClient, + "globals.test_settings.visual_regression_settings.generate_screenshot_path", + testFn + ); + + const result = generateScreenshotFilePath( + nightwatchClient, + "baseline", + "foo-test" + ); + const expected = path.resolve( + `${process.cwd()}/baseline/visualizations/custom-foo-test.png` + ); + + expect(result).toEqual(expected); + }); +}); diff --git a/tests/lib/get-vrt-settings-test.js b/tests/lib/get-vrt-settings-test.js index c81f522..2b074d7 100644 --- a/tests/lib/get-vrt-settings-test.js +++ b/tests/lib/get-vrt-settings-test.js @@ -1,83 +1,81 @@ -'use strict' - -const getVrtSettings = require('../../lib/get-vrt-settings'), - defaultSettings = { - latest_screenshots_path: 'vrt/latest', - latest_suffix: '', - baseline_screenshots_path: 'vrt/baseline', - baseline_suffix: '', - diff_screenshots_path: 'vrt/diff', - diff_suffix: '', - threshold: 0.0, - prompt: false, - always_save_diff_screenshot: false - } - -describe('getVrtSettings', () => { - function getNightwatchClient(customSettings = {}) { - return { - assert: { - ok: jest.fn() - } - } - } - - describe('when getting visual regression settings', () => { - - describe('given no visual regression settings defined', () => { - it('should return default settings', () => { - const nightwatchClient = getNightwatchClient() - const settings = getVrtSettings(nightwatchClient) - - expect(settings).toEqual(defaultSettings) - }) - }) - - describe('given visual regression settings are defined in the nightwatch globals settings section', () => { - - it('should return the defined settings', () => { - const nightwatchClient = getNightwatchClient() - const vrtSettings = { - threshold: 0.2, - diff_screenshots_path: 'vrt/custom-diffs' - } - - nightwatchClient.globals = { - visual_regression_settings: vrtSettings - } - - const settings = getVrtSettings(nightwatchClient) - expect(settings).toMatchObject(vrtSettings) - }) - }) - - describe('given visual regression settings are defined in the nightwatch globals settings section within a test_settings object', () => { - - it('should return the defined settings', () => { - const nightwatchClient = getNightwatchClient() - const vrtSettings = { - threshold: 0.2, - diff_screenshots_path: 'vrt/custom-diffs' - } - - nightwatchClient.globals = { - test_settings: { visual_regression_settings: vrtSettings } - } - - const settings = getVrtSettings(nightwatchClient) - expect(settings).toMatchObject(vrtSettings) - }) - }) - - describe('given partial test-scoped visual regression settings defined', () => { - it('should return default settings', () => { - const nightwatchClient = getNightwatchClient() - const settings = getVrtSettings(nightwatchClient, {threshold: 0.5}) - const modifiedSettings = Object.assign({}, defaultSettings, {threshold: 0.5}) - - expect(settings).toEqual(modifiedSettings) - }) - }) - - }) -}) +"use strict"; + +const getVrtSettings = require("../../lib/get-vrt-settings"), + defaultSettings = { + "latest_screenshots_path": "vrt/latest", + "latest_suffix": "", + "baseline_screenshots_path": "vrt/baseline", + "baseline_suffix": "", + "diff_screenshots_path": "vrt/diff", + "diff_suffix": "", + "threshold": 0.0, + "prompt": false, + "always_save_diff_screenshot": false + }; + +describe("getVrtSettings", () => { + function getNightwatchClient(customSettings = {}) { + return { + "assert": { + "ok": jest.fn() + } + }; + } + + describe("when getting visual regression settings", () => { + describe("given no visual regression settings defined", () => { + it("should return default settings", () => { + const nightwatchClient = getNightwatchClient(); + const settings = getVrtSettings(nightwatchClient); + + expect(settings).toEqual(defaultSettings); + }); + }); + + describe("given visual regression settings are defined in the nightwatch globals settings section", () => { + it("should return the defined settings", () => { + const nightwatchClient = getNightwatchClient(); + const vrtSettings = { + "threshold": 0.2, + "diff_screenshots_path": "vrt/custom-diffs" + }; + + nightwatchClient.globals = { + "visual_regression_settings": vrtSettings + }; + + const settings = getVrtSettings(nightwatchClient); + expect(settings).toMatchObject(vrtSettings); + }); + }); + + describe("given visual regression settings are defined in the nightwatch globals settings section within a test_settings object", () => { + it("should return the defined settings", () => { + const nightwatchClient = getNightwatchClient(); + const vrtSettings = { + "threshold": 0.2, + "diff_screenshots_path": "vrt/custom-diffs" + }; + + nightwatchClient.globals = { + "test_settings": { "visual_regression_settings": vrtSettings } + }; + + const settings = getVrtSettings(nightwatchClient); + expect(settings).toMatchObject(vrtSettings); + }); + }); + + describe("given partial test-scoped visual regression settings defined", () => { + it("should return default settings", () => { + const nightwatchClient = getNightwatchClient(); + const settings = getVrtSettings(nightwatchClient, { "threshold": 0.5 }); + const modifiedSettings = Object.assign({}, defaultSettings, { + "threshold": 0.5 + }); + + expect(settings).toEqual(modifiedSettings); + }); + }); + }); +}); diff --git a/tests/lib/promisify-command-test.js b/tests/lib/promisify-command-test.js index cfa9c06..473aefd 100644 --- a/tests/lib/promisify-command-test.js +++ b/tests/lib/promisify-command-test.js @@ -1,38 +1,41 @@ -'use strict' - -const promisifyCommand = require('../../lib/promisify-command') - -describe('promisifyCommand', () => { - - function getNightwatchAPI() { - return { - result: { status: 0, value: '' }, - calls: [], - elementId(selector, callback = () => false) { - this.calls.push([selector]) - callback(this.result) - } - } - } - - it('should resolve the promise when command result status equals 0', (done) => { - const nightwatchAPI = getNightwatchAPI() - - promisifyCommand(nightwatchAPI, 'elementId', ['.selector']).then((result) => { - expect(result).toEqual(nightwatchAPI.result.value) - done() - }) - }) - - it('should reject the promise when command result status is not equal to 0', (done) => { - const nightwatchAPI = getNightwatchAPI() - - nightwatchAPI.result.status = 9 - nightwatchAPI.result.state = 'invalid call' - - promisifyCommand(nightwatchAPI, 'elementId', ['.selector']).catch((result) => { - expect(result).toEqual(nightwatchAPI.result.state) - done() - }) - }) -}) \ No newline at end of file +"use strict"; + +const promisifyCommand = require("../../lib/promisify-command"); + +describe("promisifyCommand", () => { + function getNightwatchAPI() { + return { + "result": { "status": 0, "value": "" }, + "calls": [], + elementId(selector, callback = () => false) { + this.calls.push([selector]); + callback(this.result); + } + }; + } + + it("should resolve the promise when command result status equals 0", (done) => { + const nightwatchAPI = getNightwatchAPI(); + + promisifyCommand(nightwatchAPI, "elementId", [".selector"]).then( + (result) => { + expect(result).toEqual(nightwatchAPI.result.value); + done(); + } + ); + }); + + it("should reject the promise when command result status is not equal to 0", (done) => { + const nightwatchAPI = getNightwatchAPI(); + + nightwatchAPI.result.status = 9; + nightwatchAPI.result.state = "invalid call"; + + promisifyCommand(nightwatchAPI, "elementId", [".selector"]).catch( + (result) => { + expect(result).toEqual(nightwatchAPI.result.state); + done(); + } + ); + }); +}); diff --git a/tests/lib/save-screenshot-test.js b/tests/lib/save-screenshot-test.js index 46829de..1c27fa4 100644 --- a/tests/lib/save-screenshot-test.js +++ b/tests/lib/save-screenshot-test.js @@ -1,32 +1,30 @@ -'use strict' +"use strict"; -const saveScreenshot = require('../../lib/save-screenshot') +const saveScreenshot = require("../../lib/save-screenshot"); -describe('saveScreenshot', () => { - function getNightwatchClient() { - return { - assert: { - ok: jest.fn() - } - } - } +describe("saveScreenshot", () => { + function getNightwatchClient() { + return { + "assert": { + "ok": jest.fn() + } + }; + } - function getImage() { - return { - write: jest.fn() - } - } + function getImage() { + return { + "write": jest.fn() + }; + } - it('should write the screenshot file in the file path specified', () => { - const filePath = 'filePath' - const message = 'This is the message' - const image = getImage() - const client = getNightwatchClient() + it("should write the screenshot file in the file path specified", () => { + const filePath = "filePath"; + const message = "This is the message"; + const image = getImage(); + const client = getNightwatchClient(); - saveScreenshot(filePath, image).then((savedScreenshot) => { - expect(image.write.mock.calls[0]).toEqual([ - filePath, savedScreenshot - ]) - }) - }) -}) + saveScreenshot(filePath, image).then((savedScreenshot) => { + expect(image.write.mock.calls[0]).toEqual([filePath, savedScreenshot]); + }); + }); +}); From 2b5367ad8c5d6438c557ce9c32256ce69c610a78 Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 09:04:05 +0000 Subject: [PATCH 3/9] added package-lock.json to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2008cf6..d2a0bce 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ yarn.lock selenium-debug.log .DS_Store +#NPM package-lock.json +package-lock.json # Directory for instrumented libs generated by jscoverage/JSCover lib-cov @@ -59,4 +61,3 @@ typings/ .idea/ *.iml tasks.xml - From fc5eab6ddc469c0d7323ee65e53a359eac82d171 Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 09:46:59 +0000 Subject: [PATCH 4/9] fixed typeings --- index.d.ts | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/index.d.ts b/index.d.ts index ea261df..adee144 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,16 +1,16 @@ -import * as nightwatch from "nightwatch"; - declare module "nightwatch" { + import * as nightwatch from "nightwatch"; + export interface NightwatchVRTSettings { - "baseline_screenshots_path"?: string; - "baseline_suffix"?: string; - "latest_screenshots_path"?: string; - "latest_suffix"?: string; - "diff_screenshots_path"?: string; - "diff_suffix"?: string; - "threshold"?: number; - "screenshotPath": (browser: NightwatchAPI) => string; - "prompt"?: boolean; + "baseline_screenshots_path"?: string; + "baseline_suffix"?: string; + "latest_screenshots_path"?: string; + "latest_suffix"?: string; + "diff_screenshots_path"?: string; + "diff_suffix"?: string; + "threshold"?: number; + "screenshotPath": (browser: NightwatchAPI) => string; + "prompt"?: boolean; } export interface NightwatchAssertions { @@ -30,19 +30,19 @@ declare module "nightwatch" { * * @param {String} elementId Identifies the element that will be captured in the screenshot. * @param {String} fileName Optional file name for this screenshot; defaults to the selector - * @param {NightwatchVRTOptions} settings Optional settings to override the defaults and `visual_regression_settings` + * @param {NightwatchVRTSettings} settings Optional settings to override the defaults and `visual_regression_settings` * @param {String} message Optional message for `nightwatch` to log upon completion */ - screenshotIdenticalToBaseline: (elementId: string, fileName?: string, options?: NightwatchVRTSettings, message?: string) => this; + screenshotIdenticalToBaseline: (elementId: string, fileName?: string, settings?: NightwatchVRTSettings, message?: string) => this; } export interface NightwatchAPI { /** * Takes a screenshot of the visible region encompassed by the bounding rectangle * of an element. - * + * * @link - * @param {string} selector Identifies the element that will be captured in the screenshot. + * @param {string} selector Identifies the element that will be captured in the screenshot. * @param {function} callback Callback function which is called with the captured screenshot as an argument. * @returns {Object} The captured screenshot. This object is a Jimp (library) image instance. */ diff --git a/package.json b/package.json index 25a3d45..e574650 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "test:dev": "jest --watch --notify", "test": "jest --coverage", "clean": "rimraf node_modules package-lock.json reports", - "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\"", + "prepare": "husky install", "demo": "node demo/nightwatch.conf.js && run-p --race demo:start demo:nightwatch", "demo:start": "http-server demo --silent", "demo:nightwatch": "sleep 1 && nightwatch --config demo/nightwatch.conf.js --env phantomjs" From 6f8d3f5621ff571371ef734bd6ad022facb31ccf Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 11:58:48 +0000 Subject: [PATCH 5/9] added .eslintignore added typescript linting --- .eslintignore | 7 ++++ .eslintrc.json | 11 +++++- index.d.ts | 100 ++++++++++++++++++++++++++----------------------- package.json | 5 ++- 4 files changed, 73 insertions(+), 50 deletions(-) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..d5560d6 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,7 @@ +# Project +.eslintcache +.husky/ +.idea/ +*.js +node_modules +package-lock.json diff --git a/.eslintrc.json b/.eslintrc.json index bc98fbf..128b742 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,12 +1,19 @@ { - "plugins": ["prettier"], - "extends": ["plugin:prettier/recommended"], + "plugins": ["prettier", "@typescript-eslint"], + "extends": [ + "plugin:prettier/recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], "env": { "node": true, "es6": true, "browser": true }, "rules": { + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/consistent-type-definitions": "warn", + "@typescript-eslint/no-explicit-any": "warn", "no-unused-vars": "off", "no-console": "off", "prettier/prettier": "error", diff --git a/index.d.ts b/index.d.ts index adee144..08c6050 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,51 +1,59 @@ declare module "nightwatch" { - import * as nightwatch from "nightwatch"; + import * as nightwatch from "nightwatch"; - export interface NightwatchVRTSettings { - "baseline_screenshots_path"?: string; - "baseline_suffix"?: string; - "latest_screenshots_path"?: string; - "latest_suffix"?: string; - "diff_screenshots_path"?: string; - "diff_suffix"?: string; - "threshold"?: number; - "screenshotPath": (browser: NightwatchAPI) => string; - "prompt"?: boolean; - } + export interface NightwatchVRTSettings { + "baseline_screenshots_path"?: string; + "baseline_suffix"?: string; + "latest_screenshots_path"?: string; + "latest_suffix"?: string; + "diff_screenshots_path"?: string; + "diff_suffix"?: string; + "threshold"?: number; + "screenshotPath": (browser: NightwatchAPI) => string; + "prompt"?: boolean; + } - export interface NightwatchAssertions { - /** - * Asserts if a screenshot that captures the visual representation of - * an element in the application is identical to a previously captured - * screenshot used as a baseline. - * - * When this assertion is executed and the baseline screenshot doesn't exists, - * it will use save captured screenshot as the baseline and the assertion will succeed. - * - * The baseline screenshot will be saved in the baseline directory passed in - * the settings, or the directory specified in the nightwatch configuration - * (under test_settings/visual_regression_settings), or in a default generated path; in - * that order. Further assertions will compare against the screenshot that was - * saved in the first execution of the assertion. - * - * @param {String} elementId Identifies the element that will be captured in the screenshot. - * @param {String} fileName Optional file name for this screenshot; defaults to the selector - * @param {NightwatchVRTSettings} settings Optional settings to override the defaults and `visual_regression_settings` - * @param {String} message Optional message for `nightwatch` to log upon completion - */ - screenshotIdenticalToBaseline: (elementId: string, fileName?: string, settings?: NightwatchVRTSettings, message?: string) => this; - } + export interface NightwatchAssertions { + /** + * Asserts if a screenshot that captures the visual representation of + * an element in the application is identical to a previously captured + * screenshot used as a baseline. + * + * When this assertion is executed and the baseline screenshot does not exist, + * it will use save captured screenshot as the baseline and the assertion will succeed. + * + * The baseline screenshot will be saved in the baseline directory passed in + * the settings, or the directory specified in the nightwatch configuration + * (under test_settings/visual_regression_settings), or in a default generated path; in + * that order. Further assertions will compare against the screenshot that was + * saved in the first execution of the assertion. + * + * @param {String} elementId Identifies the element that will be captured in the screenshot. + * @param {String} fileName Optional file name for this screenshot; defaults to the selector + * @param {NightwatchVRTSettings} settings Optional settings to override the defaults and `visual_regression_settings` + * @param {String} message Optional message for `nightwatch` to log upon completion + */ + screenshotIdenticalToBaseline: ( + elementId: string, + fileName?: string, + settings?: NightwatchVRTSettings, + message?: string + ) => this; + } - export interface NightwatchAPI { - /** - * Takes a screenshot of the visible region encompassed by the bounding rectangle - * of an element. - * - * @link - * @param {string} selector Identifies the element that will be captured in the screenshot. - * @param {function} callback Callback function which is called with the captured screenshot as an argument. - * @returns {Object} The captured screenshot. This object is a Jimp (library) image instance. - */ - captureElementScreenshot: (elementId: string, callback?: (arg?: any) => void) => this - } + export interface NightwatchAPI { + /** + * Takes a screenshot of the visible region encompassed by the bounding rectangle + * of an element. + * + * @link + * @param {string} selector Identifies the element that will be captured in the screenshot. + * @param {function} callback Callback function which is called with the captured screenshot as an argument. + * @returns {Object} The captured screenshot. This object is a Jimp (library) image instance. + */ + captureElementScreenshot: ( + elementId: string, + callback?: (arg?: any) => void + ) => this; + } } diff --git a/package.json b/package.json index e574650..36192db 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "types": "index", "scripts": { "lint": "eslint . --fix", - "pretty": "prettier --write \"./**/*.{css,html,js,json,xml}\"", + "pretty": "prettier --write \"./**/*.{css,html,js,json,ts,xml}\"", "test:dev": "jest --watch --notify", "test": "jest --coverage", "clean": "rimraf node_modules package-lock.json reports", @@ -55,6 +55,7 @@ }, "devDependencies": { "@prettier/plugin-xml": "^2.2.0", + "@typescript-eslint/eslint-plugin": "^5.49.0", "eslint": "^8.19.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", @@ -70,7 +71,7 @@ "selenium-standalone": "^8.2.5" }, "lint-staged": { - "*.{js}": ["eslint --cache --fix", "prettier --write"], + "*.{js,ts}": ["eslint --cache --fix", "prettier --write"], "*.{css,html,json,xml}": "prettier --write" } } From 2a13be80542ad647a847512457952da58853dfcf Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 12:20:22 +0000 Subject: [PATCH 6/9] added husky prepare silent fail install script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 36192db..e3f2277 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "test:dev": "jest --watch --notify", "test": "jest --coverage", "clean": "rimraf node_modules package-lock.json reports", - "prepare": "husky install", + "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\"", "demo": "node demo/nightwatch.conf.js && run-p --race demo:start demo:nightwatch", "demo:start": "http-server demo --silent", "demo:nightwatch": "sleep 1 && nightwatch --config demo/nightwatch.conf.js --env phantomjs" From 970c66fc153d25dcd40eafc5e103b4fabd285604 Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 13:55:07 +0000 Subject: [PATCH 7/9] added husky prepare silent fail install script --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e3f2277..82e7f17 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "test:dev": "jest --watch --notify", "test": "jest --coverage", "clean": "rimraf node_modules package-lock.json reports", - "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\"", + "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\" && husky install", "demo": "node demo/nightwatch.conf.js && run-p --race demo:start demo:nightwatch", "demo:start": "http-server demo --silent", "demo:nightwatch": "sleep 1 && nightwatch --config demo/nightwatch.conf.js --env phantomjs" @@ -60,7 +60,7 @@ "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", "http-server": "^14.1.1", - "husky": "^8.0.3", + "husky": "^8.0.1", "jest": "^29.4.0", "lint-staged": "^13.0.3", "nightwatch": "^2.6.10", From df5b76c45735f91191bab87a8c9e7be3db7ada2b Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 14:53:12 +0000 Subject: [PATCH 8/9] removed travis.yml --- .travis.yml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0b1a009..0000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js -node_js: - - "node" - -cache: - directories: - - "node_modules" \ No newline at end of file From 4bba1747c13e6120889a0d37e89f8dabb5f8c764 Mon Sep 17 00:00:00 2001 From: humphreyn Date: Wed, 25 Jan 2023 15:48:32 +0000 Subject: [PATCH 9/9] removed husky dependency --- .eslintignore | 1 - .gitignore | 3 --- .husky/pre-commit | 4 ---- .prettierignore | 1 - package.json | 6 ------ 5 files changed, 15 deletions(-) delete mode 100644 .husky/pre-commit diff --git a/.eslintignore b/.eslintignore index d5560d6..2077798 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,5 @@ # Project .eslintcache -.husky/ .idea/ *.js node_modules diff --git a/.gitignore b/.gitignore index d2a0bce..59c597d 100644 --- a/.gitignore +++ b/.gitignore @@ -54,9 +54,6 @@ typings/ # next.js build output .next -# Husky -.husky/_ - # Project .idea/ *.iml diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100644 index d24fdfc..0000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -npx lint-staged diff --git a/.prettierignore b/.prettierignore index e16b913..547ad4b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,5 @@ # Project .eslintcache -.husky/ .idea/ node_modules package-lock.json diff --git a/package.json b/package.json index 82e7f17..92cbbb7 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "test:dev": "jest --watch --notify", "test": "jest --coverage", "clean": "rimraf node_modules package-lock.json reports", - "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\" && husky install", "demo": "node demo/nightwatch.conf.js && run-p --race demo:start demo:nightwatch", "demo:start": "http-server demo --silent", "demo:nightwatch": "sleep 1 && nightwatch --config demo/nightwatch.conf.js --env phantomjs" @@ -60,7 +59,6 @@ "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", "http-server": "^14.1.1", - "husky": "^8.0.1", "jest": "^29.4.0", "lint-staged": "^13.0.3", "nightwatch": "^2.6.10", @@ -69,9 +67,5 @@ "prettier": "^2.8.3", "rimraf": "^4.1.2", "selenium-standalone": "^8.2.5" - }, - "lint-staged": { - "*.{js,ts}": ["eslint --cache --fix", "prettier --write"], - "*.{css,html,json,xml}": "prettier --write" } }