-
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(tsc): add type checking to gather-runner #4944
Conversation
}) | ||
.then(_ => driver.beginEmulation(options.settings)) | ||
.then(_ => driver.enableRuntimeEvents()) | ||
.then(_ => driver.cacheNatives()) | ||
.then(_ => driver.registerPerformanceObserver()) | ||
.then(_ => driver.dismissJavaScriptDialogs()) | ||
.then(_ => resetStorage && driver.clearDataForOrigin(options.url)); | ||
.then(_ => { | ||
if (resetStorage) return driver.clearDataForOrigin(options.url); |
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.
sorry, tsc rightly complains about the return type of resetStorage && driver.clearDataForOrigin(options.url))
. Good news is this will be much nicer when we switch to async/await for these functions :)
const tracingData = { | ||
traces: {}, | ||
devtoolsLogs: {}, | ||
}; | ||
|
||
if (typeof options.url !== 'string' || options.url.length === 0) { |
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.
these are already checked by runner
, so no need to waste our time
@@ -106,22 +106,12 @@ describe('GatherRunner', function() { | |||
}); | |||
}); | |||
|
|||
it('creates settings if needed', () => { |
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.
deleted tests are for deleted options.url
, etc checks above
@@ -622,6 +597,85 @@ describe('GatherRunner', function() { | |||
}); | |||
|
|||
describe('artifact collection', () => { | |||
it('runs gatherer lifecycle methods strictly in sequence', async () => { |
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.
as we switch from promise reduce chains to for loops, want to make sure our gatherers never execute in parallel :)
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.
sg. wanna add a comment saying this?
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
|
||
declare global { | ||
module LH { | ||
export interface 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.
LH.Artifacts
is both an interface and a namespace. Typescript correctly knows if you're referring to a type (e.g. @param {LH.Artifacts.TraceTimes} traceTimes
in a jsdoc) to look up in the namespace while if you're referring to a property on something with the LH.Artifacts
interface (e.g. artifacts.TraceTimes
in actual js code) to look up in the interface.
Let me know if that's confusing, but in practice they're separate worlds and it doesn't seem to cause confusion. And we get to avoid a different name for each, e.g. LH.Artifacts.TraceTimes
vs LH.ArtifactTypes.TraceTimes
or whatever
} else if (cliFlags.perf) { | ||
config = /** @type {!LH.Config} */ (perfOnlyConfig); | ||
config = perfOnlyConfig; |
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.
since these are now js
files, typescript now imports them and checks that they're compatible with being assigned to LH.Config.Json|undefined
here :)
const gathererResults = { | ||
LighthouseRunWarnings: [], | ||
LighthouseRunWarnings: [[]], |
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.
What's up with this nested array? We always seem to only use [0]
from it...
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.
technically all gatherResults
are nested arrays, we just tricked things before by nesting LighthouseRunWarnings
at the last minute in collectArtifacts
. Agreed that this version is a lot more fragile and (seemingly) arbitrary, though. I'll take another go at it
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.
What's up with this nested array?
ok, how's that
@@ -622,6 +597,85 @@ describe('GatherRunner', function() { | |||
}); | |||
|
|||
describe('artifact collection', () => { | |||
it('runs gatherer lifecycle methods strictly in sequence', async () => { |
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.
sg. wanna add a comment saying this?
* The pre-normalization Lighthouse Config format. | ||
*/ | ||
export interface Json { | ||
settings?: SettingsJson; |
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.
shall we flesh this out a bit more?
settings?; SettingsJson;
passes?: PassJson[];
extends?: string;
audits?: string[];
categories?: Object;
groups?: Object;
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.
audit might go down the rabbit hole that gatherers did but sg, it might make more sense to not type at all until we flesh them out fully though.
extends
with 'lighthouse:full' | 'lighthouse:default'
would be 🎯
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.
yeah, I think we're going to have to face this when we add types to config.js and do it right
typings/artifacts.d.ts
Outdated
module LH { | ||
export interface Artifacts { | ||
fetchedAt: string; | ||
LanternMetric: Artifacts.LanternMetric; |
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 remove this, TraceOfTab, and TraceTimes from this one, just need the typedefs
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.
yeah, whoops, good catch. Computed 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.
you know what they say, mo' types no problems! 👏 💯
travis seems to be displeased about h2 though 🤔 |
weird. Travis now agrees that there's only 18 things loaded by dbw_tester, so good to go again |
adding types was fairly straightforward.
I did have to async/await two functions:
GatherRunner.afterPass
(to get the compiler to realize all sorts of things aren't|undefined
by the end of it) andGatherRunner.collectArtifacts
(to isolate the type switcheroo from a dynamic collection of gatherer results toLH.Artifacts
), but the translation was fairly mechanical and all existing tests were unchanged. They also look wayyy better than before :)Also
artifacts.d.ts
file to start collecting artifact typesconfig.d.ts
file, not marking a difference between the JSON form that's expected as input toConfig
and the normalized type coming out of the other side (e.g.LH.Config.PassJson
vsLH.Config.Pass
). With any luck the second form won't be necessary whenConfig.js
is typed