@mui/internal-bundle-size-checker 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/src/cli.js +10 -272
- package/src/fetchSnapshot.js +58 -0
- package/src/index.js +2 -9
- package/src/renderMarkdownReport.js +72 -74
- package/src/renderMarkdownReport.test.js +559 -0
- package/src/types.d.ts +1 -58
- package/src/viteBuilder.js +229 -0
- package/src/webpackBuilder.js +267 -0
- package/src/worker.js +51 -283
- package/vite.config.mts +5 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { renderMarkdownReport } from './renderMarkdownReport.js';
|
|
3
|
+
import * as fetchSnapshotModule from './fetchSnapshot.js';
|
|
4
|
+
|
|
5
|
+
// Mock the fetchSnapshot module
|
|
6
|
+
vi.mock('./fetchSnapshot.js');
|
|
7
|
+
|
|
8
|
+
describe('renderMarkdownReport', () => {
|
|
9
|
+
const mockFetchSnapshot = vi.mocked(fetchSnapshotModule.fetchSnapshot);
|
|
10
|
+
const mockFetchSnapshotWithFallback = vi.mocked(fetchSnapshotModule.fetchSnapshotWithFallback);
|
|
11
|
+
|
|
12
|
+
/** @type {PrInfo} */
|
|
13
|
+
const mockPrInfo = {
|
|
14
|
+
number: 42,
|
|
15
|
+
base: {
|
|
16
|
+
ref: 'master',
|
|
17
|
+
sha: 'abc123',
|
|
18
|
+
repo: { full_name: 'mui/material-ui' },
|
|
19
|
+
},
|
|
20
|
+
head: {
|
|
21
|
+
ref: 'feature-branch',
|
|
22
|
+
sha: 'def456',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
mockFetchSnapshot.mockClear();
|
|
28
|
+
mockFetchSnapshotWithFallback.mockClear();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should generate markdown report with size increases', async () => {
|
|
32
|
+
const baseSnapshot = {
|
|
33
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
34
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const prSnapshot = {
|
|
38
|
+
'@mui/material/Button/index.js': { parsed: 15400, gzip: 4600 }, // +400/+100
|
|
39
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 }, // no change
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
43
|
+
snapshot: baseSnapshot,
|
|
44
|
+
actualCommit: 'abc123',
|
|
45
|
+
});
|
|
46
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
47
|
+
|
|
48
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
49
|
+
|
|
50
|
+
expect(result).toMatchInlineSnapshot(`
|
|
51
|
+
"**Total Size Change:** 🔺+400B<sup>(+1.08%)</sup> - **Total Gzip Change:** 🔺+100B<sup>(+0.91%)</sup>
|
|
52
|
+
Files: 2 total (0 added, 0 removed, 1 changed)
|
|
53
|
+
|
|
54
|
+
<details>
|
|
55
|
+
<summary>Show details for 2 more bundles</summary>
|
|
56
|
+
|
|
57
|
+
**@mui/material/Button/index.js** **parsed:** 🔺+400B<sup>(+2.67%)</sup> **gzip:** 🔺+100B<sup>(+2.22%)</sup>
|
|
58
|
+
**@mui/material/TextField/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
59
|
+
|
|
60
|
+
</details>
|
|
61
|
+
|
|
62
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
63
|
+
`);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should handle new files added in PR', async () => {
|
|
67
|
+
const baseSnapshot = {
|
|
68
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const prSnapshot = {
|
|
72
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
73
|
+
'@mui/material/Chip/index.js': { parsed: 3500, gzip: 1200 }, // new file
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
77
|
+
snapshot: baseSnapshot,
|
|
78
|
+
actualCommit: 'abc123',
|
|
79
|
+
});
|
|
80
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
81
|
+
|
|
82
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
83
|
+
|
|
84
|
+
expect(result).toMatchInlineSnapshot(`
|
|
85
|
+
"**Total Size Change:** 🔺+3.5KB<sup>(+23.33%)</sup> - **Total Gzip Change:** 🔺+1.2KB<sup>(+26.67%)</sup>
|
|
86
|
+
Files: 2 total (1 added, 0 removed, 0 changed)
|
|
87
|
+
|
|
88
|
+
<details>
|
|
89
|
+
<summary>Show details for 2 more bundles</summary>
|
|
90
|
+
|
|
91
|
+
**@mui/material/Chip/index.js** **parsed:** 🔺+3.5KB<sup>(new)</sup> **gzip:** 🔺+1.2KB<sup>(new)</sup>
|
|
92
|
+
**@mui/material/Button/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
93
|
+
|
|
94
|
+
</details>
|
|
95
|
+
|
|
96
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
97
|
+
`);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should handle missing base snapshot when GitHub API also fails', async () => {
|
|
101
|
+
const prSnapshot = {
|
|
102
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({ snapshot: null, actualCommit: null });
|
|
106
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
107
|
+
|
|
108
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
109
|
+
|
|
110
|
+
expect(result).toContain(
|
|
111
|
+
'No bundle size snapshot found for base commit abc123 or any of its 3 parent commits.',
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should handle size decreases', async () => {
|
|
116
|
+
const baseSnapshot = {
|
|
117
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const prSnapshot = {
|
|
121
|
+
'@mui/material/Button/index.js': { parsed: 14500, gzip: 4300 }, // -500/-200
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
125
|
+
snapshot: baseSnapshot,
|
|
126
|
+
actualCommit: 'abc123',
|
|
127
|
+
});
|
|
128
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
129
|
+
|
|
130
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
131
|
+
|
|
132
|
+
expect(result).toMatchInlineSnapshot(`
|
|
133
|
+
"**Total Size Change:** ▼-500B<sup>(-3.33%)</sup> - **Total Gzip Change:** ▼-200B<sup>(-4.44%)</sup>
|
|
134
|
+
Files: 1 total (0 added, 0 removed, 1 changed)
|
|
135
|
+
|
|
136
|
+
<details>
|
|
137
|
+
<summary>Show details for 1 more bundle</summary>
|
|
138
|
+
|
|
139
|
+
**@mui/material/Button/index.js** **parsed:** ▼-500B<sup>(-3.33%)</sup> **gzip:** ▼-200B<sup>(-4.44%)</sup>
|
|
140
|
+
|
|
141
|
+
</details>
|
|
142
|
+
|
|
143
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
144
|
+
`);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should handle removed files', async () => {
|
|
148
|
+
const baseSnapshot = {
|
|
149
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
150
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 },
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const prSnapshot = {
|
|
154
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
155
|
+
// TextField removed
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
159
|
+
snapshot: baseSnapshot,
|
|
160
|
+
actualCommit: 'abc123',
|
|
161
|
+
});
|
|
162
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
163
|
+
|
|
164
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
165
|
+
|
|
166
|
+
expect(result).toMatchInlineSnapshot(`
|
|
167
|
+
"**Total Size Change:** ▼-22KB<sup>(-59.46%)</sup> - **Total Gzip Change:** ▼-6.5KB<sup>(-59.09%)</sup>
|
|
168
|
+
Files: 2 total (0 added, 1 removed, 0 changed)
|
|
169
|
+
|
|
170
|
+
<details>
|
|
171
|
+
<summary>Show details for 2 more bundles</summary>
|
|
172
|
+
|
|
173
|
+
**@mui/material/TextField/index.js** **parsed:** ▼-22KB<sup>(removed)</sup> **gzip:** ▼-6.5KB<sup>(removed)</sup>
|
|
174
|
+
**@mui/material/Button/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
175
|
+
|
|
176
|
+
</details>
|
|
177
|
+
|
|
178
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
179
|
+
`);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should show collapsible section for many small changes', async () => {
|
|
183
|
+
/** @type {import('./sizeDiff.js').SizeSnapshot} */
|
|
184
|
+
const baseSnapshot = {};
|
|
185
|
+
/** @type {import('./sizeDiff.js').SizeSnapshot} */
|
|
186
|
+
const prSnapshot = {};
|
|
187
|
+
|
|
188
|
+
// Create many small changes (under threshold)
|
|
189
|
+
for (let i = 1; i <= 15; i += 1) {
|
|
190
|
+
const filename = `@mui/icons-material/Icon${i}.js`;
|
|
191
|
+
baseSnapshot[filename] = { parsed: 1000, gzip: 300 };
|
|
192
|
+
prSnapshot[filename] = { parsed: 1050, gzip: 310 }; // +50/+10 (under threshold)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Add one significant change
|
|
196
|
+
baseSnapshot['@mui/material/Button/index.js'] = { parsed: 15000, gzip: 4500 };
|
|
197
|
+
prSnapshot['@mui/material/Button/index.js'] = { parsed: 15400, gzip: 4600 }; // +400/+100 (over threshold)
|
|
198
|
+
|
|
199
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
200
|
+
snapshot: baseSnapshot,
|
|
201
|
+
actualCommit: 'abc123',
|
|
202
|
+
});
|
|
203
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
204
|
+
|
|
205
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
206
|
+
|
|
207
|
+
expect(result).toMatchInlineSnapshot(`
|
|
208
|
+
"**Total Size Change:** 🔺+1.15KB<sup>(+3.83%)</sup> - **Total Gzip Change:** 🔺+250B<sup>(+2.78%)</sup>
|
|
209
|
+
Files: 16 total (0 added, 0 removed, 16 changed)
|
|
210
|
+
|
|
211
|
+
<details>
|
|
212
|
+
<summary>Show details for 16 more bundles</summary>
|
|
213
|
+
|
|
214
|
+
**@mui/material/Button/index.js** **parsed:** 🔺+400B<sup>(+2.67%)</sup> **gzip:** 🔺+100B<sup>(+2.22%)</sup>
|
|
215
|
+
**@mui/icons-material/Icon1.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
216
|
+
**@mui/icons-material/Icon10.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
217
|
+
**@mui/icons-material/Icon11.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
218
|
+
**@mui/icons-material/Icon12.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
219
|
+
**@mui/icons-material/Icon13.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
220
|
+
**@mui/icons-material/Icon14.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
221
|
+
**@mui/icons-material/Icon15.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
222
|
+
**@mui/icons-material/Icon2.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
223
|
+
**@mui/icons-material/Icon3.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
224
|
+
**@mui/icons-material/Icon4.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
225
|
+
**@mui/icons-material/Icon5.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
226
|
+
**@mui/icons-material/Icon6.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
227
|
+
**@mui/icons-material/Icon7.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
228
|
+
**@mui/icons-material/Icon8.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
229
|
+
**@mui/icons-material/Icon9.js** **parsed:** 🔺+50B<sup>(+5.00%)</sup> **gzip:** 🔺+10B<sup>(+3.33%)</sup>
|
|
230
|
+
|
|
231
|
+
</details>
|
|
232
|
+
|
|
233
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
234
|
+
`);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('should include CircleCI build number in details URL', async () => {
|
|
238
|
+
const baseSnapshot = {
|
|
239
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const prSnapshot = {
|
|
243
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
247
|
+
snapshot: baseSnapshot,
|
|
248
|
+
actualCommit: 'abc123',
|
|
249
|
+
});
|
|
250
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
251
|
+
|
|
252
|
+
const result = await renderMarkdownReport(mockPrInfo, '12345');
|
|
253
|
+
|
|
254
|
+
expect(result).toContain('circleCIBuildNumber=12345');
|
|
255
|
+
expect(result).toMatchInlineSnapshot(`
|
|
256
|
+
"**Total Size Change:** 0B<sup>(0.00%)</sup> - **Total Gzip Change:** 0B<sup>(0.00%)</sup>
|
|
257
|
+
Files: 1 total (0 added, 0 removed, 0 changed)
|
|
258
|
+
|
|
259
|
+
<details>
|
|
260
|
+
<summary>Show details for 1 more bundle</summary>
|
|
261
|
+
|
|
262
|
+
**@mui/material/Button/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
263
|
+
|
|
264
|
+
</details>
|
|
265
|
+
|
|
266
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456&circleCIBuildNumber=12345)"
|
|
267
|
+
`);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should handle no changes', async () => {
|
|
271
|
+
const baseSnapshot = {
|
|
272
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const prSnapshot = {
|
|
276
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
280
|
+
snapshot: baseSnapshot,
|
|
281
|
+
actualCommit: 'abc123',
|
|
282
|
+
});
|
|
283
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
284
|
+
|
|
285
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
286
|
+
|
|
287
|
+
expect(result).toMatchInlineSnapshot(`
|
|
288
|
+
"**Total Size Change:** 0B<sup>(0.00%)</sup> - **Total Gzip Change:** 0B<sup>(0.00%)</sup>
|
|
289
|
+
Files: 1 total (0 added, 0 removed, 0 changed)
|
|
290
|
+
|
|
291
|
+
<details>
|
|
292
|
+
<summary>Show details for 1 more bundle</summary>
|
|
293
|
+
|
|
294
|
+
**@mui/material/Button/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
295
|
+
|
|
296
|
+
</details>
|
|
297
|
+
|
|
298
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
299
|
+
`);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('should handle track option with tracked bundles shown prominently', async () => {
|
|
303
|
+
const baseSnapshot = {
|
|
304
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
305
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 },
|
|
306
|
+
'@mui/icons-material/Add.js': { parsed: 1000, gzip: 300 },
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
const prSnapshot = {
|
|
310
|
+
'@mui/material/Button/index.js': { parsed: 15400, gzip: 4600 }, // +400/+100
|
|
311
|
+
'@mui/material/TextField/index.js': { parsed: 22200, gzip: 6600 }, // +200/+100
|
|
312
|
+
'@mui/icons-material/Add.js': { parsed: 1100, gzip: 350 }, // +100/+50
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
316
|
+
snapshot: baseSnapshot,
|
|
317
|
+
actualCommit: 'abc123',
|
|
318
|
+
});
|
|
319
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
320
|
+
|
|
321
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
322
|
+
track: ['@mui/material/Button/index.js', '@mui/material/TextField/index.js'],
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
expect(result).toMatchInlineSnapshot(`
|
|
326
|
+
"**@mui/material/Button/index.js** **parsed:** 🔺+400B<sup>(+2.67%)</sup> **gzip:** 🔺+100B<sup>(+2.22%)</sup>
|
|
327
|
+
**@mui/material/TextField/index.js** **parsed:** 🔺+200B<sup>(+0.91%)</sup> **gzip:** 🔺+100B<sup>(+1.54%)</sup><details>
|
|
328
|
+
<summary>Show details for 1 more bundle</summary>
|
|
329
|
+
|
|
330
|
+
**@mui/icons-material/Add.js** **parsed:** 🔺+100B<sup>(+10.00%)</sup> **gzip:** 🔺+50B<sup>(+16.67%)</sup>
|
|
331
|
+
|
|
332
|
+
</details>
|
|
333
|
+
|
|
334
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
335
|
+
`);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should calculate totals only for tracked bundles', async () => {
|
|
339
|
+
const baseSnapshot = {
|
|
340
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
341
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 },
|
|
342
|
+
'@mui/icons-material/Add.js': { parsed: 1000, gzip: 300 },
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const prSnapshot = {
|
|
346
|
+
'@mui/material/Button/index.js': { parsed: 15500, gzip: 4650 }, // +500/+150
|
|
347
|
+
'@mui/material/TextField/index.js': { parsed: 22300, gzip: 6650 }, // +300/+150
|
|
348
|
+
'@mui/icons-material/Add.js': { parsed: 2000, gzip: 600 }, // +1000/+300 (not tracked)
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
352
|
+
snapshot: baseSnapshot,
|
|
353
|
+
actualCommit: 'abc123',
|
|
354
|
+
});
|
|
355
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
356
|
+
|
|
357
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
358
|
+
track: ['@mui/material/Button/index.js', '@mui/material/TextField/index.js'],
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
expect(result).toMatchInlineSnapshot(`
|
|
362
|
+
"**@mui/material/Button/index.js** **parsed:** 🔺+500B<sup>(+3.33%)</sup> **gzip:** 🔺+150B<sup>(+3.33%)</sup>
|
|
363
|
+
**@mui/material/TextField/index.js** **parsed:** 🔺+300B<sup>(+1.36%)</sup> **gzip:** 🔺+150B<sup>(+2.31%)</sup><details>
|
|
364
|
+
<summary>Show details for 1 more bundle</summary>
|
|
365
|
+
|
|
366
|
+
**@mui/icons-material/Add.js** **parsed:** 🔺+1KB<sup>(+100.00%)</sup> **gzip:** 🔺+300B<sup>(+100.00%)</sup>
|
|
367
|
+
|
|
368
|
+
</details>
|
|
369
|
+
|
|
370
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
371
|
+
`);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('should put non-tracked bundles in details when track is specified', async () => {
|
|
375
|
+
const baseSnapshot = {
|
|
376
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
377
|
+
'@mui/icons-material/Add.js': { parsed: 1000, gzip: 300 },
|
|
378
|
+
'@mui/icons-material/Delete.js': { parsed: 1200, gzip: 350 },
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
const prSnapshot = {
|
|
382
|
+
'@mui/material/Button/index.js': { parsed: 15400, gzip: 4600 }, // +400/+100 (tracked)
|
|
383
|
+
'@mui/icons-material/Add.js': { parsed: 1100, gzip: 350 }, // +100/+50 (not tracked)
|
|
384
|
+
'@mui/icons-material/Delete.js': { parsed: 1300, gzip: 400 }, // +100/+50 (not tracked)
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
388
|
+
snapshot: baseSnapshot,
|
|
389
|
+
actualCommit: 'abc123',
|
|
390
|
+
});
|
|
391
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
392
|
+
|
|
393
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
394
|
+
track: ['@mui/material/Button/index.js'],
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
expect(result).toMatchInlineSnapshot(`
|
|
398
|
+
"**@mui/material/Button/index.js** **parsed:** 🔺+400B<sup>(+2.67%)</sup> **gzip:** 🔺+100B<sup>(+2.22%)</sup><details>
|
|
399
|
+
<summary>Show details for 2 more bundles</summary>
|
|
400
|
+
|
|
401
|
+
**@mui/icons-material/Add.js** **parsed:** 🔺+100B<sup>(+10.00%)</sup> **gzip:** 🔺+50B<sup>(+16.67%)</sup>
|
|
402
|
+
**@mui/icons-material/Delete.js** **parsed:** 🔺+100B<sup>(+8.33%)</sup> **gzip:** 🔺+50B<sup>(+14.29%)</sup>
|
|
403
|
+
|
|
404
|
+
</details>
|
|
405
|
+
|
|
406
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
407
|
+
`);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('should show tracked bundles prominently even when they have no changes', async () => {
|
|
411
|
+
const baseSnapshot = {
|
|
412
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
413
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 },
|
|
414
|
+
'@mui/material/Icon/index.js': { parsed: 8000, gzip: 2500 },
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const prSnapshot = {
|
|
418
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 }, // tracked, no change
|
|
419
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 }, // tracked, no change
|
|
420
|
+
'@mui/material/Icon/index.js': { parsed: 8100, gzip: 2550 }, // untracked, has change
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
424
|
+
snapshot: baseSnapshot,
|
|
425
|
+
actualCommit: 'abc123',
|
|
426
|
+
});
|
|
427
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
428
|
+
|
|
429
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
430
|
+
track: ['@mui/material/Button/index.js', '@mui/material/TextField/index.js'],
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
expect(result).toMatchInlineSnapshot(`
|
|
434
|
+
"**@mui/material/Button/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
435
|
+
**@mui/material/TextField/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup><details>
|
|
436
|
+
<summary>Show details for 1 more bundle</summary>
|
|
437
|
+
|
|
438
|
+
**@mui/material/Icon/index.js** **parsed:** 🔺+100B<sup>(+1.25%)</sup> **gzip:** 🔺+50B<sup>(+2.00%)</sup>
|
|
439
|
+
|
|
440
|
+
</details>
|
|
441
|
+
|
|
442
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
443
|
+
`);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
it('should show message when tracking is enabled but no untracked bundles have changes', async () => {
|
|
447
|
+
const baseSnapshot = {
|
|
448
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
449
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 },
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
const prSnapshot = {
|
|
453
|
+
'@mui/material/Button/index.js': { parsed: 15400, gzip: 4600 }, // tracked, has change
|
|
454
|
+
'@mui/material/TextField/index.js': { parsed: 22000, gzip: 6500 }, // untracked, no change
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
458
|
+
snapshot: baseSnapshot,
|
|
459
|
+
actualCommit: 'abc123',
|
|
460
|
+
});
|
|
461
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
462
|
+
|
|
463
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, {
|
|
464
|
+
track: ['@mui/material/Button/index.js'],
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
expect(result).toMatchInlineSnapshot(`
|
|
468
|
+
"**@mui/material/Button/index.js** **parsed:** 🔺+400B<sup>(+2.67%)</sup> **gzip:** 🔺+100B<sup>(+2.22%)</sup><details>
|
|
469
|
+
<summary>Show details for 1 more bundle</summary>
|
|
470
|
+
|
|
471
|
+
**@mui/material/TextField/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
472
|
+
|
|
473
|
+
</details>
|
|
474
|
+
|
|
475
|
+
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
476
|
+
`);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('should throw error when tracked bundle is missing from head snapshot', async () => {
|
|
480
|
+
const baseSnapshot = {
|
|
481
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const prSnapshot = {
|
|
485
|
+
'@mui/material/Button/index.js': { parsed: 15400, gzip: 4600 },
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
489
|
+
snapshot: baseSnapshot,
|
|
490
|
+
actualCommit: 'abc123',
|
|
491
|
+
});
|
|
492
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
493
|
+
|
|
494
|
+
await expect(
|
|
495
|
+
renderMarkdownReport(mockPrInfo, undefined, {
|
|
496
|
+
track: ['@mui/material/Button/index.js', '@mui/material/NonExistent/index.js'],
|
|
497
|
+
}),
|
|
498
|
+
).rejects.toThrow(
|
|
499
|
+
'Tracked bundle not found in head snapshot: @mui/material/NonExistent/index.js',
|
|
500
|
+
);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
it('should fallback to parent commit when base snapshot is missing', async () => {
|
|
504
|
+
const parentSnapshot = {
|
|
505
|
+
'@mui/material/Button/index.js': { parsed: 14500, gzip: 4300 },
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
const prSnapshot = {
|
|
509
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
513
|
+
snapshot: parentSnapshot,
|
|
514
|
+
actualCommit: 'parent1',
|
|
515
|
+
});
|
|
516
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
517
|
+
|
|
518
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
519
|
+
|
|
520
|
+
expect(result).toContain('Using snapshot from parent commit parent1 (fallback from abc123)');
|
|
521
|
+
expect(result).toContain('baseCommit=parent1');
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
it('should show no snapshot message when fallback fails', async () => {
|
|
525
|
+
const prSnapshot = {
|
|
526
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({ snapshot: null, actualCommit: null });
|
|
530
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
531
|
+
|
|
532
|
+
const result = await renderMarkdownReport(mockPrInfo);
|
|
533
|
+
|
|
534
|
+
expect(result).toContain(
|
|
535
|
+
'No bundle size snapshot found for base commit abc123 or any of its 3 parent commits.',
|
|
536
|
+
);
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
it('should respect custom fallbackDepth option', async () => {
|
|
540
|
+
const parentSnapshot = {
|
|
541
|
+
'@mui/material/Button/index.js': { parsed: 14500, gzip: 4300 },
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
const prSnapshot = {
|
|
545
|
+
'@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
mockFetchSnapshotWithFallback.mockResolvedValueOnce({
|
|
549
|
+
snapshot: parentSnapshot,
|
|
550
|
+
actualCommit: 'parent1',
|
|
551
|
+
});
|
|
552
|
+
mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
|
|
553
|
+
|
|
554
|
+
const result = await renderMarkdownReport(mockPrInfo, undefined, { fallbackDepth: 1 });
|
|
555
|
+
|
|
556
|
+
expect(result).toContain('Using snapshot from parent commit parent1 (fallback from abc123)');
|
|
557
|
+
expect(mockFetchSnapshotWithFallback).toHaveBeenCalledWith('mui/material-ui', 'abc123', 1);
|
|
558
|
+
});
|
|
559
|
+
});
|
package/src/types.d.ts
CHANGED
|
@@ -18,15 +18,6 @@ interface StatsChunkGroup {
|
|
|
18
18
|
assets: Array<{ name: string; size: number }>;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
interface WebpackStats {
|
|
22
|
-
hasErrors(): boolean;
|
|
23
|
-
toJson(options: any): {
|
|
24
|
-
assets?: StatsAsset[];
|
|
25
|
-
entrypoints?: Record<string, StatsChunkGroup>;
|
|
26
|
-
errors?: any[];
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
21
|
// Upload configuration with optional properties
|
|
31
22
|
interface UploadConfig {
|
|
32
23
|
repo?: string; // The repository name (e.g., "mui/material-ui")
|
|
@@ -79,6 +70,7 @@ interface CommandLineArgs {
|
|
|
79
70
|
verbose?: boolean;
|
|
80
71
|
filter?: string[];
|
|
81
72
|
concurrency?: number;
|
|
73
|
+
vite?: boolean;
|
|
82
74
|
}
|
|
83
75
|
|
|
84
76
|
// Diff command argument types
|
|
@@ -110,52 +102,3 @@ interface PrInfo {
|
|
|
110
102
|
sha: string;
|
|
111
103
|
};
|
|
112
104
|
}
|
|
113
|
-
|
|
114
|
-
// Check the PR message for available colors: https://github.com/mui/mui-public/pull/332
|
|
115
|
-
type KatexColor =
|
|
116
|
-
| 'blueviolet'
|
|
117
|
-
| 'aquamarine'
|
|
118
|
-
| 'brown'
|
|
119
|
-
| 'cadetblue'
|
|
120
|
-
| 'darkorchid'
|
|
121
|
-
| 'chocolate'
|
|
122
|
-
| 'cornflowerblue'
|
|
123
|
-
| 'cyan'
|
|
124
|
-
| 'darkgray'
|
|
125
|
-
| 'darkslateblue'
|
|
126
|
-
| 'forestgreen'
|
|
127
|
-
| 'fuchsia'
|
|
128
|
-
| 'gold'
|
|
129
|
-
| 'goldenrod'
|
|
130
|
-
| 'gray'
|
|
131
|
-
| 'green'
|
|
132
|
-
| 'greenyellow'
|
|
133
|
-
| 'lavender'
|
|
134
|
-
| 'lightgray'
|
|
135
|
-
| 'limegreen'
|
|
136
|
-
| 'magenta'
|
|
137
|
-
| 'maroon'
|
|
138
|
-
| 'mediumpurple'
|
|
139
|
-
| 'midnightblue'
|
|
140
|
-
| 'navajowhite'
|
|
141
|
-
| 'olive'
|
|
142
|
-
| 'orange'
|
|
143
|
-
| 'orangered'
|
|
144
|
-
| 'orchid'
|
|
145
|
-
| 'pink'
|
|
146
|
-
| 'plum'
|
|
147
|
-
| 'purple'
|
|
148
|
-
| 'red'
|
|
149
|
-
| 'royalblue'
|
|
150
|
-
| 'salmon'
|
|
151
|
-
| 'seagreen'
|
|
152
|
-
| 'silver'
|
|
153
|
-
| 'skyblue'
|
|
154
|
-
| 'springgreen'
|
|
155
|
-
| 'tan'
|
|
156
|
-
| 'thistle'
|
|
157
|
-
| 'tomato'
|
|
158
|
-
| 'turquoise'
|
|
159
|
-
| 'violet'
|
|
160
|
-
| 'yellow'
|
|
161
|
-
| 'yellowgreen';
|