Skip to content

Commit 5936383

Browse files
committed
test(ci): integration test for portal cache in standalone mode
1 parent 360c112 commit 5936383

File tree

6 files changed

+248
-36
lines changed

6 files changed

+248
-36
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"persist": {
3+
"outputDir": ".code-pushup",
4+
"filename": "report",
5+
"format": ["json", "md"]
6+
},
7+
"upload": {
8+
"server": "https://api.code-pushup.dunder-mifflin.org/graphql",
9+
"apiKey": "cp_abcdef0123456789",
10+
"organization": "dunder-mifflin",
11+
"project": "website"
12+
},
13+
"categories": [],
14+
"plugins": [
15+
{
16+
"title": "TypeScript migration",
17+
"slug": "ts-migration",
18+
"icon": "typescript",
19+
"audits": [
20+
{
21+
"slug": "ts-files",
22+
"title": "Source files converted from JavaScript to TypeScript"
23+
}
24+
]
25+
}
26+
]
27+
}

packages/ci/mocks/fixtures/outputs/diff-project.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
"hash": "efed65b3ffab808176c4f8670d77f8d69f71490e",
55
"message": "Initial commit",
66
"date": "2024-10-14T09:00:13.000Z",
7-
"author": "John Doe"
7+
"author": "John Doe <john.doe@example.com>"
88
},
99
"after": {
1010
"hash": "2f3b5365432abb7c9949aa50ff3aa8b7a02256de",
1111
"message": "Convert JS file to TS",
1212
"date": "2024-10-14T09:00:13.000Z",
13-
"author": "John Doe"
13+
"author": "John Doe <john.doe@example.com>"
1414
}
1515
},
1616
"categories": {

packages/ci/mocks/fixtures/outputs/report-after.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"hash": "99781f731759ef36b2fb7e4a39703965904f5376",
44
"message": "Convert JS file to TS",
55
"date": "2024-10-14T09:55:21.000Z",
6-
"author": "John Doe"
6+
"author": "John Doe <john.doe@example.com>"
77
},
88
"packageName": "@code-pushup/core",
99
"version": "0.51.0",

packages/ci/mocks/fixtures/outputs/report-before.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"hash": "efed65b3ffab808176c4f8670d77f8d69f71490e",
44
"message": "Initial commit",
55
"date": "2024-10-14T09:00:13.000Z",
6-
"author": "John Doe"
6+
"author": "John Doe <john.doe@example.com>"
77
},
88
"packageName": "@code-pushup/core",
99
"version": "0.51.0",
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"__typename": "Report",
3+
"commit": {
4+
"__typename": "Commit",
5+
"sha": "efed65b3ffab808176c4f8670d77f8d69f71490e",
6+
"message": "Initial commit",
7+
"date": "2024-10-14T09:00:13.000Z",
8+
"author": {
9+
"__typename": "CommitAuthor",
10+
"name": "John Doe",
11+
"email": "john.doe@example.com"
12+
}
13+
},
14+
"packageName": "@code-pushup/core",
15+
"packageVersion": "0.51.0",
16+
"commandStartDate": "2024-10-14T09:00:14.969Z",
17+
"commandDuration": 14,
18+
"categories": [],
19+
"plugins": [
20+
{
21+
"__typename": "Plugin",
22+
"slug": "ts-migration",
23+
"title": "TypeScript migration",
24+
"icon": "typescript",
25+
"description": null,
26+
"docsUrl": null,
27+
"packageName": null,
28+
"packageVersion": null,
29+
"runnerStartDate": "2024-10-14T09:00:14.978Z",
30+
"runnerDuration": 2,
31+
"audits": {
32+
"edges": [
33+
{
34+
"node": {
35+
"__typename": "Audit",
36+
"slug": "ts-files",
37+
"title": "Source files converted from JavaScript to TypeScript",
38+
"description": null,
39+
"docsUrl": null,
40+
"score": 0.5,
41+
"value": 50,
42+
"formattedValue": "50% converted",
43+
"details": {
44+
"enabled": true,
45+
"tables": [],
46+
"trees": []
47+
}
48+
}
49+
}
50+
]
51+
},
52+
"groups": []
53+
}
54+
],
55+
"issues": {
56+
"edges": [
57+
{
58+
"node": {
59+
"__typename": "Issue",
60+
"message": "Use .ts file extension instead of .js",
61+
"severity": "WARNING",
62+
"audit": {
63+
"__typename": "Audit",
64+
"slug": "ts-files",
65+
"plugin": {
66+
"__typename": "Plugin",
67+
"slug": "ts-migration"
68+
}
69+
},
70+
"source": {
71+
"__typename": "SourceCodeLocation",
72+
"filePath": "index.js",
73+
"startLine": null,
74+
"startColumn": null,
75+
"endLine": null,
76+
"endColumn": null
77+
}
78+
}
79+
}
80+
]
81+
}
82+
}

