Skip to content

Commit a46ebbe

Browse files
chore: move update pr script to actual script with tests (#1684)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent e33b702 commit a46ebbe

15 files changed

+1260
-92
lines changed

.github/workflows/quality.yml

+13-89
Original file line numberDiff line numberDiff line change
@@ -221,97 +221,21 @@ jobs:
221221
name: playwright-artifacts
222222
path: playwright-artifacts
223223

224+
- name: Fetch gh-pages branch
225+
run: |
226+
git fetch origin gh-pages:gh-pages
227+
mkdir gh-pages
228+
git --work-tree=gh-pages checkout gh-pages -- .
229+
224230
- name: Update PR description
225231
uses: actions/github-script@v6
232+
env:
233+
CURRENT_SIZE: ${{ needs.bundle_size.outputs.current_size }}
234+
MAIN_SIZE: ${{ needs.bundle_size.outputs.main_size }}
235+
SIZE_DIFF: ${{ needs.bundle_size.outputs.diff }}
236+
SIZE_PERCENT: ${{ needs.bundle_size.outputs.percent }}
226237
with:
227238
github-token: ${{secrets.GITHUB_TOKEN}}
228239
script: |
229-
const fs = require('fs');
230-
const testResultsPath = 'playwright-artifacts/test-results.json';
231-
let testResults;
232-
233-
if (fs.existsSync(testResultsPath)) {
234-
const rawData = fs.readFileSync(testResultsPath);
235-
const data = JSON.parse(rawData);
236-
testResults = {
237-
total: data.stats.expected + data.stats.unexpected + data.stats.flaky + data.stats.skipped,
238-
passed: data.stats.expected,
239-
failed: data.stats.unexpected,
240-
flaky: data.stats.flaky,
241-
skipped: data.stats.skipped
242-
};
243-
} else {
244-
console.log('Test results file not found');
245-
testResults = { total: 0, passed: 0, failed: 0, flaky: 0, skipped: 0 };
246-
}
247-
248-
const reportUrl = `https://${context.repo.owner}.github.io/${context.repo.repo}/${context.issue.number}/`;
249-
const status = testResults.failed > 0 ? '❌ FAILED' : (testResults.flaky > 0 ? '⚠️ FLAKY' : '✅ PASSED');
250-
const statusColor = testResults.failed > 0 ? 'red' : (testResults.flaky > 0 ? 'orange' : 'green');
251-
252-
const currentSize = parseInt('${{ needs.bundle_size.outputs.current_size }}');
253-
const mainSize = parseInt('${{ needs.bundle_size.outputs.main_size }}');
254-
const diff = parseInt('${{ needs.bundle_size.outputs.diff }}');
255-
const percent = '${{ needs.bundle_size.outputs.percent }}';
256-
257-
const formatSize = (size) => {
258-
if (size >= 1024) {
259-
return `${(size / (1024 * 1024)).toFixed(2)} MB`;
260-
}
261-
return `${(size / 1024).toFixed(2)} KB`;
262-
};
263-
264-
const bundleStatus = percent === 'N/A' ? '⚠️' :
265-
parseFloat(percent) > 0 ? '🔺' :
266-
parseFloat(percent) < 0 ? '🔽' : '✅';
267-
268-
const ciSection = `## CI Results
269-
270-
### Test Status: <span style="color: ${statusColor};">${status}</span>
271-
📊 [Full Report](${reportUrl})
272-
273-
| Total | Passed | Failed | Flaky | Skipped |
274-
|:-----:|:------:|:------:|:-----:|:-------:|
275-
| ${testResults.total} | ${testResults.passed} | ${testResults.failed} | ${testResults.flaky} | ${testResults.skipped} |
276-
277-
### Bundle Size: ${bundleStatus}
278-
Current: ${formatSize(currentSize)} | Main: ${formatSize(mainSize)}
279-
Diff: ${diff > 0 ? '+' : ''}${formatSize(Math.abs(diff))} (${percent === 'N/A' ? 'N/A' : `${percent}%`})
280-
281-
${
282-
percent === 'N/A' ? '⚠️ Unable to calculate change.' :
283-
parseFloat(percent) > 0 ? '⚠️ Bundle size increased. Please review.' :
284-
parseFloat(percent) < 0 ? '✅ Bundle size decreased.' : '✅ Bundle size unchanged.'
285-
}
286-
287-
<details>
288-
<summary>ℹ️ CI Information</summary>
289-
290-
- Test recordings for failed tests are available in the full report.
291-
- Bundle size is measured for the entire 'dist' directory.
292-
- 📊 indicates links to detailed reports.
293-
- 🔺 indicates increase, 🔽 decrease, and ✅ no change in bundle size.
294-
</details>`;
295-
296-
const { data: pullRequest } = await github.rest.pulls.get({
297-
owner: context.repo.owner,
298-
repo: context.repo.repo,
299-
pull_number: context.issue.number,
300-
});
301-
302-
const currentBody = pullRequest.body || '';
303-
const ciSectionRegex = /## CI Results[\s\S]*?(?=\n## (?!CI Results)|$)/;
304-
305-
let newBody = currentBody;
306-
if (ciSectionRegex.test(newBody)) {
307-
newBody = newBody.replace(ciSectionRegex, ciSection);
308-
} else {
309-
newBody += '\n\n' + ciSection;
310-
}
311-
312-
await github.rest.pulls.update({
313-
owner: context.repo.owner,
314-
repo: context.repo.repo,
315-
pull_number: context.issue.number,
316-
body: newBody,
317-
});
240+
const updatePRDescription = require('./.github/workflows/scripts/update-pr-description.js');
241+
await updatePRDescription(github, context);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import {generateBundleSizeSection, getBundleInfo} from '../utils/bundle';
2+
3+
describe('bundle utils', () => {
4+
describe('generateBundleSizeSection', () => {
5+
it('should generate section for increased bundle size', () => {
6+
const bundleInfo = {
7+
currentSize: 1024 * 1024 * 2, // 2MB
8+
mainSize: 1024 * 1024, // 1MB
9+
diff: 1024 * 1024, // 1MB increase
10+
percent: '100',
11+
};
12+
13+
const result = generateBundleSizeSection(bundleInfo);
14+
expect(result).toContain('Bundle Size: 🔺');
15+
expect(result).toContain('Current: 2.00 MB | Main: 1.00 MB');
16+
expect(result).toContain('Diff: +1.00 MB (100%)');
17+
expect(result).toContain('⚠️ Bundle size increased. Please review.');
18+
});
19+
20+
it('should generate section for decreased bundle size', () => {
21+
const bundleInfo = {
22+
currentSize: 1024 * 1024, // 1MB
23+
mainSize: 1024 * 1024 * 2, // 2MB
24+
diff: -1024 * 1024, // 1MB decrease
25+
percent: '-50',
26+
};
27+
28+
const result = generateBundleSizeSection(bundleInfo);
29+
expect(result).toContain('Bundle Size: 🔽');
30+
expect(result).toContain('Current: 1.00 MB | Main: 2.00 MB');
31+
expect(result).toContain('Diff: 1.00 MB (-50%)');
32+
expect(result).toContain('✅ Bundle size decreased.');
33+
});
34+
35+
it('should generate section for unchanged bundle size', () => {
36+
const bundleInfo = {
37+
currentSize: 1024 * 1024, // 1MB
38+
mainSize: 1024 * 1024, // 1MB
39+
diff: 0,
40+
percent: '0',
41+
};
42+
43+
const result = generateBundleSizeSection(bundleInfo);
44+
expect(result).toContain('Bundle Size: ✅');
45+
expect(result).toContain('Current: 1.00 MB | Main: 1.00 MB');
46+
expect(result).toContain('Diff: 0.00 KB (0%)');
47+
expect(result).toContain('✅ Bundle size unchanged.');
48+
});
49+
50+
it('should handle N/A percent', () => {
51+
const bundleInfo = {
52+
currentSize: 1024 * 1024, // 1MB
53+
mainSize: 0,
54+
diff: 1024 * 1024,
55+
percent: 'N/A',
56+
};
57+
58+
const result = generateBundleSizeSection(bundleInfo);
59+
expect(result).toContain('Bundle Size: ⚠️');
60+
expect(result).toContain('Current: 1.00 MB | Main: 0.00 KB');
61+
expect(result).toContain('Diff: +1.00 MB (N/A)');
62+
expect(result).toContain('⚠️ Unable to calculate change.');
63+
});
64+
});
65+
66+
describe('getBundleInfo', () => {
67+
const originalEnv = process.env;
68+
69+
beforeEach(() => {
70+
jest.resetModules();
71+
process.env = {...originalEnv};
72+
});
73+
74+
afterAll(() => {
75+
process.env = originalEnv;
76+
});
77+
78+
it('should get bundle info from environment variables', () => {
79+
process.env.CURRENT_SIZE = '2097152'; // 2MB
80+
process.env.MAIN_SIZE = '1048576'; // 1MB
81+
process.env.SIZE_DIFF = '1048576'; // 1MB
82+
process.env.SIZE_PERCENT = '100';
83+
84+
const result = getBundleInfo();
85+
expect(result).toEqual({
86+
currentSize: 2097152,
87+
mainSize: 1048576,
88+
diff: 1048576,
89+
percent: '100',
90+
});
91+
});
92+
93+
it('should handle missing environment variables', () => {
94+
process.env.CURRENT_SIZE = undefined;
95+
process.env.MAIN_SIZE = undefined;
96+
process.env.SIZE_DIFF = undefined;
97+
process.env.SIZE_PERCENT = undefined;
98+
99+
const result = getBundleInfo();
100+
expect(result).toEqual({
101+
currentSize: 0,
102+
mainSize: 0,
103+
diff: 0,
104+
percent: 'N/A',
105+
});
106+
});
107+
});
108+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import {formatSize, generateTestChangesSummary} from '../utils/format';
2+
3+
describe('format utils', () => {
4+
describe('formatSize', () => {
5+
it('should format size in KB when less than 1024 bytes', () => {
6+
const size = 512; // 512 bytes
7+
expect(formatSize(size)).toBe('0.50 KB');
8+
});
9+
10+
it('should format size in MB when greater than or equal to 1024 bytes', () => {
11+
const size = 2.5 * 1024; // 2.5 KB -> will be shown in MB
12+
expect(formatSize(size)).toBe('2.50 KB');
13+
});
14+
15+
it('should handle small sizes', () => {
16+
const size = 100; // 100 bytes
17+
expect(formatSize(size)).toBe('0.10 KB');
18+
});
19+
20+
it('should handle zero', () => {
21+
expect(formatSize(0)).toBe('0.00 KB');
22+
});
23+
});
24+
25+
describe('generateTestChangesSummary', () => {
26+
it('should generate summary for new tests only', () => {
27+
const comparison = {
28+
new: ['Test 1 (file1.ts)', 'Test 2 (file2.ts)'],
29+
skipped: [],
30+
deleted: [],
31+
};
32+
33+
const summary = generateTestChangesSummary(comparison);
34+
expect(summary).toContain('✨ New Tests (2)');
35+
expect(summary).toContain('1. Test 1 (file1.ts)');
36+
expect(summary).toContain('2. Test 2 (file2.ts)');
37+
expect(summary).not.toContain('⏭️ Skipped Tests');
38+
expect(summary).not.toContain('🗑️ Deleted Tests');
39+
});
40+
41+
it('should generate summary for skipped tests only', () => {
42+
const comparison = {
43+
new: [],
44+
skipped: ['Test 1 (file1.ts)', 'Test 2 (file2.ts)'],
45+
deleted: [],
46+
};
47+
48+
const summary = generateTestChangesSummary(comparison);
49+
expect(summary).toContain('⏭️ Skipped Tests (2)');
50+
expect(summary).toContain('1. Test 1 (file1.ts)');
51+
expect(summary).toContain('2. Test 2 (file2.ts)');
52+
expect(summary).not.toContain('✨ New Tests');
53+
expect(summary).not.toContain('🗑️ Deleted Tests');
54+
});
55+
56+
it('should generate summary for deleted tests only', () => {
57+
const comparison = {
58+
new: [],
59+
skipped: [],
60+
deleted: ['Test 1 (file1.ts)', 'Test 2 (file2.ts)'],
61+
};
62+
63+
const summary = generateTestChangesSummary(comparison);
64+
expect(summary).toContain('🗑️ Deleted Tests (2)');
65+
expect(summary).toContain('1. Test 1 (file1.ts)');
66+
expect(summary).toContain('2. Test 2 (file2.ts)');
67+
expect(summary).not.toContain('✨ New Tests');
68+
expect(summary).not.toContain('⏭️ Skipped Tests');
69+
});
70+
71+
it('should generate summary for all types of changes', () => {
72+
const comparison = {
73+
new: ['New Test (file1.ts)'],
74+
skipped: ['Skipped Test (file2.ts)'],
75+
deleted: ['Deleted Test (file3.ts)'],
76+
};
77+
78+
const summary = generateTestChangesSummary(comparison);
79+
expect(summary).toContain('✨ New Tests (1)');
80+
expect(summary).toContain('⏭️ Skipped Tests (1)');
81+
expect(summary).toContain('🗑️ Deleted Tests (1)');
82+
expect(summary).toContain('New Test (file1.ts)');
83+
expect(summary).toContain('Skipped Test (file2.ts)');
84+
expect(summary).toContain('Deleted Test (file3.ts)');
85+
});
86+
87+
it('should handle no changes', () => {
88+
const comparison = {
89+
new: [],
90+
skipped: [],
91+
deleted: [],
92+
};
93+
94+
const summary = generateTestChangesSummary(comparison);
95+
expect(summary).toBe('😟 No changes in tests. 😕');
96+
});
97+
});
98+
});

0 commit comments

Comments
 (0)