diff --git a/Libraries/WebPerformance/__mocks__/NativePerformance.js b/Libraries/WebPerformance/__mocks__/NativePerformance.js new file mode 100644 index 00000000000..6b11a27a20a --- /dev/null +++ b/Libraries/WebPerformance/__mocks__/NativePerformance.js @@ -0,0 +1,65 @@ +/** + * 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 { + NativeMemoryInfo, + ReactNativeStartupTiming, + Spec as NativePerformance, +} from '../NativePerformance'; + +import NativePerformanceObserver from '../NativePerformanceObserver'; +import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; + +const marks: Map = new Map(); + +const NativePerformanceMock: NativePerformance = { + mark: (name: string, startTime: number, duration: number): void => { + NativePerformanceObserver?.logRawEntry({ + name, + entryType: RawPerformanceEntryTypeValues.MARK, + startTime, + duration, + }); + marks.set(name, startTime); + }, + + measure: ( + name: string, + startTime: number, + endTime: number, + duration?: number, + startMark?: string, + endMark?: string, + ): void => { + const start = startMark != null ? marks.get(startMark) ?? 0 : startTime; + const end = endMark != null ? marks.get(endMark) ?? 0 : endTime; + NativePerformanceObserver?.logRawEntry({ + name, + entryType: RawPerformanceEntryTypeValues.MEASURE, + startTime: start, + duration: duration ?? (end ? end - start : 0), + }); + }, + + getSimpleMemoryInfo: (): NativeMemoryInfo => { + return {}; + }, + + getReactNativeStartupTiming: (): ReactNativeStartupTiming => { + return { + startTime: 0, + endTime: 0, + executeJavaScriptBundleEntryPointStart: 0, + executeJavaScriptBundleEntryPointEnd: 0, + }; + }, +}; + +export default NativePerformanceMock; diff --git a/Libraries/WebPerformance/__tests__/NativePerformanceMock-test.js b/Libraries/WebPerformance/__tests__/NativePerformanceMock-test.js new file mode 100644 index 00000000000..679dad39dfc --- /dev/null +++ b/Libraries/WebPerformance/__tests__/NativePerformanceMock-test.js @@ -0,0 +1,82 @@ +/** + * 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. + * + * @format + * @oncall react_native + */ + +const NativePerformanceMock = require('../__mocks__/NativePerformance').default; +const PerformanceObserver = require('../PerformanceObserver').default; + +describe('NativePerformanceMock', () => { + jest.mock( + '../NativePerformanceObserver', + () => require('../__mocks__/NativePerformanceObserver').default, + ); + + it('marks get reported', async () => { + let entries = []; + const observer = new PerformanceObserver((list, _observer) => { + entries = [...entries, ...list.getEntries()]; + }); + + observer.observe({type: 'mark'}); + + NativePerformanceMock.mark('mark1', 0, 10); + NativePerformanceMock.mark('mark2', 5, 10); + NativePerformanceMock.mark('mark3', 10, 20); + + await jest.runAllTicks(); + expect(entries).toHaveLength(3); + expect(entries.map(e => e.name)).toStrictEqual(['mark1', 'mark2', 'mark3']); + expect(entries.map(e => e.startTime)).toStrictEqual([0, 5, 10]); + }); + + it('measures get reported', async () => { + let entries = []; + const observer = new PerformanceObserver((list, _observer) => { + entries = [...entries, ...list.getEntries()]; + }); + + observer.observe({entryTypes: ['measure']}); + + NativePerformanceMock.mark('mark0', 0.0, 1.0); + NativePerformanceMock.mark('mark1', 1.0, 3.0); + NativePerformanceMock.mark('mark2', 2.0, 4.0); + + NativePerformanceMock.measure('measure0', 0, 2); + NativePerformanceMock.measure('measure1', 0, 2, 4); + NativePerformanceMock.measure( + 'measure2', + 0, + 0, + undefined, + 'mark1', + 'mark2', + ); + NativePerformanceMock.measure('measure3', 0, 0, 5, 'mark1'); + NativePerformanceMock.measure( + 'measure4', + 1.5, + 0, + undefined, + undefined, + 'mark2', + ); + + await jest.runAllTicks(); + expect(entries).toHaveLength(5); + expect(entries.map(e => e.name)).toStrictEqual([ + 'measure0', + 'measure1', + 'measure2', + 'measure3', + 'measure4', + ]); + expect(entries.map(e => e.startTime)).toStrictEqual([0, 0, 1, 1, 1.5]); + expect(entries.map(e => e.duration)).toStrictEqual([2, 4, 1, 5, 0.5]); + }); +});