Skip to content

Commit

Permalink
Merge pull request #103 from Financial-Times/add-rum-tests
Browse files Browse the repository at this point in the history
Add unit tests for Real User Monitoring
  • Loading branch information
rowanmanning authored Sep 1, 2022
2 parents 7e0cffe + 76686f8 commit 22601b2
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`src/client/trackers/realUserMonitoringForPerformance .realUserMonitoringForPerformance() analyticsTracker(options) when all metrics are sent broadcasts an o-tracking event with the formatted metrics data 1`] = `
Object {
"action": "performance",
"category": "page",
"cumulativeLayoutShift": 13.7,
"domComplete": 123,
"domInteractive": 679,
"firstContentfulPaint": 14,
"firstInputDelay": 14,
"firstPaint": 14,
"largestContentfulPaint": 14,
"timeToFirstByte": 14,
"totalBlockingTime": 14,
"url": "http://localhost/",
}
`;
149 changes: 149 additions & 0 deletions src/client/trackers/__test__/realUserMonitoring.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@

// Mock the ready-state module
jest.mock('ready-state', () => ({
complete: {
// We want ready-state to complete immediately
then: (fn) => fn()
}
}));

// Mock the utility to check whether the seed is in the sample
jest.mock('../../utils/seedIsInSample', () => ({
seedIsInSample: jest.fn().mockReturnValue(true)
}));
import {seedIsInSample} from '../../utils/seedIsInSample';

// Mock the utility to get a spoor ID from the cookie
jest.mock('../../utils/getSpoorId', () => ({
getSpoorId: jest.fn().mockReturnValue('mock-spoor-id')
}));

// Mock the broadcast method which fires an o-tracking event
jest.mock('../../broadcast', () => ({
broadcast: jest.fn()
}));
import {broadcast} from '../../broadcast';

// Mock Perfume
jest.mock('perfume.js', () => {
return jest.fn();
});
import Perfume from 'perfume.js';

// Mock global performance metrics
Performance.prototype.getEntriesByType = jest.fn().mockReturnValue([
{
type: 'navigate',
domComplete: 123.45,
domInteractive: 678.90
}
]);

// Mock requestIdleCallback so we can capture metrics
// sent by Perfume
window.requestIdleCallback = jest.fn();

import {realUserMonitoringForPerformance} from '../realUserMonitoringForPerformance';

describe('src/client/trackers/realUserMonitoringForPerformance', () => {

describe('.realUserMonitoringForPerformance()', () => {

beforeEach(() => {
realUserMonitoringForPerformance();
});

it('creates a Perfume instance with a custom analytics tracker', () => {
expect(Perfume).toHaveBeenCalledTimes(1);
const perfumeOptions = Perfume.mock.calls[0][0];
expect(typeof perfumeOptions).toBe('object');
expect(typeof perfumeOptions.analyticsTracker).toBe('function');
});

describe('analyticsTracker(options)', () => {
let analyticsTracker;
let oldConsole;

beforeEach(() => {
// We mock the console here so that our library's console.logs don't
// make it hard to read the test output
oldConsole = global.console;
global.console = {log: jest.fn()};
analyticsTracker = Perfume.mock.calls[0][0].analyticsTracker;
});

afterEach(() => {
global.console = oldConsole;
});

describe('when only one metric type is sent', () => {
beforeEach(() => {
analyticsTracker({ metricName: 'fid', data: 13.7 });
});

it('does not broadcast an o-tracking event', () => {
expect(broadcast).toHaveBeenCalledTimes(0);
});
});

describe('when all metrics are sent', () => {
beforeEach(() => {
analyticsTracker({ metricName: 'fid', data: 13.7 });
analyticsTracker({ metricName: 'lcp', data: 13.7 });
analyticsTracker({ metricName: 'ttfb', data: 13.7 });
analyticsTracker({ metricName: 'fp', data: 13.7 });
analyticsTracker({ metricName: 'fcp', data: 13.7 });
analyticsTracker({ metricName: 'cls', data: 13.7 });
analyticsTracker({ metricName: 'tbt', data: 13.7 });
});

it('broadcasts an o-tracking event with the formatted metrics data', () => {
expect(broadcast).toHaveBeenCalledTimes(1);
const broadcastArguments = broadcast.mock.calls[0];
expect(broadcastArguments[0]).toBe('oTracking.event');
expect(broadcastArguments[1]).toMatchSnapshot();
});

describe('when any one of the metrics are sent a second time', () => {
beforeEach(() => {
analyticsTracker({ metricName: 'fid', data: 13.7 });
});

it('does not broadcast a second o-tracking event', () => {
expect(broadcast).toHaveBeenCalledTimes(1);
});
});
});

});

describe('when the seed is not in the sample', () => {

beforeEach(() => {
Perfume.mockReset();
seedIsInSample.mockReturnValue(false);
realUserMonitoringForPerformance();
});

it('does not create a Perfume instance', () => {
expect(Perfume).toHaveBeenCalledTimes(0);
});

});

describe('when no "navigation" performance entries are available', () => {

beforeEach(() => {
Perfume.mockReset();
Performance.prototype.getEntriesByType.mockReturnValue([]);
realUserMonitoringForPerformance();
});

it('does not create a Perfume instance', () => {
expect(Perfume).toHaveBeenCalledTimes(0);
});

});

});
});

0 comments on commit 22601b2

Please sign in to comment.