From 5624e29608bb87e860b9ac6aec828010ddb9a90d Mon Sep 17 00:00:00 2001 From: Dominik Ferber Date: Sun, 28 Oct 2018 11:10:44 +0100 Subject: [PATCH] feat: add setDefaultOptions and restoreDefaultOptions --- README.md | 107 +++++++++++++++++++++++++++++++++++++++-------- generateImage.js | 34 +-------------- index.js | 2 + options.js | 47 +++++++++++++++++++++ 4 files changed, 140 insertions(+), 50 deletions(-) create mode 100644 options.js diff --git a/README.md b/README.md index 248f40c..348efd4 100755 --- a/README.md +++ b/README.md @@ -12,18 +12,25 @@ This package will only give you the image, you'll have to diff it with something - [Install](#install) - [Usage](#usage) - - [Options](#options) - - [`options.launch`](#-optionslaunch-) - - [`options.screenshot`](#-optionsscreenshot-) - - [`options.serve`](#-optionsserve-) - - [`options.debug`](#-optionsdebug-) - - [`options.viewport`](#-optionsviewport-) - - [`options.waitUntilNetworkIdle`](#-optionswaituntilnetworkidle-) - - [`options.intercept`](#-optionsintercept-) - - [Changing viewport](#changing-viewport) +- [Usage in Jest & React](#usage-in-jest---react) +- [API](#api) + - [`generateImage(options)`](#-generateimage-options--) + - [Options](#options) + - [`options.launch`](#-optionslaunch-) + - [`options.screenshot`](#-optionsscreenshot-) + - [`options.serve`](#-optionsserve-) + - [`options.debug`](#-optionsdebug-) + - [`options.viewport`](#-optionsviewport-) + - [`options.waitUntilNetworkIdle`](#-optionswaituntilnetworkidle-) + - [`options.intercept`](#-optionsintercept-) + - [Changing viewport](#changing-viewport) + - [`setDefaultOptions(options)`](#-setdefaultoptions-options--) + - [`restoreDefaultOptions()`](#-restoredefaultoptions---) + - [`debug(element)`](#-debug-element--) - [How it works](#how-it-works) - [High level](#high-level) - [Technically](#technically) +- [Performance](#performance) - [Debugging](#debugging) - [Debugging JSDOM](#debugging-jsdom) - [Debugging `puppeteer`](#debugging--puppeteer-) @@ -51,7 +58,31 @@ document.body.appendChild(div); generateImage(component, options); ``` -### Options +## Usage in Jest & React + +It is recommended to use this package with [`jest-image-snapshot`](https://www.npmjs.com/package/jest-image-snapshot) and [`react-testing-library`](https://github.com/kentcdodds/react-testing-library). Use it as together like this: + +```js +import React from "react"; +import { generateImage, setDefaultOptions } from "jsdom-screenshot"; +import { render } from "react-testing-library"; +import { SomeComponent } from ""; + +it("should have no visual regressions", async () => { + render(); + expect(await generateImage()).toMatchImageSnapshot(); +}); +``` + +## API + +### `generateImage(options)` + +`generateImage` is the main function you're going to use to take a screenshot of the JSDOM. It supports these options. + +> Tip: You can use `react-testing-library`'s `fireEvent` to get the component into any state before taking the screenshot. + +#### Options ```js options = { @@ -72,38 +103,38 @@ options = { }; ``` -#### `options.launch` +##### `options.launch` `launch` options are passed to `puppeteer.launch([options])`, see [`docs`](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunch). -#### `options.screenshot` +##### `options.screenshot` `screenshot` options are passed to `page.screenshot([options])`, see [`docs`](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagescreenshotoptions). -#### `options.serve` +##### `options.serve` `serve` is an array of strings. You can provide a list of folders to serve statically. This is useful when your component uses assets through relative links like ``. In this case, you could provide `serve: ["images"]` when the `images` folder at the root of your project (where you launch the tests from) contains `party-parrot.gif`. -#### `options.debug` +##### `options.debug` Prints the jsdom markup to the console before taking the screenshot. See the [Debugging JSDOM](#debugging-jsdom) section below for more information. -#### `options.viewport` +##### `options.viewport` This is a shortcut to set `options.launch.defaultViewport`. `options.launch.defaultViewport` will take precedence in case both are passed. -#### `options.waitUntilNetworkIdle` +##### `options.waitUntilNetworkIdle` When set to `true`, `jsdom-screenshot` will wait until the network becomes idle (all resources are loaded) before taking a screenshot. You can use this to ensure that all resources are loaded before the screenshot is taken. It is disabled by default as it adds roughly one second to each screenshot. Use it wisely to avoid slowing down tests unnecessarily. You can mock requests using [`options.intercept`](#-optionsintercept-). -#### `options.intercept` +##### `options.intercept` When provided, `puppeteer`'s request interception will be enabled. The provided function will be called with the intercepted request. @@ -134,7 +165,7 @@ generateImage({ See [`page.setintercept`](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetinterceptvalue) of `puppeteer`. -### Changing viewport +#### Changing viewport Puppeteer will use an 800x600 viewport by default. You can change the viewport by passing `launch.defaultViewport`: @@ -156,6 +187,46 @@ generateImage({ viewport: { width: 1024, height: 768 } }); See [`launch.defaultViewport`](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunch). +### `setDefaultOptions(options)` + +Having to reapply the same options for every test is pretty inconvenient. The `setDefaultOptions` function can be used to set default options for every `generateImage` call. Any `options` passed to the `generateImage` call will get merged with the specified `defaultOptions`. + +This function can be used to provide global defaults. + +It can also be used together with `restoreDefaultOptions()` to set defaults for a specific spec. + +```js +import React from "react"; +import { + generateImage, + setDefaultOptions, + restoreDefaultOptions +} from "jsdom-screenshot"; +import { render } from "react-testing-library"; +import { SomeCOmponent } from ""; + +beforeAll(() => { + setDefaultOptions({ viewport: { width: 600, height: 400 } }); +}); + +afterAll(() => { + restoreDefaultOptions(); +}); + +it("has no visual regressions", async () => { + render( {}} />); + expect(await generateImage()).toMatchImageSnapshot(); +}); +``` + +### `restoreDefaultOptions()` + +The `restoreDefaultOptions` function restores the default options provided by `jsdom-screenshot`. See `setDefaultOptions` for a usage example. + +### `debug(element)` + +Logs the JSDOM contents to the console. See [Debugging](#debugging) for more information. + ## How it works ### High level diff --git a/generateImage.js b/generateImage.js index 273b04a..b7886fc 100755 --- a/generateImage.js +++ b/generateImage.js @@ -1,15 +1,6 @@ const puppeteer = require("puppeteer"); -const merge = require("lodash.merge"); const debug = require("./debug"); - -const addArg = (opts, arg) => { - // eslint-disable-next-line no-param-reassign - if (!Array.isArray(opts.launch.args)) opts.launch.args = []; - - if (!opts.launch.args.includes(arg)) { - opts.launch.args.push(arg); - } -}; +const { getMergedOptions } = require("./options"); // starts a server and returns it // - server runs on random open port @@ -79,29 +70,8 @@ const takeScreenshot = async (url, opts) => { return image; }; -const defaultOpts = { - waitUntilNetworkIdle: false, - launch: {}, - screenshot: undefined, - serve: [] -}; - const generateImage = async options => { - const opts = merge({}, defaultOpts, options); - - // config sugar to let users specify viewport directly - if (options && options.viewport && !opts.launch.defaultViewport) { - opts.launch.defaultViewport = options.viewport; - } - - if (!Array.isArray(opts.serve)) { - throw new Error("jsdom-screenshot: options.serve must be an array"); - } - - // Disable "lcd text antialiasing" to avoid differences in the snapshots - // depending on the used monitor. - // See https://github.com/dferber90/jsdom-screenshot/issues/1 - addArg(opts, "--disable-lcd-text"); + const opts = getMergedOptions(options); // Allows easy debugging by passing generateImage({ debug: true }) if (opts.debug) debug(document); diff --git a/index.js b/index.js index 078f411..21da814 100644 --- a/index.js +++ b/index.js @@ -12,5 +12,7 @@ module.exports = { // // render: require("./src/render"), generateImage: require("./generateImage"), + setDefaultOptions: require("./options").setDefaultOptions, + restoreDefaultOptions: require("./options").restoreDefaultOptions, debug: require("./debug") }; diff --git a/options.js b/options.js new file mode 100644 index 0000000..46f190f --- /dev/null +++ b/options.js @@ -0,0 +1,47 @@ +const merge = require("lodash.merge"); + +const defaultOptionsTemplate = { + waitUntilNetworkIdle: false, + launch: {}, + screenshot: undefined, + serve: [] +}; + +let defaultOptions = defaultOptionsTemplate; + +const addArg = (opts, arg) => { + // eslint-disable-next-line no-param-reassign + if (!Array.isArray(opts.launch.args)) opts.launch.args = []; + + if (!opts.launch.args.includes(arg)) { + opts.launch.args.push(arg); + } +}; + +module.exports.setDefaultOptions = options => { + defaultOptions = merge({}, defaultOptionsTemplate, options); +}; + +module.exports.restoreDefaultOptions = () => { + defaultOptions = defaultOptionsTemplate; +}; + +module.exports.getMergedOptions = options => { + const opts = merge({}, defaultOptions, options); + + // config sugar to let users specify viewport directly + if (options && options.viewport && !opts.launch.defaultViewport) { + opts.launch.defaultViewport = options.viewport; + } + + if (!Array.isArray(opts.serve)) { + throw new Error("jsdom-screenshot: options.serve must be an array"); + } + + // Disable "lcd text antialiasing" to avoid differences in the snapshots + // depending on the used monitor. + // See https://github.com/dferber90/jsdom-screenshot/issues/1 + addArg(opts, "--disable-lcd-text"); + + return opts; +};