Skip to content

Commit

Permalink
feat: add setDefaultOptions and restoreDefaultOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
dferber90 committed Oct 28, 2018
1 parent 322e3e4 commit 5624e29
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 50 deletions.
107 changes: 89 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-)
Expand Down Expand Up @@ -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 "<your-code>";

it("should have no visual regressions", async () => {
render(<SomeComponent />);
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 = {
Expand All @@ -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 `<img src="/party-parrot.gif" />`.

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.

Expand Down Expand Up @@ -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`:

Expand All @@ -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 "<your-code>";

beforeAll(() => {
setDefaultOptions({ viewport: { width: 600, height: 400 } });
});

afterAll(() => {
restoreDefaultOptions();
});

it("has no visual regressions", async () => {
render(<PrimaryButton label="Submit" onClick={() => {}} />);
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
Expand Down
34 changes: 2 additions & 32 deletions generateImage.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ module.exports = {
//
// render: require("./src/render"),
generateImage: require("./generateImage"),
setDefaultOptions: require("./options").setDefaultOptions,
restoreDefaultOptions: require("./options").restoreDefaultOptions,
debug: require("./debug")
};
47 changes: 47 additions & 0 deletions options.js
Original file line number Diff line number Diff line change
@@ -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;
};

0 comments on commit 5624e29

Please sign in to comment.