-
Notifications
You must be signed in to change notification settings - Fork 9.5k
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(gather-runner): covert assertPageLoaded into soft failure #4048
Changes from all commits
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 |
---|---|---|
|
@@ -138,14 +138,12 @@ class GatherRunner { | |
} | ||
|
||
/** | ||
* Throws an error if the original network request failed or wasn't found. | ||
* Returns an error if the original network request failed or wasn't found. | ||
* @param {string} url The URL of the original requested page. | ||
* @param {{online: boolean}} driver | ||
* @param {!Array<WebInspector.NetworkRequest>} networkRecords | ||
* @return {?Error} | ||
*/ | ||
static assertPageLoaded(url, driver, networkRecords) { | ||
if (!driver.online) return; | ||
|
||
static getPageLoadError(url, networkRecords) { | ||
const mainRecord = networkRecords.find(record => { | ||
// record.url is actual request url, so needs to be compared without any URL fragment. | ||
return URL.equalWithExcludedFragments(record.url, url); | ||
|
@@ -162,7 +160,7 @@ class GatherRunner { | |
log.error('GatherRunner', errorMessage, url); | ||
const error = new Error(`Unable to load page: ${errorMessage}`); | ||
error.code = 'PAGE_LOAD_ERROR'; | ||
throw error; | ||
return error; | ||
} | ||
} | ||
|
||
|
@@ -260,6 +258,7 @@ class GatherRunner { | |
const passData = {}; | ||
|
||
let pass = Promise.resolve(); | ||
let pageLoadError; | ||
|
||
if (config.recordTrace) { | ||
pass = pass.then(_ => { | ||
|
@@ -280,9 +279,18 @@ class GatherRunner { | |
log.log('status', status); | ||
const devtoolsLog = driver.endDevtoolsLog(); | ||
const networkRecords = NetworkRecorder.recordsFromLogs(devtoolsLog); | ||
GatherRunner.assertPageLoaded(options.url, driver, networkRecords); | ||
log.verbose('statusEnd', status); | ||
|
||
pageLoadError = GatherRunner.getPageLoadError(options.url, networkRecords); | ||
// If the driver was offline, a page load error is expected, so do not save it. | ||
if (!driver.online) pageLoadError = null; | ||
|
||
if (pageLoadError) { | ||
gathererResults.LighthouseRunWarnings.push('Lighthouse was unable to reliably load the ' + | ||
'page you requested. Make sure you are testing the correct URL and that the server is ' + | ||
'properly responding to all requests.'); | ||
} | ||
|
||
// Expose devtoolsLog and networkRecords to gatherers | ||
passData.devtoolsLog = devtoolsLog; | ||
passData.networkRecords = networkRecords; | ||
|
@@ -295,7 +303,9 @@ class GatherRunner { | |
const status = `Retrieving: ${gatherer.name}`; | ||
return chain.then(_ => { | ||
log.log('status', status); | ||
const artifactPromise = Promise.resolve().then(_ => gatherer.afterPass(options, passData)); | ||
const artifactPromise = pageLoadError ? | ||
Promise.reject(pageLoadError) : | ||
Promise.resolve().then(_ => gatherer.afterPass(options, passData)); | ||
gathererResults[gatherer.name].push(artifactPromise); | ||
return GatherRunner.recoverOrThrow(artifactPromise); | ||
}).then(_ => { | ||
|
@@ -319,8 +329,10 @@ class GatherRunner { | |
const artifacts = {}; | ||
|
||
// Nest LighthouseRunWarnings, if any, so they will be collected into artifact. | ||
gathererResults.LighthouseRunWarnings = [gathererResults.LighthouseRunWarnings]; | ||
const uniqueWarnings = Array.from(new Set(gathererResults.LighthouseRunWarnings)); | ||
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. would it be worthwhile to change 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. eh, it's not clear when we would do the flip back to array needed for JSON.stringify, so I'm not necessarily sold. since we were already manipulating it here and aggregating across multiple passes, seems reasonable to de-dupe but let audits keep track of it on their own |
||
gathererResults.LighthouseRunWarnings = [uniqueWarnings]; | ||
|
||
const pageLoadFailures = []; | ||
return Object.keys(gathererResults).reduce((chain, gathererName) => { | ||
return chain.then(_ => { | ||
const phaseResultsPromises = gathererResults[gathererName]; | ||
|
@@ -336,9 +348,16 @@ class GatherRunner { | |
// To reach this point, all errors are non-fatal, so return err to | ||
// runner to handle turning it into an error audit. | ||
artifacts[gathererName] = err; | ||
// Track page load errors separately, so we can fail loudly if needed. | ||
if (err.code === 'PAGE_LOAD_ERROR') pageLoadFailures.push(err); | ||
}); | ||
}); | ||
}, Promise.resolve()).then(_ => { | ||
// Fail the run if more than 50% of all artifacts failed due to page load failure. | ||
if (pageLoadFailures.length > Object.keys(artifacts).length * .5) { | ||
throw pageLoadFailures[0]; | ||
} | ||
|
||
return artifacts; | ||
}); | ||
} | ||
|
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.
can we do this check within
getPageLoadError
? seems reasonable.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.
heh, I explicitly moved it out of there since it felt like it was in the wrong place over there :)
In fact I'd eventually want to remove this special check entirely to make the passes on similar footing. Is it primarily the extra line here that you don't like?