Skip to content
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

Merged
merged 4 commits into from
Apr 10, 2018
Merged

Conversation

brendankenny
Copy link
Member

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) and GatherRunner.collectArtifacts (to isolate the type switcheroo from a dynamic collection of gatherer results to LH.Artifacts), but the translation was fairly mechanical and all existing tests were unchanged. They also look wayyy better than before :)

Also

  • split out an artifacts.d.ts file to start collecting artifact types
  • split out an config.d.ts file, not marking a difference between the JSON form that's expected as input to Config and the normalized type coming out of the other side (e.g. LH.Config.PassJson vs LH.Config.Pass). With any luck the second form won't be necessary when Config.js is typed

})
.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);
Copy link
Member Author

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) {
Copy link
Member Author

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', () => {
Copy link
Member Author

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 () => {
Copy link
Member Author

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 :)

Copy link
Member

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?

Copy link
Member Author

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 {
Copy link
Member Author

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;
Copy link
Member Author

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: [[]],
Copy link
Member

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...

Copy link
Member Author

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

Copy link
Member Author

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 () => {
Copy link
Member

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;
Copy link
Member

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;

Copy link
Collaborator

@patrickhulce patrickhulce Apr 9, 2018

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 🎯

Copy link
Member Author

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

module LH {
export interface Artifacts {
fetchedAt: string;
LanternMetric: Artifacts.LanternMetric;
Copy link
Collaborator

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

Copy link
Member Author

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.

Copy link
Collaborator

@patrickhulce patrickhulce left a 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! 👏 💯

@patrickhulce
Copy link
Collaborator

travis seems to be displeased about h2 though 🤔

@brendankenny
Copy link
Member Author

weird. Travis now agrees that there's only 18 things loaded by dbw_tester, so good to go again

@brendankenny brendankenny merged commit 9823a65 into master Apr 10, 2018
@brendankenny brendankenny deleted the tsgatherrunner branch April 10, 2018 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants