diff --git a/Dockerfile b/Dockerfile index cb06296..a3a184b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,8 +5,9 @@ MAINTAINER Jay MOULIN #https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md RUN mkdir -p /home/chrome/testcases && cd /home/chrome && yarn add google-lighthouse-puppeteer COPY entrypoint.sh /usr/bin/entrypoint -COPY ./bin/lighthouse-puppeteer.js /home/chrome/lighthouse-puppeteer +COPY ./bin/lighthouse-puppeteer.js /home/chrome/bin/lighthouse-puppeteer +COPY ./lighthouse-puppeteer.js /home/chrome/lighthouse-puppeteer.js WORKDIR /home/chrome VOLUME /home/chrome/testcases - +ENV PATH="/home/chrome/bin:${PATH}" ENTRYPOINT ["entrypoint"] diff --git a/README.md b/README.md index ead2458..dd1c3cc 100644 --- a/README.md +++ b/README.md @@ -58,58 +58,61 @@ npm install -g google-lighthouse-puppeteer --unsafe-perm=true ### CLI Usage ``` -lighthouse-puppeteer /path/to/your/test/case.js [options] -``` +$> lighthouse-puppeteer -h -with : -* `/path/to/you/test/case.js` a JS file matching the spec below -* `options` optional JSON parameter to configure components +Options -#### options + -f, --file FILE Path to your testcase REQUIRED (default option) + (example: /home/chrome/testcases/mytestcase.js) + -p, --port PORT Chrome headless debug port (default: 9222) + -v, --verbose The more you add, the more it show information + -h, --help Print this usage guide. -Default: +Lighthouse -```json -{ - debugPort:9222, //port to communicate with chrome-debug (change only if you know what you are doing) - lighthouse: { //parameters sent to lighthouse-batch - params:'', //optional parameters to be passed to lighthouse - useGlobal:true, //should use running chrome-debug or not (yes to use default, no to launch a new one with lighthouse) (change only if you know what you are doing) - out:'/home/chrome/reports', //path to export reports to - html:true, //true to export HTML reports with JSON reports, false for json only - verbose:false, //false to hide debug, true to display some more informations - }, - puppeteer: { //parameters sent to puppeteer - args: [ - ] - } -} + -d, --output_directory FOLDER Path to output reports + (default: /home/chrome/reports) + -w, --html Renders HTML reports alongside JSON reports + -l, --lighthouse_params Optional parameters to pass to lighthouse + (example: "--quiet --perf") + +Puppeteer + + You can add your options for puppeteer by prefixing them with --puppeteer- + (https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions) + + example: "--puppeteer-ignoreHTTPSErrors --puppeteer-slowMo 20" ``` ### Package Usage ```javascript const lp = require('google-lighthouse-puppeteer'); - -lp.exec('/path/to/my/test.js') +const options = {}; +lp.exec('/path/to/my/test.js', options) .then(() => console.log('everything ok')) .catch((err) => console.error(err)); ``` +### Options -#### options +You can change some options like in CLI : -Default: - -``` +```json { - debugPort:9222, //port to communicate with chrome-debug (change only if you know what you are doing) - lighthouse: { - params:'', //optional parameters to be passed to lighthouse - useGlobal:true, //should use running chrome-debug or not (yes to use default, no to launch a new one with lighthouse) (change only if you know what you are doing) - out:'/home/chrome/reports', //path to export reports to - html:true, //true to export HTML reports with JSON reports, false for json only - verbose:false, //false to hide debug, true to display some more informations - } + "main": { + "port":9222, + "verbose":[true, true] //the more you add true, the more the verbosity + }, + "lighthouse": { + "params":"", + "output_directory":"/home/chrome/reports", + "lighthouse_params":"" + }, + "_unknown": [ //for puppeteer + "--puppeteer-ignoreHTTPSErrors", + "--puppeteer-slowMo", + "20" + ] } ``` diff --git a/bin/lighthouse-puppeteer.js b/bin/lighthouse-puppeteer.js index 8ca0505..70a9e9a 100755 --- a/bin/lighthouse-puppeteer.js +++ b/bin/lighthouse-puppeteer.js @@ -1,28 +1,87 @@ #! /usr/bin/env node - -if (process.argv.length <= 2) { - console.log(`Usage: ${__filename} testcase [options]`); +const clu = require('command-line-usage'); +const cla = require('command-line-args'); +const optionDefinitions = [ + { + name: 'file', + alias: 'f', + typeLabel: '[underline]{FILE}', + description: 'Path to your testcase [underline]{REQUIRED} (default option)' + + '\n([italic]{example}: /home/chrome/testcases/mytestcase.js)', + defaultOption: true, + group: 'main', + }, + { + name: 'port', + alias: 'p', + typeLabel: '[underline]{PORT}', + description: 'Chrome headless debug port ([italic]{default}: 9222)', + defaultValue: 9222, + type: Number, + group: 'main', + }, + { + name: 'output_directory', + alias: 'd', + typeLabel: '[underline]{FOLDER}', + description: 'Path to output reports' + + '\n([italic]{default}: /home/chrome/reports)', + defaultValue: '/home/chrome/reports', + group: 'lighthouse' + }, + { + name: 'html', + alias: 'w', + description: 'Renders HTML reports alongside JSON reports', + type: Boolean, + group: 'lighthouse' + }, + { + name: 'lighthouse_params', + alias: 'l', + description: 'Optional parameters to pass to lighthouse' + + '\n([italic]{example}: "--quiet --perf")', + group: 'lighthouse' + }, + { + name: 'verbose', + alias: 'v', + description: 'The more you add, the more it show information', + type: Boolean, + multiple: true, + group: 'main', + }, + { + name: 'help', + alias: 'h', + description: 'Print this usage guide.', + type: Boolean, + group: 'main', + } +]; +const definition = [ + { + header: "Options", + optionList: optionDefinitions, + group: 'main', + }, + { + header: "Lighthouse", + optionList: optionDefinitions, + group: 'lighthouse', + }, + { + header: "Puppeteer", + content: 'You can add your options for puppeteer by prefixing them with [bold]{--puppeteer-}' + + '\n(https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)' + + '\n\n[italic]{example}: "--puppeteer-ignoreHTTPSErrors --puppeteer-slowMo"' + } +]; +const usage = clu(definition); +const options = cla(optionDefinitions, {partial: true}); +if (options.main.help || typeof(options.main.file) === 'undefined' || !options.main.file.length) { + console.log(usage); process.exit(-1); } - -const fs = require('fs'); -const modulePath = process.argv[2]; -const opts = process.argv[3] || '{}'; - -if (!fs.existsSync(modulePath)) { - console.log(`File must exists : ${modulePath}`); - process.exit(-2); -} -const testcase = require(modulePath); -if (typeof(testcase.connect) !== 'function') { - - console.log(`${modulePath}: Module incorrectly formatted. Module should have "connect" method!`); - process.exit(-3); -} -if (typeof(testcase.getUrls) !== 'function') { - console.log(`${modulePath}: Module incorrectly formatted. Module should have "getUrls" method!`); - process.exit(-4); -} - -const lighthousePuppeteer = require('google-lighthouse-puppeteer'); -lighthousePuppeteer.exec(testcase, JSON.parse(opts)).catch((error) => console.error(error)); +const lighthousePuppeteer = require('../lighthouse-puppeteer'); +lighthousePuppeteer.exec(options.main.file, options).catch((error) => console.error(error)); diff --git a/entrypoint.sh b/entrypoint.sh index 91d10ce..f328f34 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -2,7 +2,7 @@ set -e if [[ -f "/home/chrome/testcases/$1.js" ]]; then - ./lighthouse-puppeteer "/home/chrome/testcases/$1.js" "$2" + lighthouse-puppeteer "/home/chrome/testcases/$1.js" "$2" else exec "$@" fi diff --git a/lighthouse-puppeteer.js b/lighthouse-puppeteer.js index 57b1219..8da376a 100755 --- a/lighthouse-puppeteer.js +++ b/lighthouse-puppeteer.js @@ -6,23 +6,60 @@ class LighthousePuppeteer { this.defaultOptions = { debugPort: this.DEBUG_PORT, lighthouse: { - params: '', - useGlobal: true, out: '/home/chrome/reports', - html: true, - verbose: false, + html: false, + params: '', + verbose: false }, puppeteer: { args: [] } }; + this.options = Object.assign({}, this.defaultOptions); this.browser = null; } + definePuppeteerOptions(opts = []) { + for (let name in opts) { + if (opts[name].startsWith('--puppeteer-')) { + const param = opts[name].replace('--puppeteer-', ''); + const nextParam = opts[name - -1]; + this.options.puppeteer[param] = nextParam.startsWith('--puppeteer-') || (nextParam || true); + } + } + return this; + } + + defineOptions(opts = {}) { + if (opts.main.port) { + this.options.debugPort = opts.main.port; + } + if (opts.lighthouse && opts.lighthouse.output_directory) { + this.options.lighthouse.out = opts.lighthouse.output_directory; + } + if (opts.lighthouse && opts.lighthouse.html) { + this.options.lighthouse.html = opts.lighthouse.html; + } + if (opts.lighthouse && opts.lighthouse.lighthouse_params) { + this.options.lighthouse.params = opts.lighthouse.lighthouse_params; + } + if (!opts.main.verbose) { + this.options.lighthouse.params += '--quiet'; + } + if (opts.main.verbose && opts.main.verbose.length > 1) { + this.options.lighthouse.verbose = true; + } + this.definePuppeteerOptions(opts._unknown || []); + if (typeof (this.options.puppeteer.args) === 'undefined') { + this.options.puppeteer.args = []; + } + this.options.puppeteer.args.push(`--remote-debugging-port=${this.options.debugPort}`); + return this; + } + exec(modulePath, opts = {}) { return new Promise((resolveGlobal, reject) => { - let options = Object.assign({}, this.defaultOptions, opts); - options.puppeteer.args.push(`--remote-debugging-port=${options.debugPort}`); + this.defineOptions(opts); const testcase = typeof (modulePath) === 'object' ? modulePath : require(modulePath); if (typeof(testcase.connect) !== 'function') { console.log(`${modulePath}: Module incorrectly formatted. Module should have "connect" method!`); @@ -32,7 +69,7 @@ class LighthousePuppeteer { console.log(`${modulePath}: Module incorrectly formatted. Module should have "getUrls" method!`); process.exit(-4); } - this.puppeteer.launch(options.puppeteer) + this.puppeteer.launch(this.options.puppeteer) .then(testcase.connect) .then(b => new Promise((resolve) => { this.browser = b; @@ -40,12 +77,12 @@ class LighthousePuppeteer { })) .then(b => new Promise((resolve) => { const lighthouseOptions = { - verbose: options.lighthouse.verbose, + verbose: this.options.lighthouse.verbose, sites: testcase.getUrls(), - html: options.lighthouse.html, - out: options.lighthouse.out, - useGlobal: options.lighthouse.useGlobal, - params: `--port ${options.debugPort} ${options.lighthouse.params}`, + html: this.options.lighthouse.html, + out: this.options.lighthouse.out, + useGlobal: true, + params: `--port ${this.options.debugPort} ${this.options.lighthouse.params}`, }; this.lightHouseBatch(lighthouseOptions); resolve(b); diff --git a/package.json b/package.json index 4ee8614..2412bf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "google-lighthouse-puppeteer", - "version": "0.2.7", + "version": "0.3.0", "description": "Google Lighthouse Puppeteer is a package to generate reports on multiple urls that allows or not authentication", "main": "lighthouse-puppeteer.js", "scripts": { @@ -19,6 +19,8 @@ "lighthouse-puppeteer": "./bin/lighthouse-puppeteer.js" }, "dependencies": { + "command-line-args": "^4.0.7", + "command-line-usage": "^4.0.1", "lighthouse-batch": "^2.1.0", "puppeteer": "^0.13.0" },