@mui/internal-bundle-size-checker 1.0.9-canary.33 → 1.0.9-canary.34

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/internal-bundle-size-checker",
3
- "version": "1.0.9-canary.33",
3
+ "version": "1.0.9-canary.34",
4
4
  "description": "Bundle size checker for MUI packages.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -38,7 +38,7 @@
38
38
  "@types/micromatch": "^4.0.9",
39
39
  "@types/yargs": "^17.0.33"
40
40
  },
41
- "gitSha": "cf68446433d3e1fcb7a2be55e7fdf866835c36b6",
41
+ "gitSha": "4c0f0d55b88cdb008a066a7de077b7a20def6245",
42
42
  "scripts": {
43
43
  "typescript": "tsc -p tsconfig.json",
44
44
  "test": "pnpm -w test --project @mui/internal-bundle-size-checker"
package/src/cli.js CHANGED
@@ -85,7 +85,7 @@ async function reportCommand(argv) {
85
85
  // Get current repo info and coerce with provided arguments
86
86
  const currentRepo = await getCurrentRepoInfo();
87
87
  const owner = argOwner ?? currentRepo.owner;
88
- const repo = argRepo ?? currentRepo.repo;
88
+ const repo = argRepo ?? currentRepo.name;
89
89
 
90
90
  if (typeof pr !== 'number') {
91
91
  throw new Error('Invalid pull request number. Please provide a valid --pr option.');
@@ -105,8 +105,18 @@ async function reportCommand(argv) {
105
105
  pull_number: pr,
106
106
  });
107
107
 
108
+ const getMergeBaseFromGithubApi = async (
109
+ /** @type {string} */ base,
110
+ /** @type {string} */ head,
111
+ ) => {
112
+ const { data } = await octokit.repos.compareCommits({ owner, repo, base, head });
113
+ return data.merge_base_commit.sha;
114
+ };
115
+
108
116
  // Generate and print the markdown report
109
- const report = await renderMarkdownReport(prInfo);
117
+ const report = await renderMarkdownReport(prInfo, undefined, {
118
+ getMergeBase: getMergeBaseFromGithubApi,
119
+ });
110
120
  // eslint-disable-next-line no-console
111
121
  console.log(report);
112
122
  }
package/src/git.js CHANGED
@@ -26,20 +26,25 @@ export async function getMergeBase(base, head) {
26
26
 
27
27
  /**
28
28
  * Gets the current repository owner and name from git remote
29
- * @returns {Promise<{owner: string | null, repo: string | null}>}
29
+ * @returns {Promise<string | null>}
30
30
  */
31
- export async function getCurrentRepoInfo() {
31
+ async function getRemoteUrl(remote = 'origin') {
32
32
  try {
33
- const { stdout } = await execa('git', ['remote', 'get-url', 'origin']);
34
- const parsed = gitUrlParse(stdout.trim());
35
- return {
36
- owner: parsed.owner,
37
- repo: parsed.name,
38
- };
39
- } catch (error) {
40
- return {
41
- owner: null,
42
- repo: null,
43
- };
33
+ const { stdout } = await execa('git', ['remote', 'get-url', remote]);
34
+ return stdout.trim();
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Gets the current repository owner and name from git remote
42
+ * @returns {Promise<{owner: string | null, name: string | null}>}
43
+ */
44
+ export async function getCurrentRepoInfo() {
45
+ const remoteUrl = (await getRemoteUrl('upstream')) || (await getRemoteUrl('origin'));
46
+ if (!remoteUrl) {
47
+ return { owner: null, name: null };
44
48
  }
49
+ return gitUrlParse(remoteUrl);
45
50
  }
@@ -7,8 +7,7 @@
7
7
  import { calculateSizeDiff } from './sizeDiff.js';
8
8
  import { fetchSnapshot } from './fetchSnapshot.js';
9
9
  import { displayPercentFormatter, byteSizeChangeFormatter } from './formatUtils.js';
10
- import { octokit } from './github.js';
11
- import { getCurrentRepoInfo, getMergeBase } from './git.js';
10
+ import { getMergeBase } from './git.js';
12
11
  import { fetchSnapshotWithFallback } from './fetchSnapshotWithFallback.js';
13
12
 
14
13
  /**
@@ -224,6 +223,7 @@ function getDetailsUrl(prInfo, options = {}) {
224
223
  * @param {string[]} [options.track] - Array of bundle IDs to track
225
224
  * @param {number} [options.fallbackDepth=3] - How many parent commits to try as fallback when base snapshot is missing
226
225
  * @param {number} [options.maxDetailsLines=100] - Maximum number of bundles to show in details section
226
+ * @param {(base: string, head: string) => Promise<string>} [options.getMergeBase] - Custom function to get merge base commit
227
227
  * @returns {Promise<string>} Markdown report
228
228
  */
229
229
  export async function renderMarkdownReport(prInfo, circleciBuildNumber, options = {}) {
@@ -233,22 +233,8 @@ export async function renderMarkdownReport(prInfo, circleciBuildNumber, options
233
233
  const repo = prInfo.base.repo.full_name;
234
234
  const { fallbackDepth = 3 } = options;
235
235
 
236
- const [owner, repoName] = repo.split('/');
237
-
238
- const currentRepo = await getCurrentRepoInfo();
239
-
240
- let baseCommit;
241
- if (owner === currentRepo.owner && repoName === currentRepo.repo) {
242
- baseCommit = await getMergeBase(prInfo.base.sha, prCommit);
243
- } else {
244
- const { data } = await octokit.repos.compareCommits({
245
- owner,
246
- repo: repoName,
247
- base: prInfo.base.sha,
248
- head: prCommit,
249
- });
250
- baseCommit = data.merge_base_commit.sha;
251
- }
236
+ const getMergeBaseFn = options.getMergeBase || getMergeBase;
237
+ const baseCommit = await getMergeBaseFn(prInfo.base.sha, prCommit);
252
238
 
253
239
  const [baseResult, prSnapshot] = await Promise.all([
254
240
  fetchSnapshotWithFallback(repo, baseCommit, fallbackDepth),
@@ -3,29 +3,21 @@ import { vi, describe, it, expect, beforeEach } from 'vitest';
3
3
  import { renderMarkdownReport } from './renderMarkdownReport.js';
4
4
  import * as fetchSnapshotModule from './fetchSnapshot.js';
5
5
  import * as fetchSnapshotWithFallbackModule from './fetchSnapshotWithFallback.js';
6
+ import * as gitModule from './git.js';
6
7
 
7
8
  // Mock the fetchSnapshot module
8
9
  vi.mock('./fetchSnapshot.js');
9
10
  // Mock the fetchSnapshotWithFallback module
10
11
  vi.mock('./fetchSnapshotWithFallback.js');
11
- // Mock the @octokit/rest module
12
- vi.mock('@octokit/rest', () => ({
13
- Octokit: vi.fn(() => ({
14
- repos: {
15
- compareCommits: vi.fn(),
16
- listCommits: vi.fn(),
17
- },
18
- pulls: {
19
- get: vi.fn(),
20
- },
21
- })),
22
- }));
12
+ // Mock the git module
13
+ vi.mock('./git.js');
23
14
 
24
15
  describe('renderMarkdownReport', () => {
25
16
  const mockFetchSnapshot = vi.mocked(fetchSnapshotModule.fetchSnapshot);
26
17
  const mockFetchSnapshotWithFallback = vi.mocked(
27
18
  fetchSnapshotWithFallbackModule.fetchSnapshotWithFallback,
28
19
  );
20
+ const mockGetMergeBase = vi.mocked(gitModule.getMergeBase);
29
21
 
30
22
  /** @type {PrInfo} */
31
23
  const mockPrInfo = {
@@ -41,26 +33,13 @@ describe('renderMarkdownReport', () => {
41
33
  },
42
34
  };
43
35
 
44
- beforeEach(async () => {
36
+ beforeEach(() => {
45
37
  mockFetchSnapshot.mockClear();
46
38
  mockFetchSnapshotWithFallback.mockClear();
39
+ mockGetMergeBase.mockClear();
47
40
 
48
- // Import and mock the octokit instance after mocking the module
49
- const { octokit } = await import('./github.js');
50
-
51
- // Set up default mock for compareCommits to return the base commit SHA
52
- vi.mocked(octokit.repos.compareCommits).mockResolvedValue(
53
- /** @type {any} */ ({
54
- data: {
55
- merge_base_commit: {
56
- sha: mockPrInfo.base.sha,
57
- },
58
- },
59
- }),
60
- );
61
-
62
- // Clear any previous mock calls
63
- vi.mocked(octokit.repos.compareCommits).mockClear();
41
+ // Set up default mock for getMergeBase
42
+ mockGetMergeBase.mockResolvedValue(mockPrInfo.base.sha);
64
43
  });
65
44
 
66
45
  it('should generate markdown report with size increases', async () => {
@@ -582,11 +561,83 @@ describe('renderMarkdownReport', () => {
582
561
  });
583
562
  mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
584
563
 
585
- const result = await renderMarkdownReport(mockPrInfo, undefined, { fallbackDepth: 1 });
564
+ const result = await renderMarkdownReport(mockPrInfo, undefined, {
565
+ fallbackDepth: 1,
566
+ });
586
567
 
587
568
  expect(result).toContain(
588
569
  'Using snapshot from parent commit parent1 (fallback from merge base abc123)',
589
570
  );
590
571
  expect(mockFetchSnapshotWithFallback).toHaveBeenCalledWith('mui/material-ui', 'abc123', 1);
591
572
  });
573
+
574
+ it('should throw error when default getMergeBase fails', async () => {
575
+ const prSnapshot = {
576
+ '@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
577
+ };
578
+
579
+ // Mock getMergeBase to fail (simulating no merge base found)
580
+ mockGetMergeBase.mockRejectedValue(new Error('fatal: Not a valid object name abc123'));
581
+ mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
582
+
583
+ await expect(renderMarkdownReport(mockPrInfo)).rejects.toThrow(
584
+ 'fatal: Not a valid object name abc123',
585
+ );
586
+
587
+ // Verify that getMergeBase was called with correct parameters
588
+ expect(mockGetMergeBase).toHaveBeenCalledWith('abc123', 'def456');
589
+ });
590
+
591
+ it('should use custom getMergeBase function when provided', async () => {
592
+ const baseSnapshot = {
593
+ '@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
594
+ };
595
+
596
+ const prSnapshot = {
597
+ '@mui/material/Button/index.js': { parsed: 15400, gzip: 4600 },
598
+ };
599
+
600
+ const customGetMergeBase = vi.fn().mockResolvedValue('custom123');
601
+
602
+ // Reset mocks to ensure clean state for this test
603
+ mockFetchSnapshotWithFallback.mockReset();
604
+ mockFetchSnapshot.mockReset();
605
+
606
+ mockFetchSnapshotWithFallback.mockResolvedValueOnce({
607
+ snapshot: baseSnapshot,
608
+ actualCommit: 'custom123',
609
+ });
610
+ mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
611
+
612
+ const result = await renderMarkdownReport(mockPrInfo, undefined, {
613
+ getMergeBase: customGetMergeBase,
614
+ });
615
+
616
+ // Verify that custom getMergeBase was called instead of default
617
+ expect(customGetMergeBase).toHaveBeenCalledWith('abc123', 'def456');
618
+ expect(mockGetMergeBase).not.toHaveBeenCalled();
619
+ expect(mockFetchSnapshotWithFallback).toHaveBeenCalledWith('mui/material-ui', 'custom123', 3);
620
+
621
+ expect(result).toContain('**Total Size Change:** 🔺+400B');
622
+ });
623
+
624
+ it('should throw error when custom getMergeBase fails', async () => {
625
+ const prSnapshot = {
626
+ '@mui/material/Button/index.js': { parsed: 15000, gzip: 4500 },
627
+ };
628
+
629
+ const customGetMergeBase = vi.fn().mockRejectedValue(new Error('Custom merge base error'));
630
+
631
+ mockFetchSnapshot.mockResolvedValueOnce(prSnapshot);
632
+
633
+ await expect(
634
+ renderMarkdownReport(mockPrInfo, undefined, {
635
+ getMergeBase: customGetMergeBase,
636
+ }),
637
+ ).rejects.toThrow('Custom merge base error');
638
+
639
+ // Verify that custom getMergeBase was called
640
+ expect(customGetMergeBase).toHaveBeenCalledWith('abc123', 'def456');
641
+ expect(mockGetMergeBase).not.toHaveBeenCalled();
642
+ });
592
643
  });