Skip to content

Commit bcce235

Browse files
rubennortefacebook-github-bot
authored andcommitted
Add basic tests for Event Timing API (facebook#50289)
Summary: Pull Request resolved: facebook#50289 Changelog: [internal] Adding basic Fantom tests for the new Event Timing API. Reviewed By: huntie Differential Revision: D71734778 fbshipit-source-id: b5da3162fade64eadede72346af50df68b4facd9
1 parent 499eef1 commit bcce235

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
* @format
9+
* @oncall react_native
10+
* @fantom_flags enableReportEventPaintTime:true
11+
*/
12+
13+
import 'react-native/Libraries/Core/InitializeCore';
14+
15+
import type {PerformanceObserverEntryList} from 'react-native/src/private/webapis/performance/PerformanceObserver';
16+
17+
import * as Fantom from '@react-native/fantom';
18+
import nullthrows from 'nullthrows';
19+
import {useState} from 'react';
20+
import {Text, View} from 'react-native';
21+
import setUpPerformanceObserver from 'react-native/src/private/setup/setUpPerformanceObserver';
22+
import {PerformanceEventTiming} from 'react-native/src/private/webapis/performance/EventTiming';
23+
import {PerformanceObserver} from 'react-native/src/private/webapis/performance/PerformanceObserver';
24+
25+
setUpPerformanceObserver();
26+
27+
function sleep(ms: number) {
28+
const end = performance.now() + ms;
29+
while (performance.now() < end) {}
30+
}
31+
32+
function ensurePerformanceEventTiming(value: mixed): PerformanceEventTiming {
33+
if (!(value instanceof PerformanceEventTiming)) {
34+
throw new Error(
35+
`Expected instance of PerformanceEventTiming but got ${String(value)}`,
36+
);
37+
}
38+
39+
return value;
40+
}
41+
42+
describe('Event Timing API', () => {
43+
it('reports events without event handlers or updates', () => {
44+
const callback = jest.fn();
45+
46+
const observer = new PerformanceObserver(callback);
47+
observer.observe({entryTypes: ['event']});
48+
49+
const root = Fantom.createRoot();
50+
Fantom.runTask(() => {
51+
root.render(<View />);
52+
});
53+
54+
const element = nullthrows(root.document.documentElement.firstElementChild);
55+
56+
expect(callback).not.toHaveBeenCalled();
57+
58+
Fantom.dispatchNativeEvent(element, 'click');
59+
60+
expect(callback).toHaveBeenCalledTimes(1);
61+
62+
const entryList = callback.mock.lastCall[0] as PerformanceObserverEntryList;
63+
const entries = entryList.getEntries();
64+
65+
expect(entries.length).toBe(1);
66+
67+
const entry = ensurePerformanceEventTiming(entries[0]);
68+
69+
expect(entry.entryType).toBe('event');
70+
expect(entry.name).toBe('click');
71+
72+
expect(entry.startTime).toBeGreaterThanOrEqual(0);
73+
expect(entry.processingStart).toBeGreaterThan(entry.startTime);
74+
expect(entry.processingEnd).toBeGreaterThanOrEqual(entry.processingStart);
75+
76+
expect(entry.duration).toBeGreaterThanOrEqual(0);
77+
expect(entry.duration).toBeGreaterThan(
78+
entry.processingEnd - entry.startTime,
79+
);
80+
81+
expect(entry.interactionId).toBeGreaterThanOrEqual(0);
82+
});
83+
84+
it('reports events with handlers but no updates', () => {
85+
const callback = jest.fn();
86+
87+
const observer = new PerformanceObserver(callback);
88+
observer.observe({entryTypes: ['event']});
89+
90+
const SIMULATED_PROCESSING_DELAY = 50;
91+
92+
const root = Fantom.createRoot();
93+
Fantom.runTask(() => {
94+
root.render(
95+
<View
96+
onClick={event => {
97+
sleep(SIMULATED_PROCESSING_DELAY);
98+
}}
99+
/>,
100+
);
101+
});
102+
103+
const element = nullthrows(root.document.documentElement.firstElementChild);
104+
105+
expect(callback).not.toHaveBeenCalled();
106+
107+
Fantom.dispatchNativeEvent(element, 'click');
108+
109+
expect(callback).toHaveBeenCalledTimes(1);
110+
111+
const entryList = callback.mock.lastCall[0] as PerformanceObserverEntryList;
112+
const entries = entryList.getEntries();
113+
114+
expect(entries.length).toBe(1);
115+
116+
const entry = ensurePerformanceEventTiming(entries[0]);
117+
118+
expect(entry.entryType).toBe('event');
119+
expect(entry.name).toBe('click');
120+
121+
expect(entry.startTime).toBeGreaterThanOrEqual(0);
122+
expect(entry.processingStart).toBeGreaterThan(entry.startTime);
123+
expect(entry.processingEnd).toBeGreaterThanOrEqual(entry.processingStart);
124+
125+
expect(entry.processingEnd - entry.processingStart).toBeGreaterThanOrEqual(
126+
SIMULATED_PROCESSING_DELAY,
127+
);
128+
129+
expect(entry.duration).toBeGreaterThanOrEqual(0);
130+
expect(entry.duration).toBeGreaterThan(
131+
entry.processingEnd - entry.startTime,
132+
);
133+
134+
expect(entry.interactionId).toBeGreaterThanOrEqual(0);
135+
});
136+
137+
it('reports events with updates', () => {
138+
const callback = jest.fn();
139+
140+
const observer = new PerformanceObserver(callback);
141+
observer.observe({entryTypes: ['event']});
142+
143+
function MyComponent() {
144+
const [count, setCount] = useState(0);
145+
146+
return (
147+
<View
148+
onClick={event => {
149+
setCount(count + 1);
150+
}}>
151+
<Text>{count}</Text>
152+
</View>
153+
);
154+
}
155+
156+
const root = Fantom.createRoot();
157+
Fantom.runTask(() => {
158+
root.render(<MyComponent />);
159+
});
160+
161+
const element = nullthrows(root.document.documentElement.firstElementChild);
162+
163+
expect(callback).not.toHaveBeenCalled();
164+
165+
Fantom.dispatchNativeEvent(element, 'click');
166+
167+
expect(callback).toHaveBeenCalledTimes(1);
168+
169+
const entryList = callback.mock.lastCall[0] as PerformanceObserverEntryList;
170+
const entries = entryList.getEntries();
171+
172+
expect(entries.length).toBe(1);
173+
174+
const entry = ensurePerformanceEventTiming(entries[0]);
175+
176+
expect(entry.entryType).toBe('event');
177+
expect(entry.name).toBe('click');
178+
179+
expect(entry.startTime).toBeGreaterThanOrEqual(0);
180+
expect(entry.processingStart).toBeGreaterThan(entry.startTime);
181+
expect(entry.processingEnd).toBeGreaterThanOrEqual(entry.processingStart);
182+
183+
expect(entry.duration).toBeGreaterThanOrEqual(0);
184+
expect(entry.duration).toBeGreaterThan(
185+
entry.processingEnd - entry.startTime,
186+
);
187+
188+
// TODO: When Fantom provides structured data from mounting manager, add timestamp to operations and verify that the duration includes that.
189+
190+
expect(entry.interactionId).toBeGreaterThanOrEqual(0);
191+
});
192+
});

0 commit comments

Comments
 (0)