mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Remove legacy tests for Performance API (#52465)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52465 Changelog: [internal] Now that we have enough coverage for the Performance API in Fantom, Jest tests where most of the API is mocked are redundant and useless, so this removes them (and the mock). Reviewed By: huntie Differential Revision: D77860888 fbshipit-source-id: 7dbd1a8a43b056a3b34e4e37d578be9ccb521824
This commit is contained in:
committed by
Facebook GitHub Bot
parent
9f8179afa7
commit
a3933e6878
-292
@@ -1,292 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @react-native/monorepo/sort-imports
|
||||
import type Performance from '../Performance';
|
||||
|
||||
import {performanceEntryTypeToRaw} from '../internals/RawPerformanceEntry';
|
||||
import {reportEntry} from '../specs/__mocks__/NativePerformanceMock';
|
||||
|
||||
jest.mock('../specs/NativePerformance', () =>
|
||||
require('../specs/__mocks__/NativePerformanceMock'),
|
||||
);
|
||||
|
||||
declare var performance: Performance;
|
||||
|
||||
const NativePerformanceMock =
|
||||
require('../specs/__mocks__/NativePerformanceMock').default;
|
||||
|
||||
describe('Performance', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
||||
const PerformanceClass = require('../Performance').default;
|
||||
// $FlowExpectedError[cannot-write]
|
||||
global.performance = new PerformanceClass();
|
||||
});
|
||||
|
||||
it('reports marks and measures', () => {
|
||||
NativePerformanceMock.setCurrentTime(25);
|
||||
|
||||
performance.mark('mark-now');
|
||||
performance.mark('mark-in-the-past', {
|
||||
startTime: 10,
|
||||
});
|
||||
performance.mark('mark-in-the-future', {
|
||||
startTime: 50,
|
||||
});
|
||||
performance.measure('measure-with-specific-time', {
|
||||
start: 30,
|
||||
duration: 4,
|
||||
});
|
||||
performance.measure('measure-now-with-start-mark', 'mark-in-the-past');
|
||||
performance.measure(
|
||||
'measure-with-start-and-end-mark',
|
||||
'mark-in-the-past',
|
||||
'mark-in-the-future',
|
||||
);
|
||||
|
||||
const entries = performance.getEntries();
|
||||
expect(entries.length).toBe(6);
|
||||
expect(entries.map(entry => entry.toJSON())).toEqual([
|
||||
{
|
||||
duration: 0,
|
||||
entryType: 'mark',
|
||||
name: 'mark-in-the-past',
|
||||
startTime: 10,
|
||||
},
|
||||
{
|
||||
duration: 15,
|
||||
entryType: 'measure',
|
||||
name: 'measure-now-with-start-mark',
|
||||
startTime: 10,
|
||||
},
|
||||
{
|
||||
duration: 40,
|
||||
entryType: 'measure',
|
||||
name: 'measure-with-start-and-end-mark',
|
||||
startTime: 10,
|
||||
},
|
||||
{
|
||||
duration: 0,
|
||||
entryType: 'mark',
|
||||
name: 'mark-now',
|
||||
startTime: 25,
|
||||
},
|
||||
{
|
||||
duration: 4,
|
||||
entryType: 'measure',
|
||||
name: 'measure-with-specific-time',
|
||||
startTime: 30,
|
||||
},
|
||||
{
|
||||
duration: 0,
|
||||
entryType: 'mark',
|
||||
name: 'mark-in-the-future',
|
||||
startTime: 50,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('clearMarks and clearMeasures remove correct entry types', async () => {
|
||||
performance.mark('entry1', {startTime: 0});
|
||||
performance.mark('mark2', {startTime: 0});
|
||||
|
||||
performance.measure('entry1', {start: 0, duration: 0});
|
||||
performance.measure('measure2', {start: 0, duration: 0});
|
||||
|
||||
performance.clearMarks();
|
||||
|
||||
expect(performance.getEntries().map(e => e.name)).toStrictEqual([
|
||||
'entry1',
|
||||
'measure2',
|
||||
]);
|
||||
|
||||
performance.mark('entry2', {startTime: 0});
|
||||
performance.mark('mark3', {startTime: 0});
|
||||
|
||||
performance.clearMeasures();
|
||||
|
||||
expect(performance.getEntries().map(e => e.name)).toStrictEqual([
|
||||
'entry2',
|
||||
'mark3',
|
||||
]);
|
||||
|
||||
performance.clearMarks();
|
||||
|
||||
expect(performance.getEntries().map(e => e.name)).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('getEntries only works with allowed entry types', async () => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
performance.mark('entry1', {startTime: 0});
|
||||
performance.mark('mark2', {startTime: 0});
|
||||
|
||||
jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
performance.getEntriesByType('mark');
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
|
||||
performance.getEntriesByType('measure');
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
|
||||
performance.getEntriesByName('entry1');
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
|
||||
performance.getEntriesByName('entry1', 'event');
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
|
||||
performance.getEntriesByName('entry1', 'mark');
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
|
||||
performance.getEntriesByType('event');
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('getEntries works with marks and measures', async () => {
|
||||
performance.clearMarks();
|
||||
performance.clearMeasures();
|
||||
|
||||
performance.mark('entry1', {startTime: 0});
|
||||
performance.mark('mark2', {startTime: 0});
|
||||
|
||||
performance.measure('entry1', {start: 0, duration: 0});
|
||||
performance.measure('measure2', {start: 0, duration: 0});
|
||||
|
||||
expect(performance.getEntries().map(e => e.name)).toStrictEqual([
|
||||
'entry1',
|
||||
'mark2',
|
||||
'entry1',
|
||||
'measure2',
|
||||
]);
|
||||
|
||||
expect(performance.getEntriesByType('mark').map(e => e.name)).toStrictEqual(
|
||||
['entry1', 'mark2'],
|
||||
);
|
||||
|
||||
expect(
|
||||
performance.getEntriesByType('measure').map(e => e.name),
|
||||
).toStrictEqual(['entry1', 'measure2']);
|
||||
|
||||
expect(
|
||||
performance.getEntriesByName('entry1').map(e => e.entryType),
|
||||
).toStrictEqual(['mark', 'measure']);
|
||||
|
||||
expect(
|
||||
performance.getEntriesByName('entry1', 'measure').map(e => e.entryType),
|
||||
).toStrictEqual(['measure']);
|
||||
});
|
||||
|
||||
it('defines EventCounts for Performance', () => {
|
||||
expect(performance.eventCounts).not.toBeUndefined();
|
||||
});
|
||||
|
||||
it('consistently implements the API for EventCounts', async () => {
|
||||
let interactionId = 0;
|
||||
const eventDefaultValues = {
|
||||
entryType: performanceEntryTypeToRaw('event'),
|
||||
startTime: 0, // startTime
|
||||
duration: 100, // duration
|
||||
processingStart: 0, // processing start
|
||||
processingEnd: 100, // processingEnd
|
||||
};
|
||||
|
||||
reportEntry({
|
||||
name: 'click',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
reportEntry({
|
||||
name: 'input',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
reportEntry({
|
||||
name: 'input',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
reportEntry({
|
||||
name: 'keyup',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
reportEntry({
|
||||
name: 'keyup',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
reportEntry({
|
||||
name: 'keyup',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
|
||||
const eventCounts = performance.eventCounts;
|
||||
expect(eventCounts.size).toBe(3);
|
||||
expect(Array.from(eventCounts.entries())).toStrictEqual([
|
||||
['click', 1],
|
||||
['input', 2],
|
||||
['keyup', 3],
|
||||
]);
|
||||
|
||||
expect(eventCounts.get('click')).toEqual(1);
|
||||
expect(eventCounts.get('input')).toEqual(2);
|
||||
expect(eventCounts.get('keyup')).toEqual(3);
|
||||
|
||||
expect(eventCounts.has('click')).toEqual(true);
|
||||
expect(eventCounts.has('input')).toEqual(true);
|
||||
expect(eventCounts.has('keyup')).toEqual(true);
|
||||
|
||||
expect(Array.from(eventCounts.keys())).toStrictEqual([
|
||||
'click',
|
||||
'input',
|
||||
'keyup',
|
||||
]);
|
||||
expect(Array.from(eventCounts.values())).toStrictEqual([1, 2, 3]);
|
||||
|
||||
await jest.runAllTicks();
|
||||
reportEntry({
|
||||
name: 'input',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
reportEntry({
|
||||
name: 'keyup',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
reportEntry({
|
||||
name: 'keyup',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
expect(Array.from(eventCounts.values())).toStrictEqual([1, 3, 5]);
|
||||
|
||||
await jest.runAllTicks();
|
||||
reportEntry({
|
||||
name: 'click',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
|
||||
await jest.runAllTicks();
|
||||
|
||||
reportEntry({
|
||||
name: 'keyup',
|
||||
...eventDefaultValues,
|
||||
interactionId: interactionId++,
|
||||
});
|
||||
|
||||
expect(Array.from(eventCounts.values())).toStrictEqual([2, 3, 6]);
|
||||
});
|
||||
});
|
||||
Vendored
-58
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type Performance from '../Performance';
|
||||
import type {PerformanceEntryList} from '../PerformanceEntry';
|
||||
|
||||
jest.mock(
|
||||
'../specs/NativePerformance',
|
||||
() => require('../specs/__mocks__/NativePerformanceMock').default,
|
||||
);
|
||||
|
||||
declare var performance: Performance;
|
||||
|
||||
describe('PerformanceObserver', () => {
|
||||
let PerformanceObserver;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
||||
// $FlowExpectedError[cannot-write]
|
||||
global.performance = new (require('../Performance').default)();
|
||||
PerformanceObserver = require('../PerformanceObserver').PerformanceObserver;
|
||||
});
|
||||
|
||||
it('prevents durationThreshold to be used together with entryTypes', async () => {
|
||||
const observer = new PerformanceObserver((list, _observer) => {});
|
||||
|
||||
expect(() =>
|
||||
observer.observe({entryTypes: ['event', 'mark'], durationThreshold: 100}),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
it('ignores durationThreshold when used with marks or measures', async () => {
|
||||
let entries: PerformanceEntryList = [];
|
||||
|
||||
const observer = new PerformanceObserver((list, _observer) => {
|
||||
entries = [...entries, ...list.getEntries()];
|
||||
});
|
||||
|
||||
observer.observe({type: 'measure', durationThreshold: 100});
|
||||
|
||||
performance.measure('measure1', {
|
||||
start: 0,
|
||||
duration: 10,
|
||||
});
|
||||
|
||||
await jest.runAllTicks();
|
||||
expect(entries).toHaveLength(1);
|
||||
expect(entries.map(e => e.name)).toStrictEqual(['measure1']);
|
||||
});
|
||||
});
|
||||
Vendored
-269
@@ -1,269 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {
|
||||
NativeBatchedObserverCallback,
|
||||
NativeMemoryInfo,
|
||||
NativePerformanceMarkResult,
|
||||
NativePerformanceMeasureResult,
|
||||
OpaqueNativeObserverHandle,
|
||||
PerformanceObserverInit,
|
||||
RawPerformanceEntry,
|
||||
RawPerformanceEntryType,
|
||||
ReactNativeStartupTiming,
|
||||
} from '../NativePerformance';
|
||||
import typeof NativePerformance from '../NativePerformance';
|
||||
|
||||
import {RawPerformanceEntryTypeValues} from '../../internals/RawPerformanceEntry';
|
||||
|
||||
type MockObserver = {
|
||||
handleEntry: (entry: RawPerformanceEntry) => void,
|
||||
callback: NativeBatchedObserverCallback,
|
||||
didScheduleFlushBuffer: boolean,
|
||||
entries: Array<RawPerformanceEntry>,
|
||||
options: PerformanceObserverInit,
|
||||
droppedEntriesCount: number,
|
||||
};
|
||||
|
||||
const eventCounts: Map<string, number> = new Map();
|
||||
const observers: Set<MockObserver> = new Set();
|
||||
const marks: Map<string, number> = new Map();
|
||||
let entries: Array<RawPerformanceEntry> = [];
|
||||
|
||||
function getMockObserver(
|
||||
opaqueNativeObserverHandle: OpaqueNativeObserverHandle,
|
||||
): MockObserver {
|
||||
return opaqueNativeObserverHandle as $FlowFixMe as MockObserver;
|
||||
}
|
||||
|
||||
function createMockObserver(callback: NativeBatchedObserverCallback) {
|
||||
const observer: MockObserver = {
|
||||
callback,
|
||||
didScheduleFlushBuffer: false,
|
||||
entries: [],
|
||||
options: {},
|
||||
droppedEntriesCount: 0,
|
||||
handleEntry: (entry: RawPerformanceEntry) => {
|
||||
if (
|
||||
observer.options.type !== entry.entryType &&
|
||||
!observer.options.entryTypes?.includes(entry.entryType)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
entry.entryType === RawPerformanceEntryTypeValues.EVENT &&
|
||||
entry.duration < (observer.options?.durationThreshold ?? 0)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
observer.entries.push(entry);
|
||||
|
||||
if (!observer.didScheduleFlushBuffer) {
|
||||
observer.didScheduleFlushBuffer = true;
|
||||
// $FlowFixMe[incompatible-call]
|
||||
global.queueMicrotask(() => {
|
||||
observer.didScheduleFlushBuffer = false;
|
||||
// We want to emulate the way it's done in native (i.e. async/batched)
|
||||
observer.callback();
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return observer;
|
||||
}
|
||||
|
||||
export function reportEntry(entry: RawPerformanceEntry) {
|
||||
entries.push(entry);
|
||||
|
||||
switch (entry.entryType) {
|
||||
case RawPerformanceEntryTypeValues.MARK:
|
||||
marks.set(entry.name, entry.startTime);
|
||||
break;
|
||||
case RawPerformanceEntryTypeValues.MEASURE:
|
||||
break;
|
||||
case RawPerformanceEntryTypeValues.EVENT:
|
||||
eventCounts.set(entry.name, (eventCounts.get(entry.name) ?? 0) + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
for (const observer of observers) {
|
||||
observer.handleEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
let currentTime: number = 12;
|
||||
|
||||
const NativePerformanceMock = {
|
||||
setCurrentTime: (time: number): void => {
|
||||
currentTime = time;
|
||||
},
|
||||
|
||||
now: (): number => currentTime,
|
||||
|
||||
markWithResult: (
|
||||
name: string,
|
||||
startTime?: number,
|
||||
): NativePerformanceMarkResult => {
|
||||
const computedStartTime = startTime ?? performance.now();
|
||||
|
||||
marks.set(name, computedStartTime);
|
||||
reportEntry({
|
||||
entryType: RawPerformanceEntryTypeValues.MARK,
|
||||
name,
|
||||
startTime: computedStartTime,
|
||||
duration: 0,
|
||||
});
|
||||
|
||||
return computedStartTime;
|
||||
},
|
||||
|
||||
measure: (
|
||||
name: string,
|
||||
startTime?: number,
|
||||
endTime?: number,
|
||||
duration?: number,
|
||||
startMark?: string,
|
||||
endMark?: string,
|
||||
): NativePerformanceMeasureResult => {
|
||||
const start = startMark != null ? marks.get(startMark) : startTime ?? 0;
|
||||
const end =
|
||||
endMark != null ? marks.get(endMark) : endTime ?? performance.now();
|
||||
|
||||
if (start === undefined) {
|
||||
throw new Error('startMark does not exist');
|
||||
}
|
||||
|
||||
if (end === undefined) {
|
||||
throw new Error('endMark does not exist');
|
||||
}
|
||||
|
||||
const computedDuration = duration ?? end - start;
|
||||
reportEntry({
|
||||
entryType: RawPerformanceEntryTypeValues.MEASURE,
|
||||
name,
|
||||
startTime: start,
|
||||
duration: computedDuration,
|
||||
});
|
||||
|
||||
return [start, computedDuration];
|
||||
},
|
||||
|
||||
getSimpleMemoryInfo: (): NativeMemoryInfo => {
|
||||
return {};
|
||||
},
|
||||
|
||||
getReactNativeStartupTiming: (): ReactNativeStartupTiming => {
|
||||
return {
|
||||
startTime: 0,
|
||||
endTime: 0,
|
||||
executeJavaScriptBundleEntryPointStart: 0,
|
||||
executeJavaScriptBundleEntryPointEnd: 0,
|
||||
initializeRuntimeStart: 0,
|
||||
initializeRuntimeEnd: 0,
|
||||
};
|
||||
},
|
||||
|
||||
getEventCounts: (): $ReadOnlyArray<[string, number]> => {
|
||||
return Array.from(eventCounts.entries());
|
||||
},
|
||||
|
||||
createObserver: (
|
||||
callback: NativeBatchedObserverCallback,
|
||||
): OpaqueNativeObserverHandle => {
|
||||
// $FlowExpectedError[incompatible-return]
|
||||
return createMockObserver(callback);
|
||||
},
|
||||
|
||||
getDroppedEntriesCount: (observer: OpaqueNativeObserverHandle): number => {
|
||||
return getMockObserver(observer).droppedEntriesCount;
|
||||
},
|
||||
|
||||
observe: (
|
||||
observer: OpaqueNativeObserverHandle,
|
||||
options: PerformanceObserverInit,
|
||||
): void => {
|
||||
const mockObserver = getMockObserver(observer);
|
||||
mockObserver.options = options;
|
||||
observers.add(mockObserver);
|
||||
},
|
||||
|
||||
disconnect: (observer: OpaqueNativeObserverHandle): void => {
|
||||
const mockObserver = getMockObserver(observer);
|
||||
observers.delete(mockObserver);
|
||||
},
|
||||
|
||||
takeRecords: (
|
||||
observer: OpaqueNativeObserverHandle,
|
||||
): $ReadOnlyArray<RawPerformanceEntry> => {
|
||||
const mockObserver = getMockObserver(observer);
|
||||
const observerEntries = mockObserver.entries;
|
||||
mockObserver.entries = [];
|
||||
return observerEntries.sort((a, b) => a.startTime - b.startTime);
|
||||
},
|
||||
|
||||
clearMarks: (entryName?: string) => {
|
||||
if (entryName != null) {
|
||||
marks.delete(entryName);
|
||||
} else {
|
||||
marks.clear();
|
||||
}
|
||||
|
||||
entries = entries.filter(
|
||||
entry =>
|
||||
entry.entryType !== RawPerformanceEntryTypeValues.MARK ||
|
||||
(entryName != null && entry.name !== entryName),
|
||||
);
|
||||
},
|
||||
|
||||
clearMeasures: (entryName?: string) => {
|
||||
entries = entries.filter(
|
||||
entry =>
|
||||
entry.entryType !== RawPerformanceEntryTypeValues.MEASURE ||
|
||||
(entryName != null && entry.name !== entryName),
|
||||
);
|
||||
},
|
||||
|
||||
getEntries: (): $ReadOnlyArray<RawPerformanceEntry> => {
|
||||
return [...entries].sort((a, b) => a.startTime - b.startTime);
|
||||
},
|
||||
|
||||
getEntriesByName: (
|
||||
entryName: string,
|
||||
entryType?: ?RawPerformanceEntryType,
|
||||
): $ReadOnlyArray<RawPerformanceEntry> => {
|
||||
return NativePerformanceMock.getEntries().filter(
|
||||
entry =>
|
||||
(entryType == null || entry.entryType === entryType) &&
|
||||
entry.name === entryName,
|
||||
);
|
||||
},
|
||||
|
||||
getEntriesByType: (
|
||||
entryType: RawPerformanceEntryType,
|
||||
): $ReadOnlyArray<RawPerformanceEntry> => {
|
||||
return entries.filter(entry => entry.entryType === entryType);
|
||||
},
|
||||
|
||||
getSupportedPerformanceEntryTypes:
|
||||
(): $ReadOnlyArray<RawPerformanceEntryType> => {
|
||||
return [
|
||||
RawPerformanceEntryTypeValues.MARK,
|
||||
RawPerformanceEntryTypeValues.MEASURE,
|
||||
RawPerformanceEntryTypeValues.EVENT,
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
(NativePerformanceMock: NativePerformance);
|
||||
|
||||
export default NativePerformanceMock;
|
||||
Reference in New Issue
Block a user