Skip to content

Commit 0b21289

Browse files
authored
Major refactoring to support Puppeteer package (#35)
* Major refactoring to support Puppeteer package * Fix test * Update tests * Update tests * Rename config to defaultConfigs * Update compareImage tests * Update tests
1 parent 579edfc commit 0b21289

28 files changed

+1031
-928
lines changed

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6.9.5
1+
8.5.0

API.md

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
|Method|Arguments|description|
44
|------|---------|-----------|
5-
|`update`|[TestOptions](https://github.com/NimaSoroush/differencify#testoptions)|Creates reference screenshots|
6-
|`test`|[TestOptions](https://github.com/NimaSoroush/differencify#testoptions)|Validate your changes by testing against reference screenshots|
7-
|`cleanup`|no argument|Closes all leftover browser instances|
5+
|`launchBrowser`|no argument|Launches a browser instance with [GlobalOptions](https://github.com/NimaSoroush/differencify#globaloptions). The browser will be closed when the parent node.js process is closed|
6+
|`init`|[TestOptions](https://github.com/NimaSoroush/differencify#testoptions)|Launches a browser instance if there is no instance already been launched or launches new browser window if `newWindow:true`|
7+
|`cleanup`|no argument|Closes browser instance if it is not closed already|
88

99
### Steps Methods
1010

@@ -14,27 +14,36 @@
1414
|`wait`|`string`, `integer` or `func`|waiting time in millisecond `or` waiting for a selector `or` waiting until the function you supplied is evaluated as true|
1515
|`execute`|`func` or `string`|execute an expression in the browser context|
1616
|`freezeImage`|`string`|Selector name of a <img> tag containing animated image to be freezed before taking screenshot|
17-
|`capture`|`string`|`undefiend`, `document` or selector name|
18-
19-
#### Steps example
20-
21-
```
22-
{
23-
...
24-
steps: [
25-
{ name: 'goto', value: 'http://www.example.com' },
26-
{ name: 'wait', value: 5000 },
27-
{ name: 'freezeImage', value: '#myImage' },
28-
{ name: 'execute', value: () => { alert("Hello! I am an alert box!!") } },
29-
{ name: 'capture', value: 'document' },
30-
],
31-
...
32-
}
33-
```
34-
35-
##### Coming steps
17+
|`capture`|`object`|[screenshot options](https://github.com/NimaSoroush/differencify/blob/master/API.md#screenshot-options)|
18+
|`resize`|`object`|[viewport](https://github.com/NimaSoroush/differencify/blob/master/API.md#viewport)|
19+
20+
21+
#### screenshot options
22+
- `options` <[Object]> Options object which might have the following properties:
23+
- `path` <[string]> The file path to save the image to. The screenshot type will be inferred from file extension. If `path` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). If no path is provided, the image won't be saved to the disk.
24+
- `type` <[string]> Specify screenshot type, can be either `jpeg` or `png`. Defaults to 'png'.
25+
- `quality` <[number]> The quality of the image, between 0-100. Not applicable to `png` images.
26+
- `fullPage` <[boolean]> When true, takes a screenshot of the full scrollable page. Defaults to `false`.
27+
- `clip` <[Object]> An object which specifies clipping region of the page. Should have the following fields:
28+
- `x` <[number]> x-coordinate of top-left corner of clip area
29+
- `y` <[number]> y-coordinate of top-left corner of clip area
30+
- `width` <[number]> width of clipping area
31+
- `height` <[number]> height of clipping area
32+
- `omitBackground` <[boolean]> Hides default white background and allows capturing screenshots with transparency. Defaults to `false`.
33+
34+
#### viewport
35+
- `viewport` <[Object]>
36+
- `width` <[number]> page width in pixels.
37+
- `height` <[number]> page height in pixels.
38+
- `deviceScaleFactor` <[number]> Specify device scale factor (can be thought of as dpr). Defaults to `1`.
39+
- `isMobile` <[boolean]> Whether the `meta viewport` tag is taken into account. Defaults to `false`.
40+
- `hasTouch`<[boolean]> Specifies if viewport supports touch events. Defaults to `false`
41+
- `isLandscape` <[boolean]> Specifies if viewport is in landscape mode. Defaults to `false`.
42+
43+
44+
##### Coming methods
3645
- click
3746
- setCookie
3847
- deleteCookie
39-
- clearCookies
4048
- emulate (Emulates phone)
49+
- ...

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## [1.0.0] - 2017-10-10
2+
### Changed
3+
- Replacing chromy with puppeteer as backend
4+
- Add functionality to chain differencify methods
5+
- Add resize functionality
6+
- Removed dependency to config files
7+
- Better logging
8+
- Bug fixes
9+
110
## [0.0.18] - 2017-08-14
211
### Added
312
- Fixing issue with freezing image

Dockerfile

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
1-
FROM debian:sid
1+
FROM node:8-slim
22

3-
# Install deps + add Chrome Stable + purge all the things
4-
RUN apt-get update && apt-get install -y --force-yes \
5-
apt-transport-https \
6-
ca-certificates \
7-
curl \
8-
gnupg \
9-
--no-install-recommends
10-
RUN curl -sSL https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
11-
RUN echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list
12-
RUN apt-get update && apt-get install -y \
13-
google-chrome-stable \
14-
--no-install-recommends
15-
# RUN apt-get -f purge --auto-remove -y --force-yes curl gnupg
16-
RUN apt-get -f -y --force-yes remove --purge curl
17-
# RUN apt-get -f -y --force-yes remove --purge gnupg
18-
RUN rm -rf /var/lib/apt/lists/*
3+
# Install latest chrome dev package.
4+
# Note: this installs the necessary libs to make the bundled version of Chromium that Pupppeteer
5+
# installs, work.
6+
RUN apt-get update && apt-get install -y wget --no-install-recommends \
7+
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
8+
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
9+
&& apt-get update \
10+
&& apt-get install -y google-chrome-unstable \
11+
--no-install-recommends \
12+
&& rm -rf /var/lib/apt/lists/* \
13+
&& apt-get purge --auto-remove -y curl \
14+
&& rm -rf /src/*.deb
1915

20-
# Add Chrome as a user
21-
RUN groupadd -r chrome && useradd -r -g chrome -G audio,video chrome \
22-
&& mkdir -p /home/chrome && chown -R chrome:chrome /home/chrome
16+
# Uncomment to skip the chromium download when installing puppeteer. If you do,
17+
# you'll need to launch puppeteer with:
18+
# browser.launch({executablePath: 'google-chrome-unstable'})
19+
# ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
2320

24-
EXPOSE 9222
21+
# Install puppeteer so it's available in the container.
22+
RUN yarn add puppeteer
2523

26-
# Autorun chrome headless with no GPU
27-
ENTRYPOINT [ "google-chrome-stable" ]
24+
# Add pptr user.
25+
RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
26+
&& mkdir -p /home/pptruser/Downloads \
27+
&& chown -R pptruser:pptruser /home/pptruser \
28+
&& chown -R pptruser:pptruser /node_modules
2829

29-
CMD [ "--headless", "--disable-gpu", "--remote-debugging-address=0.0.0.0", "--remote-debugging-port=9222" ]
30+
# Run user as non privileged.
31+
USER pptruser
32+
33+
CMD ["google-chrome-unstable"]

README.md

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ Regression Testing suite!
99
Status: [![CircleCI](https://circleci.com/gh/NimaSoroush/differencify/tree/master.svg?style=svg)](https://circleci.com/gh/NimaSoroush/differencify/tree/master)
1010

1111
## About
12-
Differencify is a library for visual regression testing by comparing your local changes with reference screenshots of your website.
12+
Differencify is a library for visual regression testing by comparing your local changes with reference screenshots of your website. It is built on top of chrome headless using [Puppeteer](https://github.com/GoogleChrome/puppeteer)
1313

1414
|Reference|Local changes|
1515
|---------|-------------|
1616
|<img alt="Differencify" src="images/reference_screenshot.png" width="400">|<img alt="Differencify" src="images/differencified_screenshot.png" width="400">|
1717

1818

1919
## Requirements
20-
- Node > 6
20+
- Node > 7.6.0
2121
- Chrome > 59 or [Chrome Canary](https://www.google.co.uk/chrome/browser/canary.html)
2222

2323
## Installation
@@ -30,28 +30,42 @@ npm install differencify
3030
import Differencify from 'differencify';
3131
const differencify = new Differencify(GlobalOptions);
3232
```
33-
### Create reference screenshots
34-
```js
35-
async () => {
36-
const result = await differencify.update(TestOptions);
37-
console.log(result); //true if update succeeded
38-
}
39-
```
40-
<p align="center">
41-
<img src="images/update.gif" width="500">
42-
</p>
4333

4434
### Validate your changes
4535
```js
46-
async () => {
47-
const result = await differencify.test(TestOptions);
48-
console.log(result); //true if test pass
49-
}
36+
(async () => {
37+
const result = await differencify
38+
.init()
39+
.resize({ width: 1600, height: 1200 })
40+
.goto('http://www.google.com')
41+
.wait(3000)
42+
.capture()
43+
.close()
44+
.end();
45+
46+
// or unchained
47+
48+
const page = await differencify.init({ chain: false });
49+
await page.resize({ width: 1600, height: 1200 });
50+
await page.goto('http://www.msn.com');
51+
await page.wait(3000);
52+
await page.capture();
53+
const result = await page.close();
54+
55+
console.log(result); // Prints true or false
56+
})();
5057
```
5158
<p align="center">
5259
<img src="images/test.gif" width="500">
5360
</p>
5461

62+
### Create/Update reference screenshots
63+
Simply set environment variable `update=true` and run the same code.
64+
65+
<p align="center">
66+
<img src="images/update.gif" width="500">
67+
</p>
68+
5569
### API
5670

5771
See [API.md](API.md) for full list of API calls
@@ -60,45 +74,42 @@ See [API.md](API.md) for full list of API calls
6074

6175
|Parameter|type|required|description|default|
6276
|---------|----|--------|-----------|-------|
63-
|`visible`|`bool`|no|Browser is launched in visible mode|false|
64-
|`debug`|`bool`|no|Enables console output|false|
65-
|`timeout`|`integer` (ms)|no|Global test timeout|30000|
77+
|`headless`|`boolean`|no|Browser is launched in visible mode|true|
78+
|`debug`|`boolean`|no|Enables console output|false|
79+
|`timeout`|`integer` (ms)|no|Maximum time in milliseconds to wait for the Chrome instance to start|30000|
6680
|`screenshots`|`string`|no|Stores reference screenshots in this directory|./screenshots|
67-
|`testReportPath`|`string`|no|Stores test screenshots in this directory|./differencify_report|
68-
|`saveDifferencifiedImage`|`bool`|no|Save differencified image to testReportPath in case of mistmach|true|
69-
|`mismatchThreshold`|`integer`|no|Difference tolerance between referenced/testsed image|0.01|
81+
|`testReports`|`string`|no|Stores test screenshots in this directory|./differencify_report|
82+
|`saveDifferencifiedImage`|`boolean`|no|Save differencified image to testReportPath in case of mismatch|true|
83+
|`mismatchThreshold`|`integer`|no|Difference tolerance between reference/test image|0.01|
84+
|`ignoreHTTPSErrors`|`boolean`|no|Whether to ignore HTTPS errors during navigation|false|
85+
|`slowMo`|`integer`|no|Slows down browser operations by the specified amount of milliseconds|0|
86+
|`browserArgs`|`Array`|no|Additional arguments to pass to the browser instance. List of Chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/)|[]|
87+
|`dumpio`|`boolean`|no|Whether to pipe browser process stdout and stderr into process.stdout and process.stderr|false|
7088

7189
### TestOptions
7290

7391
|Parameter|type|required|description|default|
7492
|---------|----|--------|-----------|-------|
75-
|`name`|`string`|yes|Unique name for your test case|default|
76-
|`resolution`|`object`|no|Browser width and height|800 * 600|
77-
|`steps`|`object`|yes|Steps before capturing screenshot|null|
93+
|`testName`|`string`|yes|Unique name for your test case|test|
94+
|`newWindow`|`boolean`|no|Whether to open test execution on new browser window or not. By default it opens on new tab|false|
95+
|`chain`|`boolean`|yes|Whether to chain differencify commands or not. More details on [examples](examples)|null|
7896

7997
### Steps API
8098

8199
See [API.md](API.md) for full list of Steps API calls
82100

83-
### TestOptions example
84-
85-
```
86-
{
87-
name: 'default',
88-
resolution: {
89-
width: 800,
90-
height: 600,
91-
},
92-
steps: [
93-
{ name: 'goto', value: 'http://www.example.com' },
94-
{ name: 'capture', value: 'document' },
95-
],
96-
}
97-
```
98101

99102
### Interested on Docker image!
100103

101-
A [Dockerfile](Dockerfile) with chrome-headless is availale for local and CI usage
104+
A [Dockerfile](Dockerfile) with chrome-headless is available for local and CI usage
105+
106+
Build the container:
107+
108+
```docker build -t puppeteer-chrome-linux .```
109+
110+
Run the container by passing node -e "<yourscript.js content as a string> as the command:
111+
112+
```docker run -i --rm --name puppeteer-chrome puppeteer-chrome-linux node -e "`cat yourscript.js`"```
102113

103114

104115
### Links

examples/configs/global-config.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

examples/configs/test-config.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

examples/example-test.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

examples/example-update.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

examples/jest-example.js

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,36 @@
1-
import Differencify from 'differencify';
2-
import globalConfig from './configs/global-config';
3-
import testConfig from './configs/test-config';
1+
const Differencify = require('differencify');
42

5-
const differencify = new Differencify(globalConfig.default);
3+
const differencify = new Differencify();
64

7-
describe('My website', () => {
8-
afterAll(() => {
9-
differencify.cleanup();
5+
describe('tests', () => {
6+
beforeAll(async () => {
7+
await differencify.launchBrowser();
108
});
11-
it('validate visual regression test', async () => {
12-
const result = await differencify.test(testConfig.default);
9+
afterAll(async () => {
10+
await differencify.cleanup();
11+
});
12+
it('google', async () => {
13+
const result = await differencify
14+
.init()
15+
.resize({ width: 1600, height: 1200 })
16+
.goto('http://www.google.com')
17+
.wait(3000)
18+
.capture()
19+
.close()
20+
.end();
21+
1322
expect(result).toEqual(true);
14-
}, 30000);
23+
}, 20000);
24+
it('github', async () => {
25+
await differencify
26+
.init()
27+
.goto('http://www.github.com')
28+
.close()
29+
.end();
30+
}, 7000);
31+
it('msn', async () => {
32+
const page = await differencify.init({ chain: false });
33+
await page.goto('http://www.msn.com');
34+
await page.close();
35+
}, 7000);
1536
});

0 commit comments

Comments
 (0)