| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  | #!/bin/env node
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Usage: | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |  *   node scripts/test-pwa-score <url> <min-score> [<log-file>] | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |  * Fails if the score is below `<min-score>`. | 
					
						
							|  |  |  |  * If `<log-file>` is defined, the full results will be logged there. | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  |  * | 
					
						
							|  |  |  |  * (Ignores HTTPS-related audits, when run for HTTP URL.) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Imports
 | 
					
						
							|  |  |  | const lighthouse = require('lighthouse'); | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  | const chromeLauncher = require('lighthouse/chrome-launcher/chrome-launcher'); | 
					
						
							|  |  |  | const printer = require('lighthouse/lighthouse-cli/printer'); | 
					
						
							|  |  |  | const config = require('lighthouse/lighthouse-core/config/default.js'); | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Constants
 | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  | const VIEWER_URL = 'https://googlechrome.github.io/lighthouse/viewer/'; | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Specify the path to Chrome on Travis
 | 
					
						
							|  |  |  | if (process.env.TRAVIS) { | 
					
						
							|  |  |  |   process.env.LIGHTHOUSE_CHROMIUM_PATH = process.env.CHROME_BIN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Run
 | 
					
						
							|  |  |  | _main(process.argv.slice(2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Functions - Definitions
 | 
					
						
							|  |  |  | function _main(args) { | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |   const {url, minScore, logFile} = parseInput(args); | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  |   const isOnHttp = /^http:/.test(url); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   console.log(`Running PWA audit for '${url}'...`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (isOnHttp) { | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  |     ignoreHttpsAudits(config); | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |   launchChromeAndRunLighthouse(url, {}, config). | 
					
						
							|  |  |  |     then(results => processResults(results, logFile)). | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  |     then(score => evaluateScore(minScore, score)). | 
					
						
							|  |  |  |     catch(onError); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function evaluateScore(expectedScore, actualScore) { | 
					
						
							|  |  |  |   console.log('Lighthouse PWA score:'); | 
					
						
							|  |  |  |   console.log(`  - Expected: ${expectedScore} / 100 (or higher)`); | 
					
						
							|  |  |  |   console.log(`  - Actual:   ${actualScore} / 100`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (actualScore < expectedScore) { | 
					
						
							|  |  |  |     throw new Error(`PWA score is too low. (${actualScore} < ${expectedScore})`); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  | function ignoreHttpsAudits(config) { | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  |   const httpsAudits = [ | 
					
						
							|  |  |  |     'redirects-http' | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   console.info(`Ignoring HTTPS-related audits (${httpsAudits.join(', ')})...`); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  |   config.categories.pwa.audits.forEach(audit => { | 
					
						
							|  |  |  |     if (httpsAudits.indexOf(audit.id) !== -1) { | 
					
						
							|  |  |  |       // Ugly hack to ignore HTTPS-related audits.
 | 
					
						
							|  |  |  |       // Only meant for use during development.
 | 
					
						
							|  |  |  |       audit.weight = 0; | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |    }); | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function launchChromeAndRunLighthouse(url, flags, config) { | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  |   return chromeLauncher.launch().then(chrome => { | 
					
						
							|  |  |  |     flags.port = chrome.port; | 
					
						
							|  |  |  |     return lighthouse(url, flags, config). | 
					
						
							|  |  |  |       then(results => chrome.kill().then(() => results)). | 
					
						
							|  |  |  |       catch(err => chrome.kill().then(() => { throw err; }, () => { throw err; })); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function onError(err) { | 
					
						
							|  |  |  |   console.error(err); | 
					
						
							|  |  |  |   process.exit(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function parseInput(args) { | 
					
						
							|  |  |  |   const url = args[0]; | 
					
						
							|  |  |  |   const minScore = Number(args[1]); | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |   const logFile = args[2]; | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!url) { | 
					
						
							|  |  |  |     onError('Invalid arguments: <URL> not specified.'); | 
					
						
							|  |  |  |   } else if (isNaN(minScore)) { | 
					
						
							|  |  |  |     onError('Invalid arguments: <MIN_SCORE> not specified or not a number.'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |   return {url, minScore, logFile}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function processResults(results, logFile) { | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  |   let promise = Promise.resolve(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |   if (logFile) { | 
					
						
							|  |  |  |     console.log(`Saving results in '${logFile}'...`); | 
					
						
							|  |  |  |     console.log(`(LightHouse viewer: ${VIEWER_URL})`); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  |     results.artifacts = undefined;   // Too large for the logs.
 | 
					
						
							|  |  |  |     promise = printer.write(results, 'json', logFile); | 
					
						
							| 
									
										
										
										
											2017-05-15 15:43:08 +03:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 17:08:31 +03:00
										 |  |  |   return promise.then(() => Math.round(results.score)); | 
					
						
							| 
									
										
										
										
											2017-04-01 02:24:25 +03:00
										 |  |  | } |