Repository: GoogleChrome/lighthouse
Pull request #9029 (2019-05-22 20:54:03)

core(logging): change log messages for gathering and trace retrieval
Looked back at the blame, was interested to see if these steps were named differently before.

Evaluating: https://github.com/GoogleChrome/lighthouse/blame/558a26f8661565caebcbba085b26bf028a89c283/lighthouse-core/runner.js#L94

Retrieving: https://github.com/GoogleChrome/lighthouse/blame/2a4d99c93794b883c70acbe24c332aa658e3a455/lighthouse-core/gather/gather-runner.js#L149

The answer is no :)

Hoten: > > [b914ea1](https://github.com/GoogleChrome/lighthouse/commit/b914ea1fe2c555ede8aad77ccd1cbea3a3b2d8ec)
> 
> lol, commit to master of the opposite of this PR :P

ooo guess i messed up the blame hunting
patrickhulce: > I have some faint memory of someone using the text of the status log messages to provide significant functionality

(Also, the fact that in our docs we tell users to programmatically do something based on a particular log message isn't a great sign for it's non-breakingness)

Patch:
diff --git a/docs/throttling.md b/docs/throttling.md
index c54b162cd..c29cf95a1 100644
--- a/docs/throttling.md
+++ b/docs/throttling.md
@@ -53,6 +53,6 @@ comcast --latency=150 --target-bw=1638
 # Run Lighthouse with its own throttling disabled
 lighthouse --throttling.requestLatencyMs=0 --throttling.downloadThroughputKbps=0 --throttling.uploadThroughputKbps=0 # ...
 
-# Disable the traffic throttling once you see "Retrieving trace"
+# Disable the traffic throttling once you see "Gathering trace"
 comcast --stop
 ```
diff --git a/lighthouse-cli/cli-flags.js b/lighthouse-cli/cli-flags.js
index fa5bb05b8..9b9ceb989 100644
--- a/lighthouse-cli/cli-flags.js
+++ b/lighthouse-cli/cli-flags.js
@@ -11,14 +11,26 @@ const yargs = require('yargs');
 const pkg = require('../package.json');
 const printer = require('./printer.js');
 
+/**
+ * Remove in Node 11 - [].flatMap
+ * @param {Array<Array<string>>} arr
+ * @return {string[]}
+ */
+function flatten(arr) {
+  /** @type {string[]} */
+  const result = [];
+  return result.concat(...arr);
+}
+
 /**
  * @param {string=} manualArgv
  * @return {LH.CliFlags}
  */
 function getFlags(manualArgv) {
-  // @ts-ignore yargs() is incorrectly typed as not returning itself
+  // @ts-ignore yargs() is incorrectly typed as not accepting a single string.
   const y = manualArgv ? yargs(manualArgv) : yargs;
-  return y.help('help')
+  // Intentionally left as type `any` because @types/yargs doesn't chain correctly.
+  const argv = y.help('help')
       .version(() => pkg.version)
       .showHelpOnFail(false, 'Specify --help for available options')
 
@@ -46,6 +58,9 @@ function getFlags(manualArgv) {
       .example(
           'lighthouse <url> --extra-headers=./path/to/file.json',
           'Path to JSON file of HTTP Header key/value pairs to send in requests')
+      .example(
+          'lighthouse <url> --only-categories=performance,pwa',
+          'Only run specific categories.')
 
       // List of options
       .group(['verbose', 'quiet'], 'Logging:')
@@ -171,6 +186,29 @@ function getFlags(manualArgv) {
           'For more information on Lighthouse, see https://developers.google.com/web/tools/lighthouse/.')
       .wrap(yargs.terminalWidth())
       .argv;
+
+  // Support comma-separated values for some array flags by splitting on any ',' found.
+  /** @type {Array<keyof LH.CliFlags>} */
+  const arrayKeysThatSupportCsv = [
+    'onlyAudits',
+    'onlyCategories',
+    'output',
+    'plugins',
+    'skipAudits',
+  ];
+  arrayKeysThatSupportCsv.forEach(key => {
+    // If a key is defined as an array in yargs, the value (if provided)
+    // will always be a string array. However, we keep argv and input as any,
+    // since assigning back to argv as string[] would be unsound for enums,
+    // for example: output is LH.OutputMode[].
+    const input = argv[key];
+    // Truthy check is necessary. isArray convinces TS that this is an array.
+    if (Array.isArray(input)) {
+      argv[key] = flatten(input.map(value => value.split(',')));
+    }
+  });
+
+  return argv;
 }
 
 module.exports = {
diff --git a/lighthouse-core/gather/gather-runner.js b/lighthouse-core/gather/gather-runner.js
index 9c637cfcb..46388f345 100644
--- a/lighthouse-core/gather/gather-runner.js
+++ b/lighthouse-core/gather/gather-runner.js
@@ -228,14 +228,14 @@ class GatherRunner {
 
     let trace;
     if (passConfig.recordTrace) {
-      const status = {msg: 'Retrieving trace', id: `lh:gather:getTrace`};
+      const status = {msg: 'Gathering trace', id: `lh:gather:getTrace`};
       log.time(status);
       trace = await driver.endTrace();
       log.timeEnd(status);
     }
 
     const status = {
-      msg: 'Retrieving devtoolsLog & network records',
+      msg: 'Gathering devtoolsLog & network records',
       id: `lh:gather:getDevtoolsLog`,
     };
     log.time(status);
@@ -265,7 +265,7 @@ class GatherRunner {
       // Abuse the passContext to pass through gatherer options
       passContext.options = gathererDefn.options || {};
       const status = {
-        msg: `Retrieving setup: ${gatherer.name}`,
+        msg: `Gathering setup: ${gatherer.name}`,
         id: `lh:gather:beforePass:${gatherer.name}`,
       };
       log.time(status, 'verbose');
@@ -295,7 +295,7 @@ class GatherRunner {
       // Abuse the passContext to pass through gatherer options
       passContext.options = gathererDefn.options || {};
       const status = {
-        msg: `Retrieving in-page: ${gatherer.name}`,
+        msg: `Gathering in-page: ${gatherer.name}`,
         id: `lh:gather:pass:${gatherer.name}`,
       };
       log.time(status);
@@ -327,7 +327,7 @@ class GatherRunner {
     for (const gathererDefn of gatherers) {
       const gatherer = gathererDefn.instance;
       const status = {
-        msg: `Retrieving: ${gatherer.name}`,
+        msg: `Gathering: ${gatherer.name}`,
         id: `lh:gather:afterPass:${gatherer.name}`,
       };
       log.time(status);
diff --git a/lighthouse-core/runner.js b/lighthouse-core/runner.js
index 5795cc8ae..17522fa1b 100644
--- a/lighthouse-core/runner.js
+++ b/lighthouse-core/runner.js
@@ -274,7 +274,7 @@ class Runner {
   static async _runAudit(auditDefn, artifacts, sharedAuditContext) {
     const audit = auditDefn.implementation;
     const status = {
-      msg: `Evaluating: ${i18n.getFormatted(audit.meta.title, 'en-US')}`,
+      msg: `Auditing: ${i18n.getFormatted(audit.meta.title, 'en-US')}`,
       id: `lh:audit:${audit.meta.id}`,
     };
     log.time(status);


Test patch:
diff --git a/lighthouse-cli/test/cli/cli-flags-test.js b/lighthouse-cli/test/cli/cli-flags-test.js
index 99e676e37..da5549012 100644
--- a/lighthouse-cli/test/cli/cli-flags-test.js
+++ b/lighthouse-cli/test/cli/cli-flags-test.js
@@ -28,4 +28,29 @@ describe('CLI bin', function() {
       assert.ok(optionsWithDescriptions.includes(opt), `cli option '${opt}' has no description`);
     });
   });
+
+  it('array values support csv when appropriate', () => {
+    const flags = getFlags([
+      'http://www.example.com',
+      '--only-categories=performance,seo',
+      '--skipAudits=unused-javascript,redirects',
+      '--skipAudits=bootup-time',
+    ].join(' '));
+    expect(flags.onlyCategories).toEqual(['performance', 'seo']);
+    expect(flags.skipAudits).toEqual(['unused-javascript', 'redirects', 'bootup-time']);
+  });
+
+  it('array values do not support csv when appropriate', () => {
+    const flags = getFlags([
+      'http://www.example.com',
+      '--chrome-flags="--window-size 800,600"',
+      '--chrome-flags="--enabled-features=NetworkService,VirtualTime"',
+      '--blockedUrlPatterns=.*x,y\\.png',
+    ].join(' '));
+    expect(flags.chromeFlags).toEqual([
+      '--window-size 800,600',
+      '--enabled-features=NetworkService,VirtualTime',
+    ]);
+    expect(flags.blockedUrlPatterns).toEqual(['.*x,y\\.png']);
+  });
 });