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

Ignore negative TTFB values in Firefox #147

Merged
merged 1 commit into from May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/getTTFB.ts
Expand Up @@ -59,6 +59,10 @@ export const getTTFB = (onReport: ReportHandler) => {
metric.value = metric.delta =
(navigationEntry as PerformanceNavigationTiming).responseStart;

// In some cases the value reported is negative. Ignore these cases:
// https://github.com/GoogleChrome/web-vitals/issues/137
if (metric.value < 0) return;

metric.entries = [navigationEntry];

onReport(metric);
Expand Down
31 changes: 26 additions & 5 deletions test/e2e/getTTFB-test.js
Expand Up @@ -16,7 +16,7 @@

const assert = require('assert');
const {beaconCountIs, clearBeacons, getBeacons} = require('../utils/beacons.js');

const {afterLoad} = require('../utils/afterLoad.js');

/**
* Accepts a PerformanceNavigationTimingEntry (or shim) and asserts that it
Expand Down Expand Up @@ -68,9 +68,12 @@ describe('getTTFB()', async function() {
it('reports the correct value when run during page load', async function() {
await browser.url('/test/ttfb');

await beaconCountIs(1);
const ttfb = await getTTFBBeacon();

const [ttfb] = await getBeacons();
if (browser.capabilities.browserName === 'firefox' && !ttfb) {
// Skipping test in Firefox due to entry not reported.
this.skip();
}

assert(ttfb.value >= 0);
assert(ttfb.value >= ttfb.entries[0].requestStart);
Expand All @@ -86,9 +89,12 @@ describe('getTTFB()', async function() {
it('reports the correct value when run after page load', async function() {
await browser.url('/test/ttfb?awaitLoad=1');

await beaconCountIs(1);
const ttfb = await getTTFBBeacon();

const [ttfb] = await getBeacons();
if (browser.capabilities.browserName === 'firefox' && !ttfb) {
// Skipping test in Firefox due to entry not reported.
this.skip();
}

assert(ttfb.value >= 0);
assert(ttfb.value >= ttfb.entries[0].requestStart);
Expand All @@ -101,3 +107,18 @@ describe('getTTFB()', async function() {
assertValidEntry(ttfb.entries[0]);
});
});

const getTTFBBeacon = async () => {
// In Firefox, sometimes no TTFB is reported due to negative values.
// https://github.com/GoogleChrome/web-vitals/issues/137
if (browser.capabilities.browserName === 'firefox') {
// In Firefox, wait 1 second after load.
await afterLoad();
await browser.pause(1000);
} else {
// Otherwise wait until the beacon is received.
await beaconCountIs(1);
}
const [ttfb] = await getBeacons();
return ttfb;
};
35 changes: 35 additions & 0 deletions test/utils/afterLoad.js
@@ -0,0 +1,35 @@
/*
* Copyright 2020 Google LLC
*
* 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
*
* https://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.
*/


/**
* Returns a promise that resolves once the browser window has loaded and
* all load callbacks have finished executing.
* @return {Promise<void>}
*/
function afterLoad() {
return browser.executeAsync((done) => {
if (document.readyState === 'complete') {
setTimeout(done, 0);
} else {
addEventListener('pageshow', done);
}
});
}

module.exports = {
afterLoad,
};