diff --git a/README.md b/README.md index 77a6df231..a91d5ed9f 100644 --- a/README.md +++ b/README.md @@ -194,8 +194,9 @@ selectorExpansion // See Targeting elements in the next section for more misMatchThreshold // Percentage of different pixels allowed to pass test requireSameDimensions // If set to true -- any change in selector size will trigger a test failure. viewports // An array of screen size objects your DOM will be tested against. This configuration will override the viewports property assigned at the config root. +userAgent // Set custom userAgent. This configuration will override the userAgent property assigned at the config root. ``` - + ### Testing click and hover interactions @@ -245,6 +246,25 @@ _note: path is relative to your current working directory_ Pro tip: If you want an easy way to manually export cookies from your browser then download this chrome extension. You can directly use the output cookie files with BackstopJS https://chrome.google.com/webstore/detail/%E3%82%AF%E3%83%83%E3%82%AD%E3%83%BCjson%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%87%BA%E5%8A%9B-for-puppet/nmckokihipjgplolmcmjakknndddifde +### Setting custom userAgent +BackstopJS allows setting a custom userAgent. This can be helpful to exclude via analytics or the page uses userAgent parsing that needs to be emulated. + +This is a safer way than using it than via `page.setUserAgent` in `onBefore` since this works for both engines (Puppeteer/Playwright). + +Root config: +```json +userAgent: "custom ua string" +``` + +For scenario (overrides root config): +```json +scenarios: [ + { + "userAgent": "custom ua string" + } +] +``` + ### Targeting elements @@ -464,7 +484,7 @@ module.exports = async (page, scenario, vp, isReference) => { await require('./loadCookies')(page, scenario); // Example: set user agent - await page.setUserAgent('some user agent string here'); + await page.setUserAgent('some user agent string here'); // See documentation on setting custom userAgent }; @@ -1052,7 +1072,8 @@ Be sure to use a config `id` in your config file. See https://github.com/garris/ - (RECOMMENDED Updated for version 2) Regression testing with BackstopJS, in-depth tutorial by [Angela Riggs](https://twitter.com/AngelaRiggs_) http://www.metaltoad.com/blog/regression-testing-backstopjs - [BackstopJS](#backstopjs) - - [Version 3 Features](#version-3-features) + - [News](#news) + - [Backstop Features](#backstop-features) - [Install BackstopJS now](#install-backstopjs-now) - [Contents](#contents) - [The BackstopJS workflow](#the-backstopjs-workflow) @@ -1068,7 +1089,9 @@ Be sure to use a config `id` in your config file. See https://github.com/garris/ - [Using BackstopJS](#using-backstopjs) - [Advanced Scenarios](#advanced-scenarios) - [Testing click and hover interactions](#testing-click-and-hover-interactions) + - [Key Press interactions](#key-press-interactions) - [Setting cookies](#setting-cookies) + - [Setting custom userAgent](#setting-custom-useragent) - [Targeting elements](#targeting-elements) - [selectorExpansion](#selectorexpansion) - [expect](#expect) @@ -1084,13 +1107,16 @@ Be sure to use a config `id` in your config file. See https://github.com/garris/ - [Comparing different endpoints (e.g. comparing staging and production)](#comparing-different-endpoints-eg-comparing-staging-and-production) - [Running custom scripts](#running-custom-scripts) - [Setting the base path for custom onBefore and onReady scripts](#setting-the-base-path-for-custom-onbefore-and-onready-scripts) + - [onBeforeScript/onReadyScript available variables](#onbeforescriptonreadyscript-available-variables) - [Reporting workflow tips](#reporting-workflow-tips) - [Test report integration with a build system like Jenkins/Travis](#test-report-integration-with-a-build-system-like-jenkinstravis) + - [BackstopJS and CLI return values](#backstopjs-and-cli-return-values) - [CLI error handling](#cli-error-handling) - [Setting the bitmap and script directory paths](#setting-the-bitmap-and-script-directory-paths) - [Changing the rendering engine](#changing-the-rendering-engine) - [Chrome-Headless (The latest webkit library)](#chrome-headless-the-latest-webkit-library) - - [Setting Puppeteer option flags](#setting-puppeteer-option-flags) + - [Playwright](#playwright) + - [Setting Puppeteer and Playwright option flags](#setting-puppeteer-and-playwright-option-flags) - [Using Docker for testing across different environments](#using-docker-for-testing-across-different-environments) - [Requirements for when you're using docker...](#requirements-for-when-youre-using-docker) - [Integration options (local install)](#integration-options-local-install) @@ -1107,10 +1133,12 @@ Be sure to use a config `id` in your config file. See https://github.com/garris/ - [Creating reference files](#creating-reference-files) - [Modifying output settings of image-diffs](#modifying-output-settings-of-image-diffs) - [Git Integration](#git-integration) + - [Changing screenshot filename formats](#changing-screenshot-filename-formats) - [Developing, bug fixing, contributing...](#developing-bug-fixing-contributing) - [We use `eslint-config-semistandard`.](#we-use-eslint-config-semistandard) - - [There is a BackstopJS SMOKE TEST](#there-is-a-backstopjs-smoke-test) - [HTML report development](#html-report-development) + - [Docker development](#docker-development) + - [SMOKE & FEATURE TESTS](#smoke--feature-tests) - [Troubleshooting](#troubleshooting) - [SANITY TEST: Does Backstop work in my environment?](#sanity-test-does-backstop-work-in-my-environment) - [SMOKE TEST: Are backstop features working ok?](#smoke-test-are-backstop-features-working-ok) @@ -1121,8 +1149,6 @@ Be sure to use a config `id` in your config file. See https://github.com/garris/ - [The dreaded: _command-not-found_ error...](#the-dreaded-command-not-found-error) - [Issues when installing](#issues-when-installing) - [Projects don't work when I share with other users or run in different environments.](#projects-dont-work-when-i-share-with-other-users-or-run-in-different-environments) - - [If you just upgraded to 2.x or 3.x](#if-you-just-upgraded-to-2x-or-3x) - - [Windows users...](#windows-users) - [Tutorials, Extensions and more](#tutorials-extensions-and-more) - [Credits](#credits) diff --git a/core/util/runPlaywright.js b/core/util/runPlaywright.js index da670a1b2..ea0869b72 100644 --- a/core/util/runPlaywright.js +++ b/core/util/runPlaywright.js @@ -73,7 +73,15 @@ async function processScenarioView (scenario, variantOrScenarioLabelSafe, scenar const browser = await playwright[browserChoice].launch(playwrightArgs); const ignoreHTTPSErrors = config.engineOptions.ignoreHTTPSErrors ? config.engineOptions.ignoreHTTPSErrors : true; - const browserContext = await browser.newContext({ ignoreHTTPSErrors: ignoreHTTPSErrors }); + + // set up custom userAgent via scenario or config via `userAgent` + // if no userAgent is set, the browser's default will be taken ('') + const userAgent = scenario.userAgent || config.userAgent || ''; + + const browserContext = await browser.newContext({ + ignoreHTTPSErrors: ignoreHTTPSErrors, + userAgent: userAgent + }); const page = await browserContext.newPage(); await page.setViewportSize({ width: VP_W, height: VP_H }); diff --git a/core/util/runPuppet.js b/core/util/runPuppet.js index 145ee46fa..264a4cc72 100644 --- a/core/util/runPuppet.js +++ b/core/util/runPuppet.js @@ -82,6 +82,11 @@ async function processScenarioView (scenario, variantOrScenarioLabelSafe, scenar await page.setViewport({ width: VP_W, height: VP_H }); page.setDefaultNavigationTimeout(engineTools.getEngineOption(config, 'waitTimeout', TEST_TIMEOUT)); + // set up custom userAgent via scenario or config via `userAgent` + // if no userAgent is set, the browser's default will be taken ('') + const userAgent = scenario.userAgent || config.userAgent || ''; + await page.setUserAgent(userAgent); + if (isReference) { logger.log('blue', 'CREATING NEW REFERENCE FILE'); } diff --git a/package.json b/package.json index 662d5a327..2b9fcb2f8 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "build-compare": "cp ./node_modules/diverged/src/diverged.js ./compare/output/ && cp ./node_modules/diff/dist/diff.js ./compare/output/ && webpack --config ./compare/webpack.config.js && npm run lint", "dev-compare": "webpack-dev-server --content-base ./compare/output --config ./compare/webpack.config.js", "integration-test": "rm -rf newdir && mkdir newdir && cd newdir && node ../cli/index.js genConfig && node ../cli/index.js reference && node ../cli/index.js test && node -e \"require(\"../\")(\"test\")\"", + "ua-test": "cd test/configs/ && node ../../cli/index.js reference -i --config=backstop_userAgent", "smoke-test": "cd test/configs/ && node ../../cli/index.js test --config=backstop_features", "smoke-test-docker": "cd test/configs/ && node ../../cli/index.js test --config=backstop_features --docker", "sanity-test": "cd test/configs/ && node ../../cli/index.js test", diff --git a/test/configs/backstop_userAgent.js b/test/configs/backstop_userAgent.js new file mode 100644 index 000000000..9b4ac2fae --- /dev/null +++ b/test/configs/backstop_userAgent.js @@ -0,0 +1,58 @@ +/** + * Run test: + * $ npm run ua-test -- --engine="puppeteer|playwright" --browser="chromium|firefox|webkit" + */ +const argv = require('minimist')(process.argv.slice(2)); + +const ENGINE = argv.engine || 'puppeteer'; +const BROWSER = argv.browser || 'chromium'; + +const URL = 'https://www.whatsmyua.info/'; + +module.exports = { + id: 'userAgent', + viewports: [ + { + label: 'default', + width: 800, + height: 600 + } + ], + onBeforeScript: 'puppet/onBefore.js', + onReadyScript: 'puppet/onReady.js', + scenarios: [ + { + label: 'default', + url: URL + }, + { + label: 'custom', + url: URL, + userAgent: 'custom_ua_backstopjs_vrt' + } + ], + paths: { + bitmaps_reference: `backstop_data/bitmaps_reference/${ENGINE}`, + bitmaps_test: `backstop_data/bitmaps_test/${ENGINE}`, + engine_scripts: 'backstop_data/engine_scripts', + html_report: `backstop_data/html_report/${ENGINE}`, + ci_report: 'backstop_data/ci_report' + }, + fileNameTemplate: `${ENGINE}_${BROWSER}_{scenarioLabel}`, + report: ['browser'], + engine: ENGINE, + engineOptions: { + browser: BROWSER, + ...((BROWSER === 'webkit') && { + args: [ + '--no-sandbox' + ] + }) + }, + asyncCaptureLimit: 5, + asyncCompareLimit: 50, + debug: false, + debugWindow: false, + archiveReport: false, + scenarioLogsInReports: false +};