-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core(runner): split lhr, artifacts return, respect output type #4999
Changes from 1 commit
6c6b0b1
774d3d3
f6e9dbc
e194afc
c7a5aec
23cf111
ced2c2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,12 +95,12 @@ function handleError(err) { | |
} | ||
|
||
/** | ||
* @param {!LH.Results} results | ||
* @param {!Object} artifacts | ||
* @param {!LH.RunnerResult} results | ||
* @param {!LH.Flags} flags | ||
* @return {Promise<void>} | ||
*/ | ||
function saveResults(results, artifacts, flags) { | ||
function saveResults(results, flags) { | ||
const {lhr, artifacts} = results; | ||
const cwd = process.cwd(); | ||
let promise = Promise.resolve(); | ||
|
||
|
@@ -110,12 +110,12 @@ function saveResults(results, artifacts, flags) { | |
// Use the output path as the prefix for all generated files. | ||
// If no output path is set, generate a file prefix using the URL and date. | ||
const configuredPath = !flags.outputPath || flags.outputPath === 'stdout' ? | ||
getFilenamePrefix(results) : | ||
getFilenamePrefix(lhr) : | ||
flags.outputPath.replace(/\.\w{2,4}$/, ''); | ||
const resolvedPath = path.resolve(cwd, configuredPath); | ||
|
||
if (flags.saveAssets) { | ||
promise = promise.then(_ => assetSaver.saveAssets(artifacts, results.audits, resolvedPath)); | ||
promise = promise.then(_ => assetSaver.saveAssets(artifacts, lhr.audits, resolvedPath)); | ||
} | ||
|
||
return promise.then(_ => { | ||
|
@@ -149,7 +149,7 @@ function saveResults(results, artifacts, flags) { | |
* @param {string} url | ||
* @param {LH.Flags} flags | ||
* @param {LH.Config.Json|undefined} config | ||
* @return {Promise<LH.Results|void>} | ||
* @return {Promise<LH.RunnerResult|void>} | ||
*/ | ||
function runLighthouse(url, flags, config) { | ||
/** @type {!LH.LaunchedChrome} */ | ||
|
@@ -170,9 +170,7 @@ function runLighthouse(url, flags, config) { | |
return lighthouse(url, flags, config).then(results => { | ||
return potentiallyKillChrome().then(_ => results); | ||
}).then(results => { | ||
const artifacts = results.artifacts; | ||
delete results.artifacts; | ||
return saveResults(results, artifacts, flags).then(_ => results); | ||
return saveResults(results, flags).then(_ => results); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rename There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
}); | ||
}); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ const Config = require('./config/config'); | |
* @param {string} url | ||
* @param {LH.Flags} flags | ||
* @param {LH.Config.Json|undefined} configJSON | ||
* @return {Promise<LH.Results>} | ||
* @return {Promise<LH.RunnerResult>} | ||
*/ | ||
function lighthouse(url, flags = {}, configJSON) { | ||
const startTime = Date.now(); | ||
|
@@ -46,10 +46,12 @@ function lighthouse(url, flags = {}, configJSON) { | |
// kick off a lighthouse run | ||
return Runner.run(connection, {url, config}) | ||
.then((lighthouseResults = {}) => { | ||
lighthouseResults.lhr = lighthouseResults.lhr || {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rename to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
// Annotate with time to run lighthouse. | ||
const endTime = Date.now(); | ||
lighthouseResults.timing = lighthouseResults.timing || {}; | ||
lighthouseResults.timing.total = endTime - startTime; | ||
lighthouseResults.lhr.timing = lighthouseResults.lhr.timing || {}; | ||
lighthouseResults.lhr.timing.total = endTime - startTime; | ||
|
||
return lighthouseResults; | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. live under |
||
* @license Copyright 2018 Google Inc. All Rights Reserved. | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. | ||
*/ | ||
'use strict'; | ||
|
||
const ReportGenerator = require('../report/v2/report-generator'); | ||
|
||
/** | ||
* Converts the results to a CSV formatted string | ||
* Each row describes the result of 1 audit with | ||
* - the name of the category the audit belongs to | ||
* - the name of the audit | ||
* - a description of the audit | ||
* - the score type that is used for the audit | ||
* - the score value of the audit | ||
* | ||
* @param {LH.Result} lhr | ||
* @returns {string} | ||
*/ | ||
function toCSVReport(lhr) { | ||
// To keep things "official" we follow the CSV specification (RFC4180) | ||
// The document describes how to deal with escaping commas and quotes etc. | ||
const CRLF = '\r\n'; | ||
const separator = ','; | ||
/** @param {string} value @returns {string} */ | ||
const escape = (value) => `"${value.replace(/"/g, '""')}"`; | ||
|
||
|
||
// Possible TODO: tightly couple headers and row values | ||
const header = ['category', 'name', 'title', 'type', 'score']; | ||
const table = lhr.reportCategories.map(category => { | ||
return category.audits.map(catAudit => { | ||
const audit = lhr.audits[catAudit.id]; | ||
return [category.name, audit.name, audit.description, audit.scoreDisplayMode, audit.score] | ||
.map(value => value.toString()) | ||
.map(escape); | ||
}); | ||
}); | ||
|
||
// @ts-ignore TS loses track of type Array | ||
const flattedTable = [].concat(...table); | ||
return [header, ...flattedTable].map(row => row.join(separator)).join(CRLF); | ||
} | ||
|
||
/** | ||
* Creates the results output in a format based on the `mode`. | ||
* @param {LH.Result} lhr | ||
* @param {string} outputMode | ||
* @return {string} | ||
*/ | ||
function createOutput(lhr, outputMode) { | ||
// HTML report. | ||
if (outputMode === 'html') { | ||
return new ReportGenerator().generateReportHtml(lhr); | ||
} | ||
// JSON report. | ||
if (outputMode === 'json') { | ||
return JSON.stringify(lhr, null, 2); | ||
} | ||
// CSV report. | ||
if (outputMode === 'csv') { | ||
return toCSVReport(lhr); | ||
} | ||
|
||
throw new Error('Invalid output mode: ' + outputMode); | ||
} | ||
|
||
module.exports = { | ||
createOutput, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,16 +17,15 @@ const fs = require('fs'); | |
const path = require('path'); | ||
const URL = require('./lib/url-shim'); | ||
const Sentry = require('./lib/sentry'); | ||
const getFormattedReport = require('./lib/format-output').createOutput; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nearly all our source files are defined as nouns, so we should do |
||
|
||
const Connection = require('./gather/connections/connection.js'); // eslint-disable-line no-unused-vars | ||
|
||
/** @typedef {LH.Result & {artifacts: LH.Artifacts}} RunnerResult */ | ||
|
||
class Runner { | ||
/** | ||
* @param {Connection} connection | ||
* @param {{config: LH.Config, url: string, initialUrl?: string, driverMock?: Driver}} opts | ||
* @return {Promise<RunnerResult|undefined>} | ||
* @return {Promise<LH.RunnerResult|undefined>} | ||
*/ | ||
static async run(connection, opts) { | ||
try { | ||
|
@@ -118,7 +117,8 @@ class Runner { | |
if (opts.config.categories) { | ||
reportCategories = ReportScoring.scoreAllCategories(opts.config.categories, resultsById); | ||
} | ||
return { | ||
|
||
const lhr = { | ||
userAgent: artifacts.UserAgent, | ||
lighthouseVersion, | ||
fetchedAt: artifacts.fetchedAt, | ||
|
@@ -127,11 +127,13 @@ class Runner { | |
url: opts.url, | ||
runWarnings: lighthouseRunWarnings, | ||
audits: resultsById, | ||
artifacts, | ||
runtimeConfig: Runner.getRuntimeConfig(settings), | ||
reportCategories, | ||
reportGroups: opts.config.groups, | ||
}; | ||
|
||
const formattedReport = getFormattedReport(lhr, settings.output); | ||
return {lhr, formattedReport, artifacts}; | ||
} catch (err) { | ||
// @ts-ignore TODO(bckenny): Sentry type checking | ||
await Sentry.captureException(err, {level: 'fatal'}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename
results
torunnerResult
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done