Unverified Commit 872c4d7c authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #1279 from hypothesis/karma-headless-chrome

Switch default browser for running tests from PhantomJS to headless Chrome
parents 63234da5 2030edc2
# Exclude large local dirs from the Docker build context to make the image build
# faster.
.git/
build/
coverage/
node_modules/
# nb. We use Alpine as a base image and then install Node + Yarn separately
# rather than using a Node base image because this enables automated tools to
# upgrade everything by simply updating the Alpine version.
#
# Alpine is updated every 6 months so all packages are pretty recent.
FROM alpine:3.10
RUN apk update && apk add --no-cache \
chromium \
git \
make \
nodejs \
yarn
# Do not download a Chrome build as part of installing the "puppeteer" package,
# it won't work in Alpine.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
# Enable test scripts to detect that they are running from the Docker image.
ENV RUNNING_IN_DOCKER true
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
node { node {
checkout scm checkout scm
nodeEnv = docker.image("node:10-stretch")
workspace = pwd() workspace = pwd()
// Tag used when deploying to NPM. // Tag used when deploying to NPM.
...@@ -57,9 +56,18 @@ node { ...@@ -57,9 +56,18 @@ node {
} }
echo "Building and testing ${newPkgVersion}" echo "Building and testing ${newPkgVersion}"
sh "docker build -t hypothesis-client-tests ."
nodeEnv = docker.image("hypothesis-client-tests")
stage('Setup') {
nodeEnv.inside("-e HOME=${workspace}") {
sh "yarn install"
}
}
stage('Test') { stage('Test') {
nodeEnv.inside("-e HOME=${workspace}") { nodeEnv.inside("-e HOME=${workspace}") {
sh 'make test' sh "make checkformatting lint test"
} }
} }
} }
......
...@@ -72,10 +72,10 @@ ...@@ -72,10 +72,10 @@
"karma": "^4.0.0", "karma": "^4.0.0",
"karma-browserify": "^6.0.0", "karma-browserify": "^6.0.0",
"karma-chai": "^0.1.0", "karma-chai": "^0.1.0",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage-istanbul-reporter": "^2.0.4", "karma-coverage-istanbul-reporter": "^2.0.4",
"karma-mocha": "^1.1.1", "karma-mocha": "^1.1.1",
"karma-mocha-reporter": "^2.0.4", "karma-mocha-reporter": "^2.0.4",
"karma-phantomjs-launcher": "^1.0.1",
"karma-sinon": "^1.0.5", "karma-sinon": "^1.0.5",
"katex": "^0.10.0", "katex": "^0.10.0",
"lodash.debounce": "^4.0.3", "lodash.debounce": "^4.0.3",
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
"postcss-url": "^8.0.0", "postcss-url": "^8.0.0",
"preact": "10.0.0-rc.1", "preact": "10.0.0-rc.1",
"prettier": "1.18.2", "prettier": "1.18.2",
"puppeteer": "^1.2.0",
"query-string": "^3.0.1", "query-string": "^3.0.1",
"raf": "^3.1.0", "raf": "^3.1.0",
"raven-js": "^3.7.0", "raven-js": "^3.7.0",
......
...@@ -30,11 +30,6 @@ describe('DocumentMeta', function() { ...@@ -30,11 +30,6 @@ describe('DocumentMeta', function() {
tempDocument.appendChild(tempDocumentHead); tempDocument.appendChild(tempDocumentHead);
fakeNormalizeURI = sinon.stub().callsFake((url, base) => { fakeNormalizeURI = sinon.stub().callsFake((url, base) => {
if (url === 'http://a:b:c') {
// A modern browser would reject this URL, but PhantomJS's URL parser is
// more lenient.
throw new Error('Invalid URL');
}
return normalizeURI(url, base); return normalizeURI(url, base);
}); });
......
/* global process */
'use strict'; 'use strict';
/* global __dirname */ /* global __dirname */
...@@ -5,6 +7,28 @@ ...@@ -5,6 +7,28 @@
const path = require('path'); const path = require('path');
const envify = require('loose-envify/custom'); const envify = require('loose-envify/custom');
let chromeFlags = [];
process.env.CHROME_BIN = require('puppeteer').executablePath();
// On Travis and in Docker, the tests run as root, so the sandbox must be
// disabled.
if (process.env.TRAVIS || process.env.RUNNING_IN_DOCKER) {
chromeFlags.push('--no-sandbox');
}
if (process.env.RUNNING_IN_DOCKER) {
// Disable `/dev/shm` usage as this can cause Chrome to fail to load large
// HTML pages, such as the one Karma creates with all the tests loaded.
//
// See https://github.com/GoogleChrome/puppeteer/issues/1834 and
// https://github.com/karma-runner/karma-chrome-launcher/issues/198.
chromeFlags.push('--disable-dev-shm-usage');
// Use Chromium from Alpine packages. The one that Puppeteer downloads won't
// load in Alpine.
process.env.CHROME_BIN = 'chromium-browser';
}
module.exports = function(config) { module.exports = function(config) {
config.set({ config.set({
// base path that will be used to resolve all patterns (eg. files, exclude) // base path that will be used to resolve all patterns (eg. files, exclude)
...@@ -16,14 +40,6 @@ module.exports = function(config) { ...@@ -16,14 +40,6 @@ module.exports = function(config) {
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
// Polyfills for PhantomJS
'./shared/polyfills/es2015.js',
'./shared/polyfills/es2016.js',
'./shared/polyfills/es2017.js',
'./shared/polyfills/string.prototype.normalize.js',
'./shared/polyfills/fetch.js',
'./shared/polyfills/url.js',
// Test setup // Test setup
'./sidebar/test/bootstrap.js', './sidebar/test/bootstrap.js',
...@@ -138,9 +154,16 @@ module.exports = function(config) { ...@@ -138,9 +154,16 @@ module.exports = function(config) {
// start these browsers // start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'], browsers: ['ChromeHeadless_Custom'],
browserNoActivityTimeout: 20000, // Travis is slow... browserNoActivityTimeout: 20000, // Travis is slow...
customLaunchers: {
ChromeHeadless_Custom: {
base: 'ChromeHeadless',
flags: chromeFlags,
},
},
// Continuous Integration mode // Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits // if true, Karma captures browsers, runs the tests and exits
singleRun: false, singleRun: false,
......
...@@ -208,7 +208,7 @@ describe('GroupListItem', () => { ...@@ -208,7 +208,7 @@ describe('GroupListItem', () => {
const onExpand = sinon.stub(); const onExpand = sinon.stub();
const wrapper = createGroupListItem(fakeGroup, { onExpand }); const wrapper = createGroupListItem(fakeGroup, { onExpand });
const toggleSubmenu = () => { const toggleSubmenu = () => {
const dummyEvent = new Event(); const dummyEvent = new Event('dummy');
act(() => { act(() => {
wrapper wrapper
.find('MenuItem') .find('MenuItem')
......
...@@ -57,8 +57,8 @@ describe('Slider', () => { ...@@ -57,8 +57,8 @@ describe('Slider', () => {
wrapper.setProps({ visible: false }); wrapper.setProps({ visible: false });
setTimeout(() => { setTimeout(() => {
const { height } = wrapper.getDOMNode().getBoundingClientRect(); const containerStyle = wrapper.getDOMNode().style;
assert.equal(height, 0); assert.equal(containerStyle.height, '0px');
done(); done();
}, 1); }, 1);
}); });
......
...@@ -31,7 +31,7 @@ describe('Timestamp', () => { ...@@ -31,7 +31,7 @@ describe('Timestamp', () => {
it('displays a link if an "href" is provided', () => { it('displays a link if an "href" is provided', () => {
const wrapper = createTimestamp({ const wrapper = createTimestamp({
timestamp: '', timestamp: '2016-06-10',
href: 'https://example.com', href: 'https://example.com',
}); });
const link = wrapper.find('a'); const link = wrapper.find('a');
...@@ -40,7 +40,7 @@ describe('Timestamp', () => { ...@@ -40,7 +40,7 @@ describe('Timestamp', () => {
}); });
it('displays static text if no "href" is provided', () => { it('displays static text if no "href" is provided', () => {
const wrapper = createTimestamp({ timestamp: '' }); const wrapper = createTimestamp({ timestamp: '2016-06-10' });
assert.equal(wrapper.find('a').length, 0); assert.equal(wrapper.find('a').length, 0);
assert.equal(wrapper.find('span').length, 1); assert.equal(wrapper.find('span').length, 1);
}); });
......
...@@ -175,10 +175,7 @@ function createDirective( ...@@ -175,10 +175,7 @@ function createDirective(
/** Helper to dispatch a native event to a DOM element. */ /** Helper to dispatch a native event to a DOM element. */
function sendEvent(element, eventType) { function sendEvent(element, eventType) {
// createEvent() used instead of Event constructor const event = new Event(eventType, { bubbles: true, cancelable: true });
// for PhantomJS compatibility
const event = document.createEvent('Event');
event.initEvent(eventType, true /* bubbles */, true /* cancelable */);
element.dispatchEvent(event); element.dispatchEvent(event);
} }
......
...@@ -22,7 +22,7 @@ describe('sidebar.services.api', function() { ...@@ -22,7 +22,7 @@ describe('sidebar.services.api', function() {
function defaultBodyForStatus(status) { function defaultBodyForStatus(status) {
if (status === 204) { if (status === 204) {
return ''; return null;
} else if (status >= 500) { } else if (status >= 500) {
return '<html><body>Internal Server Error</body></html>'; return '<html><body>Internal Server Error</body></html>';
} else { } else {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment