Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #177 from Galooshi/pre-cropped-screenshots
Browse files Browse the repository at this point in the history
Pre cropped screenshots
  • Loading branch information
trotzig authored Jan 9, 2017
2 parents 99041b2 + 188c097 commit 1b4d49b
Show file tree
Hide file tree
Showing 20 changed files with 243 additions and 60 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"presets": [
"airbnb"
],
"plugins": [
"transform-object-rest-spread"
]
}
3 changes: 3 additions & 0 deletions .importjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ module.exports = {
}
return [];
},
excludes: [
'./lib/**',
],
declarationKeyword: function({ pathToCurrentFile }) {
if (isNodeFile(pathToCurrentFile)) {
return 'const';
Expand Down
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6.9.1
4 changes: 1 addition & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ language: node_js
sudo: false

node_js:
- "4"
- "5"
- "6"
- "7"

addons:
firefox: "47.0.1"
firefox: "50.0"

before_install:
- "export DISPLAY=:99.0"
Expand Down
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ npm install -g happo

You'll also need Firefox installed on the machine. Happo uses
[selenium-webdriver](https://github.com/SeleniumHQ/selenium) under the hood,
and will support whatever version Selenium supports. Happo currently works best
with _Firefox 47.0.1_.
and will support the same version of Firefox as Selenium supports. Happo
currently works best with _Firefox > 50_. It uses
[geckodriver](https://github.com/mozilla/geckodriver) to control Firefox.
## Introduction
Expand Down Expand Up @@ -317,18 +318,26 @@ the argument to `happo upload`. E.g.
happo upload "https://test.example"
```
To debug uploading, you can use the `--debug` flag which will print additional
information to `stderr`.
To debug uploading, override the `uploader` configuration option with a
debug-enabled `S3Uploader` instance. This will print additional information to
`stderr`.
```js
const S3Uploader = require('happo/lib/server/S3Uploader');
module.exports = {
uploader: () => new S3Uploader({ debug: true });
}
```
### `happo upload-test`
Uploads a small text file to an AWS S3 account. This is useful if you want to
test your S3 configuration. Uses the same configuration as [`happo
upload`](#happo-upload-triggeredbyurl) does. As with `happo upload`, you can
apply a `--debug` flag here for a more verbose output.
upload`](#happo-upload-triggeredbyurl) does.
```sh
happo upload-test --debug
happo upload-test
```
## Running in a CI environment
Expand Down
Binary file added geckodriver/darwin-x64/geckodriver
Binary file not shown.
Binary file added geckodriver/linux-x64/geckodriver
Binary file not shown.
23 changes: 12 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{
"name": "happo",
"version": "3.0.2",
"version": "4.0.0-beta.2",
"description": "Command-line tool to visually diff JavaScript components",
"bin": {
"happo": "./bin/happo"
},
"scripts": {
"build": "npm run --silent clean && babel src/server/ -d lib/server/ --ignore __tests__ && npm run --silent webpack",
"babel": "babel src/server/ -d lib/server/ --ignore __tests__",
"build": "npm run clean && npm run babel && npm run webpack",
"clean": "rimraf lib public/*.worker.js public/*.bundle.js*",
"jest": "jest",
"jest:watch": "jest --watch",
"lint": "eslint --ext .js,.jsx .",
"prepublish": "npm run --silent lint && npm run --silent build",
"pretest": "npm run --silent lint",
"test": "npm run --silent jest",
"prepublish": "npm run lint && npm run build",
"pretest": "npm run lint",
"test": "npm run jest",
"webpack": "webpack --optimize-minimize",
"webpack-dev": "webpack --devtool eval-source-map --progress --watch"
},
Expand All @@ -30,16 +30,17 @@
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.14.0",
"babel-jest": "^17.0.2",
"babel-jest": "^18.0.0",
"babel-loader": "^6.2.5",
"babel-plugin-transform-object-rest-spread": "^6.20.2",
"babel-polyfill": "^6.13.0",
"babel-preset-airbnb": "^2.1.1",
"eslint": "^3.10.0",
"eslint-config-airbnb": "^13.0.0",
"eslint-plugin-import": "^2.1.0",
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.7.1",
"jest": "^17.0.3",
"jest": "^18.1.0",
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-waypoint": "^4.1.0",
Expand All @@ -53,9 +54,9 @@
"ejs": "^2.5.2",
"express": "^4.14.0",
"mkdirp": "^0.5.1",
"png-crop": "0.0.1",
"pngjs": "^2.3.1",
"selenium-webdriver": "^2.53.3",
"pngjs": "^3.0.0",
"ps-node": "^0.1.4",
"selenium-webdriver": "^3.0.1",
"worker-loader": "^0.7.1"
},
"jest": {
Expand Down
12 changes: 12 additions & 0 deletions src/HappoRunner.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SCREENSHOT_BOX_ID } from './server/Constants';
import getFullRect from './getFullRect';
import waitForImagesToRender from './waitForImagesToRender';

Expand Down Expand Up @@ -170,6 +171,17 @@ window.happo = {
width,
} = getFullRect(rootNodes);

// We place an (invisible) box on top of the visible rectangle. We
// then use it as the screenshot target.
const screenshotBox = document.createElement('div');
screenshotBox.style.position = 'absolute';
screenshotBox.style.left = `${left}px`;
screenshotBox.style.top = `${top}px`;
screenshotBox.style.width = `${width}px`;
screenshotBox.style.height = `${height}px`;
screenshotBox.setAttribute('id', SCREENSHOT_BOX_ID);
document.body.appendChild(screenshotBox);

resolve({
description: currentExample.description,
height,
Expand Down
3 changes: 3 additions & 0 deletions src/server/Constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
SCREENSHOT_BOX_ID: 'happo-screenshot-box',
};
61 changes: 61 additions & 0 deletions src/server/__tests__/checkBrowserVersion-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
jest.mock('child_process');
const childProcess = require('child_process');

jest.mock('../config');
const config = require('../config');

const checkBrowserVersion = require('../checkBrowserVersion');

beforeEach(() => {
config.driver = 'firefox';
});

describe('when firefox is new enough', () => {
beforeEach(() => {
childProcess.exec = (_, cb) => cb(null, 'Mozilla Firefox 50.0');
});

it('resolves', () =>
checkBrowserVersion().then(() => {
expect(true).toBe(true);
}));
});

describe('when firefox is too old', () => {
beforeEach(() => {
childProcess.exec = (_, cb) => cb(null, 'Mozilla Firefox 47.0');
});

it('rejects', () =>
checkBrowserVersion().catch((error) => {
expect(error.message).toEqual(
'Happo requires Firefox version 50 or later. You are using Mozilla Firefox 47.0');
}));
});

describe('when the version string is unrecognized', () => {
beforeEach(() => {
childProcess.exec = (_, cb) => cb(null, 'Godzilla Firefox 47.0');
});

it('rejects', () =>
checkBrowserVersion().catch((error) => {
expect(error.message).toEqual(
'Failed to parse Firefox version string "Godzilla Firefox 47.0"');
}));
});

describe('when using a different driver', () => {
beforeEach(() => {
config.driver = 'chrome';

// Just to make sure that we're not falsely succeeding because of normal
// handling, we also mock an old version of Firefox.
childProcess.exec = (_, cb) => cb(null, 'Mozilla Firefox 47.0');
});

it('resolves', () =>
checkBrowserVersion().then(() => {
expect(true).toBe(true);
}));
});
8 changes: 7 additions & 1 deletion src/server/__tests__/runVisualDiffs-test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
const os = require('os');
const path = require('path');

const jest = require('jest');
const rimraf = require('rimraf');

const { config } = require('../config');
const closeDriver = require('../closeDriver');
const initializeWebdriver = require('../initializeWebdriver');
const runVisualDiffs = require('../runVisualDiffs');
const server = require('../server');

jest.mock('../checkBrowserVersion');
const checkBrowserVersion = require('../checkBrowserVersion');

describe('runVisualDiffs', () => {
let driver;
let startedServer;
Expand All @@ -25,11 +30,12 @@ describe('runVisualDiffs', () => {

afterAll(() => {
startedServer.close();
driver.close();
return closeDriver(driver);
});

beforeEach(() => {
originalConfig = { ...config };
checkBrowserVersion.mockImplementation(() => Promise.resolve());
});

afterEach(() => {
Expand Down
8 changes: 8 additions & 0 deletions src/server/addGeckoDriverToPath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const path = require('path');

const { platform, arch } = process;

const geckodriverFolder = path.join(__dirname,
`../../geckodriver/${platform}-${arch}/`);

process.env.PATH += path.delimiter + geckodriverFolder;
37 changes: 37 additions & 0 deletions src/server/checkBrowserVersion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const childProcess = require('child_process');

const firefox = require('selenium-webdriver/firefox');

const config = require('./config');

const MINIMUM_FIREFOX_VERSION = 50.0;
const FIREFOX_VERSION_MATCHER = /Mozilla Firefox ([0-9.]+)/;

module.exports = function checkBrowserVersion() {
if (config.driver !== 'firefox') {
// Our main browser target is Firefox. If you are using something else, you
// must know what you are doing. :)
return Promise.resolve();
}

return new Promise((resolve, reject) => {
new firefox.Binary().locate().then((pathToExecutable) => {
childProcess.exec(`${pathToExecutable} --version`, (error, stdout) => {
if (error) {
reject(new Error(`Failed to check Firefox version: ${error}`));
return;
}
const match = stdout.match(FIREFOX_VERSION_MATCHER);
if (!match) {
reject(new Error(`Failed to parse Firefox version string "${stdout}"`));
} else if (parseFloat(match[1]) < MINIMUM_FIREFOX_VERSION) {
reject(new Error(
`Happo requires Firefox version ${MINIMUM_FIREFOX_VERSION} or later. ` +
`You are using ${stdout}`));
} else {
resolve();
}
});
});
});
};
31 changes: 18 additions & 13 deletions src/server/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ const crypto = require('crypto');

const commander = require('commander');

const S3Uploader = require('./S3Uploader');
const { config } = require('./config');
const checkBrowserVersion = require('./checkBrowserVersion');
const closeDriver = require('./closeDriver');
const constructUrl = require('./constructUrl');
const initializeWebdriver = require('./initializeWebdriver');
const runVisualDiffs = require('./runVisualDiffs');
Expand All @@ -21,19 +23,22 @@ commander.command('debug').action(() => {
});

commander.command('run').action(() => {
server.start().then(() => {
initializeWebdriver().then((driver) => {
server.start()
.then(checkBrowserVersion)
.then(initializeWebdriver)
.then((driver) => {
runVisualDiffs(driver)
.then(() => {
driver.close();
process.exit(0);
closeDriver(driver).then(() => {
process.exit(0);
});
})
.catch((error) => {
driver.close();
logAndExit(error);
closeDriver(driver).then(() => {
logAndExit(error);
});
});
});
});
});

commander.command('review').action(() => {
Expand All @@ -48,9 +53,9 @@ commander.command('review-demo').action(() => {
});
});

commander.command('upload [<triggeredByUrl>]').option('--debug').action(
(triggeredByUrl, { debug }) => {
uploadLastResult(triggeredByUrl, { debug })
commander.command('upload [<triggeredByUrl>]').action(
(triggeredByUrl) => {
uploadLastResult(triggeredByUrl)
.then((url) => {
if (url) {
console.log(url);
Expand All @@ -59,8 +64,8 @@ commander.command('upload [<triggeredByUrl>]').option('--debug').action(
.catch(logAndExit);
});

commander.command('upload-test').option('--debug').action(({ debug }) => {
const uploader = new S3Uploader({ debug });
commander.command('upload-test').action(() => {
const uploader = config.uploader();
uploader.prepare()
.then(() => {
uploader.upload({
Expand Down
Loading

0 comments on commit 1b4d49b

Please sign in to comment.