packages/ci/src/lib/run.int.test.ts

Lines changed: 135 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import path from 'node:path';
1010
import { fileURLToPath } from 'node:url';
1111
import { type SimpleGit, simpleGit } from 'simple-git';
1212
import { type MockInstance, expect } from 'vitest';
13+
import {
14+
type ReportFragment,
15+
downloadFromPortal,
16+
} from '@code-pushup/portal-client';
1317
import type { CoreConfig } from '@code-pushup/models';
1418
import {
1519
cleanTestFolder,
@@ -29,40 +33,57 @@ import type {
2933
import type { MonorepoTool } from './monorepo/index.js';
3034
import { runInCI } from './run.js';
3135

32-
describe('runInCI', () => {
33-
const fixturesDir = path.join(
34-
fileURLToPath(path.dirname(import.meta.url)),
35-
'..',
36-
'..',
37-
'mocks',
38-
'fixtures',
39-
);
40-
const reportsDir = path.join(fixturesDir, 'outputs');
41-
const workDir = path.join(process.cwd(), 'tmp', 'ci', 'run-test');
42-
43-
const fixturePaths = {
44-
reports: {
45-
before: {
46-
json: path.join(reportsDir, 'report-before.json'),
47-
md: path.join(reportsDir, 'report-before.md'),
48-
},
49-
after: {
50-
json: path.join(reportsDir, 'report-after.json'),
51-
md: path.join(reportsDir, 'report-after.md'),
52-
},
36+
vi.mock('@code-pushup/portal-client', async importOriginal => {
37+
const mod: typeof import('@code-pushup/portal-client') =
38+
await importOriginal();
39+
return {
40+
...mod,
41+
downloadFromPortal: vi.fn(simulateDownloadFromPortal),
42+
};
43+
});
44+
45+
const fixturesDir = path.join(
46+
fileURLToPath(path.dirname(import.meta.url)),
47+
'..',
48+
'..',
49+
'mocks',
50+
'fixtures',
51+
);
52+
const reportsDir = path.join(fixturesDir, 'outputs');
53+
const workDir = path.join(process.cwd(), 'tmp', 'ci', 'run-test');
54+
55+
const fixturePaths = {
56+
reports: {
57+
before: {
58+
json: path.join(reportsDir, 'report-before.json'),
59+
md: path.join(reportsDir, 'report-before.md'),
60+
portal: path.join(reportsDir, 'report-before.portal.json'),
5361
},
54-
diffs: {
55-
project: {
56-
json: path.join(reportsDir, 'diff-project.json'),
57-
md: path.join(reportsDir, 'diff-project.md'),
58-
},
59-
merged: {
60-
md: path.join(reportsDir, 'diff-merged.md'),
61-
},
62+
after: {
63+
json: path.join(reportsDir, 'report-after.json'),
64+
md: path.join(reportsDir, 'report-after.md'),
6265
},
63-
config: path.join(reportsDir, 'config.json'),
64-
};
66+
},
67+
diffs: {
68+
project: {
69+
json: path.join(reportsDir, 'diff-project.json'),
70+
md: path.join(reportsDir, 'diff-project.md'),
71+
},
72+
merged: {
73+
md: path.join(reportsDir, 'diff-merged.md'),
74+
},
75+
},
76+
config: {
77+
base: path.join(reportsDir, 'config.json'),
78+
portal: path.join(reportsDir, 'config.portal.json'),
79+
},
80+
};
81+
82+
function simulateDownloadFromPortal() {
83+
return utils.readJsonFile<ReportFragment>(fixturePaths.reports.before.portal);
84+
}
6585

86+
describe('runInCI', () => {
6687
const logger: Logger = {
6788
error: vi.fn(),
6889
warn: vi.fn(),
@@ -87,6 +108,8 @@ describe('runInCI', () => {
87108
onStdout: expect.any(Function),
88109
});
89110

111+
let includeUploadConfig: boolean;
112+
90113
let git: SimpleGit;
91114

92115
let cwdSpy: MockInstance<
@@ -120,7 +143,12 @@ describe('runInCI', () => {
120143
break;
121144

122145
case 'print-config':
123-
let content = await readFile(fixturePaths.config, 'utf8');
146+
let content = await readFile(
147+
includeUploadConfig
148+
? fixturePaths.config.portal
149+
: fixturePaths.config.base,
150+
'utf8',
151+
);
124152
if (nxMatch) {
125153
// simulate effect of custom persist.outputDir per Nx project
126154
const config = JSON.parse(content) as CoreConfig;
@@ -184,6 +212,8 @@ describe('runInCI', () => {
184212
const outputDir = path.join(workDir, '.code-pushup', '.ci');
185213

186214
beforeEach(async () => {
215+
includeUploadConfig = false;
216+
187217
const originalExecuteProcess = utils.executeProcess;
188218
executeProcessSpy = vi
189219
.spyOn(utils, 'executeProcess')
@@ -441,6 +471,79 @@ describe('runInCI', () => {
441471
expect(logger.debug).toHaveBeenCalled();
442472
});
443473

474+
it('should use cached old report from portal when upload is configured', async () => {
475+
includeUploadConfig = true;
476+
477+
const api: ProviderAPIClient = {
478+
maxCommentChars: 1_000_000,
479+
createComment: vi.fn().mockResolvedValue(mockComment),
480+
updateComment: vi.fn(),
481+
listComments: vi.fn().mockResolvedValue([]),
482+
downloadReportArtifact: vi.fn(),
483+
};
484+
485+
await expect(runInCI(refs, api, options, git)).resolves.toEqual({
486+
mode: 'standalone',
487+
commentId: mockComment.id,
488+
newIssues: [],
489+
files: {
490+
current: {
491+
json: path.join(outputDir, '.current/report.json'),
492+
md: path.join(outputDir, '.current/report.md'),
493+
},
494+
previous: {
495+
json: path.join(outputDir, '.previous/report.json'),
496+
},
497+
comparison: {
498+
json: path.join(outputDir, '.comparison/report-diff.json'),
499+
md: path.join(outputDir, '.comparison/report-diff.md'),
500+
},
501+
},
502+
} satisfies RunResult);
503+
504+
expect(downloadFromPortal).toHaveBeenCalledWith({
505+
server: 'https://api.code-pushup.dunder-mifflin.org/graphql',
506+
apiKey: 'cp_abcdef0123456789',
507+
parameters: {
508+
organization: 'dunder-mifflin',
509+
project: 'website',
510+
},
511+
});
512+
513+
expect(api.downloadReportArtifact).not.toHaveBeenCalled();
514+
515+
expect(utils.executeProcess).toHaveBeenCalledTimes(3);
516+
expect(utils.executeProcess).toHaveBeenNthCalledWith(1, {
517+
command: options.bin,
518+
args: ['print-config', expect.stringMatching(/^--output=.*\.json$/)],
519+
cwd: workDir,
520+
observer: expectedObserver,
521+
} satisfies utils.ProcessConfig);
522+
expect(utils.executeProcess).toHaveBeenNthCalledWith(2, {
523+
command: options.bin,
524+
args: [],
525+
cwd: workDir,
526+
observer: expectedObserver,
527+
} satisfies utils.ProcessConfig);
528+
expect(utils.executeProcess).toHaveBeenNthCalledWith(3, {
529+
command: options.bin,
530+
args: [
531+
'compare',
532+
`--before=${path.join(outputDir, '.previous/report.json')}`,
533+
`--after=${path.join(outputDir, '.current/report.json')}`,
534+
'--persist.format=json',
535+
'--persist.format=md',
536+
],
537+
cwd: workDir,
538+
observer: expectedObserver,
539+
} satisfies utils.ProcessConfig);
540+
541+
expect(logger.error).not.toHaveBeenCalled();
542+
expect(logger.warn).not.toHaveBeenCalled();
543+
expect(logger.info).toHaveBeenCalled();
544+
expect(logger.debug).toHaveBeenCalled();
545+
});
546+
444547
it('should skip comment if disabled', async () => {
445548
const api: ProviderAPIClient = {
446549
maxCommentChars: 1_000_000,

0 commit comments

Comments
 (0)