Skip to content

Conversation

@jeffposnick
Copy link
Contributor

R: @paulirish @samccone @paullewis etc.

This updates the logic in the offline.js gatherer. Instead of the XHR-based approach, which is prone to false-negatives for more complicated service workers, it goes through the steps needed to perform a full navigation to the target URL while the network is disconnected, and confirms that any successful responses were actually due to the service worker.

I've got a couple of inline comments that it would be great to get some feedback on, mainly due to my ignorance about Lighthouse's overall setup.

Closes #425

offlineResponseCode: -1
};
});
return driver.gotoURL(options.url, {waitForLoad: true})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think that this initial navigation to options.url is wasteful, since the config.json for this pass specifies "loadPage": true. That being said, when I used node lighthouse-cli <url> --audit-whitelist=works-offline to just run this one specific audit, I did end up needing to explicitly add in the initial navigation.

It may be because this is currently in a beforePass function. I don't think I could move this code to afterPass, since by the time that's called, tracingData is already set. Is there some other lifecycle function that I could use instead that would allow me to take advantage of "loadPage": true?

@jeffposnick
Copy link
Contributor Author

(I'm looking into the Travis CI build failure.)

@jeffposnick
Copy link
Contributor Author

Travis CI should be happy, and I tried to follow the model of using pre-recorded tracing data to drive the modified test cases. Happy to adjust the tests further based on any feedback.

@brendankenny
Copy link
Contributor

Looking at the network record is definitely a much better way of doing this, but in general we really want to avoid doing navigation inside gatherers. Ideally this gather can just be beforePass() { Offline.goOffline() }, afterPass() { Offline.goOnline(); /* process network records... */ } with the navigation part in between correctly handled by the driver. Hopefully we can instead land any changes in lighthouse that are needed so this test can just use the usual navigation.

I see two issues with the current master:

  • when whitelisting an audit, only the required gathers are run. Before getting to the offline gatherer itself, the offline test requires a full load of the page while online to get the SW registered, assets loaded, etc, and we have no way of expressing this with our current audit/gatherer dependency resolution.

    There are a few possible solutions here, but ultimately we want to make it clear that the offline test can't be in the first pass, the page has to have loaded before it runs, etc

  • networkRecords are overwritten for every pass that records them. Not a problem with the default config because only one pass records them in it, but as soon as something turns on network in another pass (like this PR does), each set of records will overwrite the last. networkRecords need to be updated to be stored per pass, like traces were in Trace buckets #531.

The second one will definitely have to be fixed before this will work, as it will break anything depending on network records from the first pass. Not sure what to do about the first one at this time, but I'd personally rather we (temporarily) break audit whitelisting for some gathers than start navigating in gatherers.

assert.deepEqual(offlineGather.artifact, {offlineResponseCode: 200});
});
it('returns an artifact set to -1 when offline loading fails', () => {
offlineGather.afterPass({url: 'https://do-not-match.com'}, tracingData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid testing with real network in the unit tests. The fixed smoke/end-to-end test in #518 should cover these two test cases. As far as unit testing goes, I'd say the only real thing that needs to be checked is any corner case(s) of url matching (trailing slash and...anything else?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, if the gatherer doesn't do any navigation these would be good tests, just processing static network records :)

@paulirish
Copy link
Member

networkRecords are overwritten for every pass that records them. Not a problem with the default config because only one pass records them in it, but as soon as something turns on network in another pass (like this PR does), each set of records will overwrite the last. networkRecords need to be updated to be stored per pass, like traces were....

Instead of flipping the network back on, I'd be in favor of leaving network listening after the first pass, and then in here, we'd work from the end of the network records to find a matching item.

@paulirish
Copy link
Member

Brendan is landing some items that will enable us to take this PR in easier. Thanks for the patience!

@brendankenny
Copy link
Contributor

@jeffposnick PTAL

Updated PR to take advantage of #610. Simpler and seems to support more sites than master (for instance, fixes #611).

There are some failure cases, like airhorner now reports that it doesn't work offline. I believe this is due to a flaw in gather-runner ordering. I'll make a separate PR for that.

@brendankenny
Copy link
Contributor

brendankenny commented Aug 29, 2016

also breaks under the smoketest. I'll take a look at that too :) May be the same issue as airhorner

@brendankenny
Copy link
Contributor

updated, should be good to go.

}

static goOnline(driver) {
return driver.sendCommand('Network.emulateNetworkConditions', Offline.config({offline: false}));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets move these to the driver

@jeffposnick
Copy link
Contributor Author

Your version of the code seems to give the correct results, and thanks for rewriting it using a cleaner approach!

I can still reliably trigger TypeError: this.networkManager._dispatcher.resourceChangedPriority is not a function when I run the CLI against my test site (https://ifixit-pwa.appspot.com), which I tried to address in one of my previous commits.

But given that I can reproduce the same error against the current master branch, I'll file an issue for it and it can be dealt with independent of this code change.

@jeffposnick
Copy link
Contributor Author

(I filed #621 to track the priority-related issues I'm seeing.)

@brendankenny
Copy link
Contributor

I can still reliably trigger TypeError: this.networkManager._dispatcher.resourceChangedPriority is not a function when I run the CLI against my test site (https://ifixit-pwa.appspot.com), which I tried to address in one of my previous commits.

really weird. I was hoping that doing it this way would avoid any WebInspector initialization timing issues. I'm not seeing the error at all, unfortunately, but maybe I should do a fresh npm install and see if I'm lagging in deps or something

@jeffposnick
Copy link
Contributor Author

After investigating more, @brendankenny, the errors I'm seeing don't appear to be related to the code in this PR. So they can be investigated independently.

@brendankenny
Copy link
Contributor

brendankenny commented Aug 31, 2016

lets move these to the driver

done, though it's a little ugly with the options object. Happy to listen to other ideas

afterPass(options, tracingData) {
const navigationRecord = tracingData.networkRecords.filter(record => {
// If options.url is just an origin without a path, Chrome will implicitly
// add in a path of '/'.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually took care of this part a bit ago: https://github.com/GoogleChrome/lighthouse/blob/ee92529ba/lighthouse-core/runner.js#L50-L51

can be simplified to just ...

return record._url === options.url && record._fetchedViaServiceWorker;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point. also updated to use the non-underscored getter versions of these properties

@paulirish
Copy link
Member

works for me. lgtm

@brendankenny brendankenny merged commit 50890ce into master Aug 31, 2016
@brendankenny brendankenny deleted the works-offline branch August 31, 2016 23:30
@brendankenny
Copy link
Contributor

Thanks @jeffposnick! Sorry this took so long.

@jeffposnick
Copy link
Contributor Author

Thanks for taking it over, @brendankenny!

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.

3 participants