Improve isolation of PerformanceReporter tests to increase their stability (#27275)

* Improve isolation of PerformanceReporter tests to increase their stability

* Change how PerformanceReporter.sendBeacon is defined
This commit is contained in:
Harrison Healey 2024-06-11 17:05:29 -04:00 committed by GitHub
parent 1d704745b7
commit dfdb6e9ece
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 14 deletions

View File

@ -17,9 +17,6 @@ import {markAndReport, measureAndReport} from '.';
jest.mock('web-vitals');
const sendBeacon = jest.fn().mockReturnValue(true);
navigator.sendBeacon = sendBeacon;
const siteUrl = 'http://localhost:8065';
describe('PerformanceReporter', () => {
@ -29,7 +26,7 @@ describe('PerformanceReporter', () => {
});
test('should report measurements to the server as histograms', async () => {
const {reporter} = newTestReporter();
const {reporter, sendBeacon} = newTestReporter();
reporter.observe();
expect(sendBeacon).not.toHaveBeenCalled();
@ -77,7 +74,7 @@ describe('PerformanceReporter', () => {
});
test('should report some marks to the server as counters', async () => {
const {reporter} = newTestReporter();
const {reporter, sendBeacon} = newTestReporter();
reporter.observe();
expect(sendBeacon).not.toHaveBeenCalled();
@ -121,7 +118,7 @@ describe('PerformanceReporter', () => {
});
test('should report longtasks to the server as counters', async () => {
const {reporter} = newTestReporter();
const {reporter, sendBeacon} = newTestReporter();
reporter.observe();
expect(sendBeacon).not.toHaveBeenCalled();
@ -166,7 +163,7 @@ describe('PerformanceReporter', () => {
});
test('should report web vitals to the server as histograms', async () => {
const {reporter} = newTestReporter();
const {reporter, sendBeacon} = newTestReporter();
reporter.observe();
expect(sendBeacon).not.toHaveBeenCalled();
@ -229,7 +226,7 @@ describe('PerformanceReporter', () => {
});
test('should not report anything there is no data to report', async () => {
const {reporter} = newTestReporter();
const {reporter, sendBeacon} = newTestReporter();
reporter.observe();
expect(sendBeacon).not.toHaveBeenCalled();
@ -247,7 +244,7 @@ describe('PerformanceReporter', () => {
});
test('should not report anything if EnableClientMetrics is false', async () => {
const {reporter} = newTestReporter(false);
const {reporter, sendBeacon} = newTestReporter(false);
reporter.observe();
expect(sendBeacon).not.toHaveBeenCalled();
@ -267,7 +264,7 @@ describe('PerformanceReporter', () => {
});
test('should not report anything if the user is not logged in', async () => {
const {reporter} = newTestReporter(true, false);
const {reporter, sendBeacon} = newTestReporter(true, false);
reporter.observe();
expect(sendBeacon).not.toHaveBeenCalled();
@ -290,7 +287,7 @@ describe('PerformanceReporter', () => {
setPlatform('MacIntel');
setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:124.0) Gecko/20100101 Firefox/124.0');
const {reporter} = newTestReporter();
const {reporter, sendBeacon} = newTestReporter();
reporter.observe();
markAndReport('reportedA');
@ -317,7 +314,11 @@ describe('PerformanceReporter', () => {
});
test('should fall back to making a fetch request if a beacon cannot be sent', async () => {
const {client, reporter} = newTestReporter();
const {
client,
reporter,
sendBeacon,
} = newTestReporter();
reporter.observe();
sendBeacon.mockReturnValue(false);
@ -344,6 +345,7 @@ describe('PerformanceReporter', () => {
});
class TestPerformanceReporter extends PerformanceReporter {
public sendBeacon: jest.Mock = jest.fn(() => true);
public reportPeriodBase = 10;
public reportPeriodJitter = 0;
@ -371,7 +373,11 @@ function newTestReporter(telemetryEnabled = true, loggedIn = true) {
},
}));
return {client, reporter};
return {
client,
reporter,
sendBeacon: reporter.sendBeacon,
};
}
function waitForReport() {

View File

@ -67,6 +67,7 @@ export default class PerformanceReporter {
private observer: PerformanceObserver;
private reportTimeout: number | undefined;
// These values are protected instead of private so that they can be modified by unit tests
protected reportPeriodBase = 60 * 1000;
protected reportPeriodJitter = 15 * 1000;
@ -298,13 +299,17 @@ export default class PerformanceReporter {
const url = this.client.getClientMetricsRoute();
const data = JSON.stringify(report);
const beaconSent = navigator.sendBeacon(url, data);
const beaconSent = this.sendBeacon(url, data);
if (!beaconSent) {
// The data couldn't be queued as a beacon for some reason, so fall back to sending an immediate fetch
fetch(url, {method: 'POST', body: data});
}
}
protected sendBeacon(url: string | URL, data?: BodyInit | null | undefined): boolean {
return navigator.sendBeacon(url, data);
}
}
function isPerformanceLongTask(entry: PerformanceEntry): entry is PerformanceLongTaskTiming {