Skip to content

Commit 84744b2

Browse files
committed
Merge remote-tracking branch 'origin/main' into add-plugin-targets
# Conflicts: # code-pushup.config.ts
2 parents d114076 + a419aec commit 84744b2

File tree

12 files changed

+134
-55
lines changed

12 files changed

+134
-55
lines changed

e2e/plugin-typescript-e2e/mocks/fixtures/default-setup/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"compilerOptions": {
3-
"rootDir": "./src",
3+
"rootDir": "${configDir}/src",
44
"target": "ES6",
55
"module": "CommonJS",
66
"strict": true,

e2e/plugin-typescript-e2e/tests/__snapshots__/collect.e2e.test.ts.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ exports[`PLUGIN collect report with typescript-plugin NPM package > should run p
121121
"details": {
122122
"issues": [
123123
{
124-
"message": "TS6059: File './exclude/utils.ts' is not under 'rootDir' 'src'. 'rootDir' is expected to contain all source files.",
124+
"message": "TS6059: File './exclude/utils.ts' is not under 'rootDir' './src'. 'rootDir' is expected to contain all source files.",
125125
"severity": "error",
126126
"source": {
127127
"file": "tmp/e2e/plugin-typescript-e2e/src/6-configuration-errors.ts",

e2e/plugin-typescript-e2e/tests/collect.e2e.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,35 @@ import {
77
E2E_ENVIRONMENTS_DIR,
88
TEST_OUTPUT_DIR,
99
omitVariableReportData,
10+
osAgnosticAuditOutputs,
11+
osAgnosticPath,
1012
teardownTestFolder,
1113
} from '@code-pushup/test-utils';
1214
import { executeProcess, readJsonFile } from '@code-pushup/utils';
1315

16+
function sanitizeReportPaths(report: Report): Report {
17+
return {
18+
...report,
19+
plugins: report.plugins.map(plugin => ({
20+
...plugin,
21+
audits: osAgnosticAuditOutputs(plugin.audits, message =>
22+
message.replace(
23+
/['"]([^'"]*[/\\][^'"]*)['"]/g,
24+
(fullMatch: string, capturedPath: string) => {
25+
const osAgnostic = osAgnosticPath(capturedPath);
26+
// Only replace directory paths, not .ts file paths
27+
if (capturedPath.endsWith('.ts')) {
28+
return `'${osAgnostic}'`;
29+
}
30+
// on Windows the path starts from "plugin-typescript-e2e/src" not "./". This normalizes it to "./<segment>"
31+
return `'${['.', osAgnostic.split('/').slice(-1)].join('/')}'`;
32+
},
33+
),
34+
),
35+
})),
36+
};
37+
}
38+
1439
describe('PLUGIN collect report with typescript-plugin NPM package', () => {
1540
const envRoot = path.join(E2E_ENVIRONMENTS_DIR, nxTargetProject());
1641
const distRoot = path.join(envRoot, TEST_OUTPUT_DIR);
@@ -57,6 +82,9 @@ describe('PLUGIN collect report with typescript-plugin NPM package', () => {
5782
path.join(envRoot, outputDir, 'report.json'),
5883
);
5984
expect(() => reportSchema.parse(reportJson)).not.toThrow();
60-
expect(omitVariableReportData(reportJson)).toMatchSnapshot();
85+
86+
expect(
87+
omitVariableReportData(sanitizeReportPaths(reportJson)),
88+
).toMatchSnapshot();
6189
});
6290
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"compilerOptions": {
3+
"rootDir": "${configDir}",
4+
"verbatimModuleSyntax": false
5+
},
6+
"include": ["src/**/*.ts"]
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "./tsconfig.extends-base.json",
3+
"compilerOptions": {
4+
"verbatimModuleSyntax": true,
5+
"module": "CommonJS"
6+
},
7+
"exclude": ["src/*-errors/**/*.ts"]
8+
}
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import { describe, expect } from 'vitest';
2+
import type { AuditOutputs } from '@code-pushup/models';
3+
import { osAgnosticAuditOutputs } from '@code-pushup/test-utils';
24
import { getAudits } from '../utils.js';
35
import { createRunnerFunction } from './runner.js';
46

57
describe('createRunnerFunction', () => {
68
it('should create valid audit outputs when called', async () => {
7-
await expect(
8-
createRunnerFunction({
9-
tsconfig:
10-
'packages/plugin-typescript/mocks/fixtures/basic-setup/tsconfig.all-audits.json',
11-
expectedAudits: getAudits(),
12-
})(() => void 0),
13-
).resolves.toMatchSnapshot();
9+
const runnerFunction = createRunnerFunction({
10+
tsconfig:
11+
'packages/plugin-typescript/mocks/fixtures/basic-setup/tsconfig.all-audits.json',
12+
expectedAudits: getAudits(),
13+
});
14+
15+
const result = await runnerFunction();
16+
17+
expect(osAgnosticAuditOutputs(result as AuditOutputs)).toMatchSnapshot();
1418
}, 35_000);
1519
});

packages/plugin-typescript/src/lib/runner/ts-runner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export type DiagnosticsOptions = {
1313
export async function getTypeScriptDiagnostics({
1414
tsconfig,
1515
}: DiagnosticsOptions): Promise<readonly Diagnostic[]> {
16-
const { fileNames, options } = await loadTargetConfig(tsconfig);
16+
const { fileNames, options } = loadTargetConfig(tsconfig);
1717
try {
1818
const program = createProgram(fileNames, options);
1919
return getPreEmitDiagnostics(program);
Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
import * as tsModule from 'typescript';
2-
import { describe, expect } from 'vitest';
2+
import { describe, expect, vi } from 'vitest';
3+
import { osAgnosticPath } from '@code-pushup/test-utils';
34
import { loadTargetConfig } from './utils.js';
45

56
describe('loadTargetConfig', () => {
6-
const parseConfigFileTextToJsonSpy = vi.spyOn(
7-
tsModule,
8-
'parseConfigFileTextToJson',
9-
);
7+
const readConfigFileSpy = vi.spyOn(tsModule, 'readConfigFile');
108
const parseJsonConfigFileContentSpy = vi.spyOn(
119
tsModule,
1210
'parseJsonConfigFileContent',
1311
);
1412

15-
it('should return the parsed content of a tsconfig file and ist TypeScript helper to parse it', async () => {
16-
await expect(
13+
it('should return the parsed content of a tsconfig file and ist TypeScript helper to parse it', () => {
14+
expect(
1715
loadTargetConfig(
18-
'packages/plugin-typescript/mocks/fixtures/basic-setup/tsconfig.init.json',
16+
osAgnosticPath(
17+
'packages/plugin-typescript/mocks/fixtures/basic-setup/tsconfig.init.json',
18+
),
1919
),
20-
).resolves.toStrictEqual(
20+
).toStrictEqual(
2121
expect.objectContaining({
2222
fileNames: expect.any(Array),
2323
options: {
2424
module: 1,
25-
configFilePath: undefined,
25+
configFilePath: expect.stringContaining('tsconfig.init.json'),
2626
esModuleInterop: true,
2727
forceConsistentCasingInFileNames: true,
2828
skipLibCheck: true,
@@ -31,25 +31,39 @@ describe('loadTargetConfig', () => {
3131
},
3232
}),
3333
);
34-
expect(parseConfigFileTextToJsonSpy).toHaveBeenCalledTimes(1);
35-
expect(parseConfigFileTextToJsonSpy).toHaveBeenCalledWith(
36-
'packages/plugin-typescript/mocks/fixtures/basic-setup/tsconfig.init.json',
37-
expect.stringContaining('/* Projects */'),
34+
expect(readConfigFileSpy).toHaveBeenCalledTimes(1);
35+
expect(readConfigFileSpy).toHaveBeenCalledWith(
36+
expect.stringContaining('tsconfig.init.json'),
37+
expect.any(Function),
3838
);
3939
expect(parseJsonConfigFileContentSpy).toHaveBeenCalledTimes(1);
40-
expect(parseJsonConfigFileContentSpy).toHaveBeenCalledWith(
40+
});
41+
42+
it('should return the parsed content of a tsconfig file that extends another config', () => {
43+
expect(
44+
loadTargetConfig(
45+
'packages/plugin-typescript/mocks/fixtures/basic-setup/tsconfig.extends-extending.json',
46+
),
47+
).toStrictEqual(
4148
expect.objectContaining({
42-
compilerOptions: expect.objectContaining({
43-
esModuleInterop: true,
44-
forceConsistentCasingInFileNames: true,
45-
module: 'commonjs',
46-
skipLibCheck: true,
47-
strict: true,
48-
target: 'es2016',
49+
fileNames: expect.arrayContaining([
50+
// from tsconfig.extends-base.json#includes and tsconfig.extends-extending.json#excludes
51+
expect.stringMatching(/src[/\\]0-no-diagnostics[/\\]/),
52+
]),
53+
options: expect.objectContaining({
54+
// Options from tsconfig.extends-base.json
55+
rootDir: expect.stringMatching(/basic-setup$/),
56+
// Options from tsconfig.extends-extending.json
57+
module: 1,
58+
configFilePath: expect.stringContaining(
59+
'tsconfig.extends-extending.json',
60+
),
61+
verbatimModuleSyntax: true, // Overrides base config's false
4962
}),
5063
}),
51-
expect.any(Object),
52-
expect.any(String),
5364
);
65+
66+
expect(readConfigFileSpy).toHaveBeenCalledTimes(1);
67+
expect(parseJsonConfigFileContentSpy).toHaveBeenCalledTimes(1);
5468
});
5569
});

packages/plugin-typescript/src/lib/runner/utils.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
// eslint-disable-next-line unicorn/import-style
2-
import { dirname } from 'node:path';
1+
import path from 'node:path';
32
import {
43
type Diagnostic,
54
DiagnosticCategory,
65
flattenDiagnosticMessageText,
7-
parseConfigFileTextToJson,
86
parseJsonConfigFileContent,
7+
readConfigFile,
98
sys,
109
} from 'typescript';
1110
import type { Issue } from '@code-pushup/models';
12-
import { readTextFile, truncateIssueMessage } from '@code-pushup/utils';
11+
import { truncateIssueMessage } from '@code-pushup/utils';
1312
import { TS_CODE_RANGE_NAMES } from './ts-error-codes.js';
1413
import type { CodeRangeName } from './types.js';
1514

@@ -84,7 +83,7 @@ export function getIssueFromDiagnostic(diag: Diagnostic) {
8483
return {
8584
...issue,
8685
source: {
87-
file: diag.file.fileName,
86+
file: path.relative(process.cwd(), diag.file.fileName),
8887
...(startLine
8988
? {
9089
position: {
@@ -96,16 +95,22 @@ export function getIssueFromDiagnostic(diag: Diagnostic) {
9695
} satisfies Issue;
9796
}
9897

99-
export async function loadTargetConfig(tsConfigPath: string) {
100-
const { config } = parseConfigFileTextToJson(
101-
tsConfigPath,
102-
await readTextFile(tsConfigPath),
103-
);
98+
export function loadTargetConfig(tsConfigPath: string) {
99+
const resolvedConfigPath = path.resolve(tsConfigPath);
100+
const { config, error } = readConfigFile(resolvedConfigPath, sys.readFile);
101+
102+
if (error) {
103+
throw new Error(
104+
`Error reading TypeScript config file at ${tsConfigPath}:\n${error.messageText}`,
105+
);
106+
}
104107

105108
const parsedConfig = parseJsonConfigFileContent(
106109
config,
107110
sys,
108-
dirname(tsConfigPath),
111+
path.dirname(resolvedConfigPath),
112+
{},
113+
resolvedConfigPath,
109114
);
110115

111116
if (parsedConfig.fileNames.length === 0) {

packages/plugin-typescript/vitest.int.config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ export default defineConfig({
1616
coverage: {
1717
reporter: ['text', 'lcov'],
1818
reportsDirectory: '../../coverage/plugin-typescript/int-tests',
19-
exclude: ['mocks/**', '**/types.ts'],
19+
exclude: [
20+
'mocks/**',
21+
'**/types.ts',
22+
'**/index.ts',
23+
'vitest.{unit,int}.config.ts',
24+
],
2025
},
2126
environment: 'node',
2227
include: ['src/**/*.int.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],

0 commit comments

Comments
 (0)