Avoid headless mode in CI

This commit is contained in:
Tim Schaub
2018-11-09 09:15:28 -07:00
parent 1253558006
commit 8c89e17618
3 changed files with 60 additions and 12 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ version: 2
jobs: jobs:
build: build:
docker: docker:
- image: circleci/node:10-browsers - image: circleci/node:latest-browsers
working_directory: ~/repo working_directory: ~/repo
+1
View File
@@ -69,6 +69,7 @@
"karma-mocha": "1.3.0", "karma-mocha": "1.3.0",
"karma-sourcemap-loader": "^0.3.7", "karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^4.0.0-rc.2", "karma-webpack": "^4.0.0-rc.2",
"loglevelnext": "^3.0.0",
"marked": "0.5.1", "marked": "0.5.1",
"mocha": "5.2.0", "mocha": "5.2.0",
"mustache": "^3.0.0", "mustache": "^3.0.0",
+58 -11
View File
@@ -10,14 +10,10 @@ const fs = require('fs');
const fse = require('fs-extra'); const fse = require('fs-extra');
const pixelmatch = require('pixelmatch'); const pixelmatch = require('pixelmatch');
const yargs = require('yargs'); const yargs = require('yargs');
const log = require('loglevelnext');
const compiler = webpack(Object.assign({mode: 'development'}, config)); const compiler = webpack(Object.assign({mode: 'development'}, config));
const handler = middleware(compiler, {
lazy: true,
logLevel: 'error'
});
function getHref(entry) { function getHref(entry) {
return path.dirname(entry).slice(1) + '/'; return path.dirname(entry).slice(1) + '/';
} }
@@ -38,16 +34,24 @@ function notFound(res) {
}; };
} }
function serve(port) { function serve(options) {
const handler = middleware(compiler, {
lazy: true,
logger: options.log,
stats: 'minimal'
});
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const server = http.createServer((req, res) => { const server = http.createServer((req, res) => {
handler(req, res, notFound(res)); handler(req, res, notFound(res));
}); });
server.listen(port, err => { server.listen(options.port, options.host, err => {
if (err) { if (err) {
return reject(err); return reject(err);
} }
const address = server.address();
options.log.info(`test server listening http://${address.address}:${address.port}/`);
resolve(() => server.close()); resolve(() => server.close());
}); });
}); });
@@ -126,7 +130,7 @@ async function renderPage(page, entry, options) {
resolve(); resolve();
}; };
}); });
await page.goto(`http://localhost:${options.port}${getHref(entry)}`, {waitUntil: 'networkidle0'}); await page.goto(`http://${options.host}:${options.port}${getHref(entry)}`, {waitUntil: 'networkidle0'});
await renderCalled; await renderCalled;
await page.screenshot({path: getActualScreenshotPath(entry)}); await page.screenshot({path: getActualScreenshotPath(entry)});
} }
@@ -155,11 +159,29 @@ async function renderEach(page, entries, options) {
} }
async function render(entries, options) { async function render(entries, options) {
const browser = await puppeteer.launch(); const browser = await puppeteer.launch({
args: options.puppeteerArgs,
headless: !process.env.CI
});
let fail = false; let fail = false;
try { try {
const page = await browser.newPage(); const page = await browser.newPage();
page.on('error', err => {
options.log.error('page crash', err);
});
page.on('pageerror', err => {
options.log.error('uncaught exception', err);
});
page.on('console', message => {
const type = message.type();
if (options.log[type]) {
options.log[type](message.text());
}
});
page.setDefaultNavigationTimeout(options.timeout);
await exposeRender(page); await exposeRender(page);
await page.setViewport({width: 256, height: 256}); await page.setViewport({width: 256, height: 256});
fail = await renderEach(page, entries, options); fail = await renderEach(page, entries, options);
@@ -173,7 +195,7 @@ async function render(entries, options) {
} }
async function main(entries, options) { async function main(entries, options) {
const done = await serve(options.port); const done = await serve(options);
try { try {
await render(entries, options); await render(entries, options);
} finally { } finally {
@@ -188,13 +210,38 @@ if (require.main === module) {
describe: 'Accept all screenshots as accepted', describe: 'Accept all screenshots as accepted',
default: false default: false
}). }).
option('host', {
describe: 'The host for serving rendering cases',
default: '127.0.0.1'
}).
option('port', { option('port', {
describe: 'The port for serving rendering cases', describe: 'The port for serving rendering cases',
type: 'number',
default: 3000 default: 3000
}). }).
option('timeout', {
describe: 'The timeout for loading pages (in milliseconds)',
type: 'number',
default: 60000
}).
option('log-level', {
describe: 'The level for logging',
choices: ['trace', 'debug', 'info', 'warn', 'error', 'silent'],
default: 'error'
}).
option('puppeteer-args', {
describe: 'Args of for puppeteer.launch()',
type: 'array',
default: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : []
}).
parse(); parse();
const entries = Object.keys(config.entry).map(key => config.entry[key]); const entries = Object.keys(config.entry).map(key => config.entry[key]);
main(entries, options).catch(err => process.stderr.write(`${err.message}\n`, () => process.exit(1))); options.log = log.create({name: 'rendering', level: options.logLevel});
main(entries, options).catch(err => {
options.log.error(err.message);
process.exit(1);
});
} }