forked from paularmstrong/react-component-benchmark
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjest.test.tsx
More file actions
135 lines (109 loc) · 3.69 KB
/
jest.test.tsx
File metadata and controls
135 lines (109 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import * as React from 'react';
import { Benchmark } from '../../src';
import type { BenchmarkType, BenchmarkRef, BenchResultsType } from '../../src';
import { act, render, waitFor } from '@testing-library/react';
// This is slow on purpose for demonstration purposes
function slowFibonacci(num: number): number {
if (num < 2) {
return num;
}
return slowFibonacci(num - 1) + slowFibonacci(num - 2);
}
interface Props {
component: React.ComponentType;
props?: Record<string, unknown>;
samples?: number;
type?: BenchmarkType;
}
/**
* A wrapper function to make benchmarking in tests a bit more reusable.
* You might tune this to your specific needs
* @param {React.Component} options.component The component you'd like to benchmark
* @param {Object} options.props Props for your component
* @param {Number} options.samples Number of samples to take. default 50 is a safe number
* @param {String} options.type Lifecycle of a component ('mount', 'update', or 'unmount')
* @return {Object} Results object
*/
async function runBenchmark({ component, props, samples = 50, type = 'mount' }: Props) {
// Benchmarking requires a real time system and not mocks. Ensure you're not using fake timers
jest.useRealTimers();
const ref = React.createRef<BenchmarkRef>();
let results: BenchResultsType;
const handleComplete = jest.fn((res) => {
results = res;
});
render(
<Benchmark
component={component}
onComplete={handleComplete}
ref={ref}
samples={samples}
componentProps={props}
type={type}
/>
);
act(() => {
ref.current?.start();
});
await waitFor(() => expect(handleComplete).toHaveBeenCalled(), { timeout: 10000 });
// @ts-ignore
return results;
}
describe('Benchmark', () => {
test('mounts slowly', async () => {
function SlowMount() {
// Running a slow calculation on mount
const fib = slowFibonacci(32);
return <div>{JSON.stringify(fib)}</div>;
}
const results = await runBenchmark({ component: SlowMount });
expect(results.mean).toBeGreaterThan(10);
});
test('mounts in a reasonable amount of time', async () => {
// Run the slow calculation somewhere else ahead of time
const fib = slowFibonacci(32);
function FastMount() {
return <div>{JSON.stringify(fib)}</div>;
}
const results = await runBenchmark({ component: FastMount });
expect(results.mean).toBeLessThan(4);
});
test('updates slowly', async () => {
function SlowUpdate() {
// Run a slow calculation on every render
const fib = slowFibonacci(32);
return <div>{JSON.stringify(fib)}</div>;
}
const results = await runBenchmark({ component: SlowUpdate, type: 'update' });
expect(results.mean).toBeGreaterThan(10);
});
test('updates in a reasonable amount of time', async () => {
function FastUpdates() {
// Memoize the slow calculation - slow mount, but fast updates
const fib = React.useMemo(() => slowFibonacci(32), []);
return <div>{JSON.stringify(fib)}</div>;
}
const results = await runBenchmark({ component: FastUpdates, type: 'update' });
expect(results.mean).toBeLessThan(4);
});
test('unmounts slowly', async () => {
function SlowUnmount() {
React.useEffect(() => {
// return function from useEffect runs on teardown
return () => {
slowFibonacci(32);
};
}, []);
return <div />;
}
const results = await runBenchmark({ component: SlowUnmount, type: 'unmount' });
expect(results.mean).toBeGreaterThan(10);
});
test('unmounts in a reasonable amount of time', async () => {
function FastUnmount() {
return <div />;
}
const results = await runBenchmark({ component: FastUnmount, type: 'unmount' });
expect(results.mean).toBeLessThan(4);
});
});