Skip to content

Commit cedf140

Browse files
authored
test(test-setup): add custom path matcher to vitest, add tests (#876)
1 parent c219602 commit cedf140

File tree

12 files changed

+301
-12
lines changed

12 files changed

+301
-12
lines changed

e2e/cli-e2e/tests/collect.e2e.test.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ describe('CLI collect', () => {
3838
});
3939

4040
it('should create report.md', async () => {
41-
const { code, stderr } = await executeProcess({
41+
const { code } = await executeProcess({
4242
command: 'npx',
4343
args: [
4444
'@code-pushup/cli',
@@ -50,7 +50,6 @@ describe('CLI collect', () => {
5050
});
5151

5252
expect(code).toBe(0);
53-
expect(stderr).toBe('');
5453

5554
const md = await readTextFile(path.join(dummyOutputDir, 'report.md'));
5655

@@ -60,14 +59,13 @@ describe('CLI collect', () => {
6059
});
6160

6261
it('should print report summary to stdout', async () => {
63-
const { code, stdout, stderr } = await executeProcess({
62+
const { code, stdout } = await executeProcess({
6463
command: 'npx',
6564
args: ['@code-pushup/cli', '--no-progress', 'collect'],
6665
cwd: dummyDir,
6766
});
6867

6968
expect(code).toBe(0);
70-
expect(stderr).toBe('');
7169

7270
expect(stdout).toContain('Code PushUp Report');
7371
expect(stdout).not.toContain('Generated reports');

e2e/cli-e2e/tests/help.e2e.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ describe('CLI help', () => {
1010
const envRoot = path.join(E2E_ENVIRONMENTS_DIR, nxTargetProject());
1111

1212
it('should print help with help command', async () => {
13-
const { code, stdout, stderr } = await executeProcess({
13+
const { code, stdout } = await executeProcess({
1414
command: 'npx',
1515
args: ['@code-pushup/cli', 'help'],
1616
cwd: envRoot,
1717
});
1818
expect(code).toBe(0);
19-
expect(stderr).toBe('');
2019
expect(removeColorCodes(stdout)).toMatchSnapshot();
2120
});
2221

e2e/create-cli-e2e/tests/init.e2e.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import { executeProcess, readJsonFile, readTextFile } from '@code-pushup/utils';
1313
const fakeCacheFolderName = () =>
1414
`fake-cache-${new Date().toISOString().replace(/[:.]/g, '-')}`;
1515

16-
describe('create-cli-init', () => {
16+
/* after a new release of the nx-verdaccio plugin we can enable the test again. For now, it is too flaky to be productive. (5.jan.2025) */
17+
describe.todo('create-cli-init', () => {
1718
const workspaceRoot = path.join(E2E_ENVIRONMENTS_DIR, nxTargetProject());
1819
const testFileDir = path.join(workspaceRoot, TEST_OUTPUT_DIR, 'init');
1920

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

+2-4
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,13 @@ describe('PLUGIN collect report with eslint-plugin NPM package', () => {
4747
});
4848

4949
it('should run ESLint plugin for flat config and create report.json', async () => {
50-
const { code, stderr } = await executeProcess({
50+
const { code } = await executeProcess({
5151
command: 'npx',
5252
args: ['@code-pushup/cli', 'collect', '--no-progress'],
5353
cwd: flatConfigDir,
5454
});
5555

5656
expect(code).toBe(0);
57-
expect(stderr).toBe('');
5857

5958
const report = await readJsonFile(
6059
path.join(flatConfigOutputDir, 'report.json'),
@@ -65,15 +64,14 @@ describe('PLUGIN collect report with eslint-plugin NPM package', () => {
6564
});
6665

6766
it('should run ESLint plugin for legacy config and create report.json', async () => {
68-
const { code, stderr } = await executeProcess({
67+
const { code } = await executeProcess({
6968
command: 'npx',
7069
args: ['@code-pushup/cli', 'collect', '--no-progress'],
7170
cwd: legacyConfigDir,
7271
env: { ...process.env, ESLINT_USE_FLAT_CONFIG: 'false' },
7372
});
7473

7574
expect(code).toBe(0);
76-
expect(stderr).toBe('');
7775

7876
const report = await readJsonFile(
7977
path.join(legacyConfigOutputDir, 'report.json'),

testing/test-setup/project.json

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
"assets": ["testing/test-setup/*.md"]
1515
}
1616
},
17+
"unit-test": {
18+
"executor": "@nx/vite:test",
19+
"options": {
20+
"configFile": "testing/test-setup/vite.config.unit.ts"
21+
}
22+
},
1723
"lint": {
1824
"executor": "@nx/linter:eslint",
1925
"outputs": ["{options.outputFile}"],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import type { SyncExpectationResult } from '@vitest/expect';
2+
import { expect } from 'vitest';
3+
import { osAgnosticPath } from '@code-pushup/test-utils';
4+
5+
export type CustomPathMatchers = {
6+
toMatchPath: (path: string) => void;
7+
toStartWithPath: (path: string) => void;
8+
toContainPath: (path: string) => void;
9+
toEndWithPath: (path: string) => void;
10+
};
11+
12+
export type CustomAsymmetricPathMatchers = {
13+
/* eslint-disable @typescript-eslint/no-explicit-any */
14+
pathToMatch: (path: string) => any;
15+
pathToStartWith: (path: string) => any;
16+
pathToContain: (path: string) => any;
17+
pathToEndWith: (path: string) => any;
18+
/* eslint-enable @typescript-eslint/no-explicit-any */
19+
};
20+
21+
expect.extend({
22+
toMatchPath: assertPathMatch,
23+
pathToMatch: assertPathMatch,
24+
toStartWithPath: assertPathStartWith,
25+
pathToStartWith: assertPathStartWith,
26+
toContainPath: assertPathContain,
27+
pathToContain: assertPathContain,
28+
toEndWithPath: assertPathEndWith,
29+
pathToEndWith: assertPathEndWith,
30+
});
31+
32+
function assertPathMatch(
33+
actual: string,
34+
expected: string,
35+
): SyncExpectationResult {
36+
const normalizedReceived = osAgnosticPath(actual);
37+
const normalizedExpected = osAgnosticPath(expected);
38+
39+
const pass = normalizedReceived === normalizedExpected;
40+
return pass
41+
? {
42+
message: () => `expected ${actual} not to match path ${expected}`,
43+
pass: true,
44+
actual,
45+
expected,
46+
}
47+
: {
48+
message: () => `expected ${actual} to match path ${expected}`,
49+
pass: false,
50+
actual,
51+
expected,
52+
};
53+
}
54+
55+
function assertPathStartWith(
56+
actual: string,
57+
expected: string,
58+
): SyncExpectationResult {
59+
const normalizedReceived = osAgnosticPath(actual);
60+
const normalizedExpected = osAgnosticPath(expected);
61+
62+
const pass = normalizedReceived.startsWith(normalizedExpected);
63+
return pass
64+
? {
65+
message: () => `expected ${actual} not to start with path ${expected}`,
66+
pass: true,
67+
actual,
68+
expected,
69+
}
70+
: {
71+
message: () => `expected ${actual} to start with path ${expected}`,
72+
pass: false,
73+
actual,
74+
expected,
75+
};
76+
}
77+
78+
function assertPathContain(
79+
actual: string,
80+
expected: string,
81+
): SyncExpectationResult {
82+
const normalizedReceived = osAgnosticPath(actual);
83+
const normalizedExpected = osAgnosticPath(expected);
84+
85+
const pass = normalizedReceived.includes(normalizedExpected);
86+
return pass
87+
? {
88+
message: () => `expected ${actual} not to contain path ${expected}`,
89+
pass: true,
90+
actual,
91+
expected,
92+
}
93+
: {
94+
message: () => `expected ${actual} to contain path ${expected}`,
95+
pass: false,
96+
actual,
97+
expected,
98+
};
99+
}
100+
101+
function assertPathEndWith(
102+
actual: string,
103+
expected: string,
104+
): SyncExpectationResult {
105+
const normalizedReceived = osAgnosticPath(actual);
106+
const normalizedExpected = osAgnosticPath(expected);
107+
108+
const pass = normalizedReceived.endsWith(normalizedExpected);
109+
return pass
110+
? {
111+
message: () => `expected ${actual} not to end with path ${expected}`,
112+
pass: true,
113+
actual,
114+
expected,
115+
}
116+
: {
117+
message: () => `expected ${actual} to end with path ${expected}`,
118+
pass: false,
119+
actual,
120+
expected,
121+
};
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { describe, expect, it, vi } from 'vitest';
2+
import * as testUtils from '@code-pushup/test-utils';
3+
4+
describe('path-matcher', () => {
5+
const osAgnosticPathSpy = vi.spyOn(testUtils, 'osAgnosticPath');
6+
7+
it('should provide "toMatchPath" as expect matcher', () => {
8+
const actual = String.raw`tmp\path\to\file.txt`;
9+
const expected = 'tmp/path/to/file.txt';
10+
11+
expect(actual).toMatchPath(expected);
12+
13+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
14+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
15+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
16+
});
17+
18+
it('should provide "pathToMatch" as expect matcher', () => {
19+
const actual = String.raw`tmp\path\to\file.txt`;
20+
const expected = 'tmp/path/to/file.txt';
21+
22+
expect({ path: actual }).toStrictEqual({
23+
path: expect.pathToMatch(expected),
24+
});
25+
26+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
27+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
28+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
29+
});
30+
31+
it('should provide "toStartWithPath" as expect matcher', () => {
32+
const actual = String.raw`tmp\path\to\file.txt`;
33+
const expected = 'tmp/path/to';
34+
35+
expect(actual).toStartWithPath(expected);
36+
37+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
38+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
39+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
40+
});
41+
42+
it('should provide "pathToStartWith" as expect matcher', () => {
43+
const actual = String.raw`tmp\path\to\file.txt`;
44+
const expected = 'tmp/path/to';
45+
46+
expect({ path: actual }).toStrictEqual({
47+
path: expect.pathToStartWith(expected),
48+
});
49+
50+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
51+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
52+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
53+
});
54+
55+
it('should provide "toContainPath" as expect matcher', () => {
56+
const actual = String.raw`tmp\path\to\file.txt`;
57+
const expected = 'path/to';
58+
59+
expect(actual).toContainPath(expected);
60+
61+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
62+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
63+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
64+
});
65+
66+
it('should provide "pathToContain" as expect matcher', () => {
67+
const actual = String.raw`tmp\path\to\file.txt`;
68+
const expected = 'path/to';
69+
70+
expect({ path: actual }).toStrictEqual({
71+
path: expect.pathToContain(expected),
72+
});
73+
74+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
75+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
76+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
77+
});
78+
79+
it('should provide "toEndWithPath" as expect matcher', () => {
80+
const actual = String.raw`tmp\path\to\file.txt`;
81+
const expected = 'path/to/file.txt';
82+
83+
expect(actual).toEndWithPath(expected);
84+
85+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
86+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
87+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
88+
});
89+
90+
it('should provide "pathToEndWith" as expect matcher', () => {
91+
const actual = String.raw`tmp\path\to\file.txt`;
92+
const expected = 'path/to/file.txt';
93+
94+
expect({ path: actual }).toStrictEqual({
95+
path: expect.pathToEndWith(expected),
96+
});
97+
98+
expect(osAgnosticPathSpy).toHaveBeenCalledTimes(2);
99+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(actual);
100+
expect(osAgnosticPathSpy).toHaveBeenCalledWith(expected);
101+
});
102+
});

testing/test-setup/src/vitest.d.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* eslint-disable @typescript-eslint/consistent-type-definitions */
2+
import type {
3+
CustomAsymmetricPathMatchers,
4+
CustomPathMatchers,
5+
} from './lib/extend/path.matcher.js';
6+
7+
declare module 'vitest' {
8+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
9+
interface Assertion extends CustomPathMatchers {}
10+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
11+
interface AsymmetricMatchersContaining extends CustomAsymmetricPathMatchers {}
12+
}
13+
/* eslint-enable @typescript-eslint/consistent-type-definitions */

testing/test-setup/tsconfig.json

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
"references": [
1515
{
1616
"path": "./tsconfig.lib.json"
17+
},
18+
{
19+
"path": "./tsconfig.test.json"
1720
}
1821
]
1922
}

testing/test-setup/tsconfig.lib.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@
66
"types": ["node"]
77
},
88
"include": ["src/**/*.ts"],
9-
"exclude": []
9+
"exclude": [
10+
"vite.config.unit.ts",
11+
"src/vitest.d.ts",
12+
"src/**/*.unit.test.ts",
13+
"src/**/*.integration.test.ts"
14+
]
1015
}

testing/test-setup/tsconfig.test.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "../../dist/out-tsc",
5+
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
6+
},
7+
"include": [
8+
"vite.config.unit.ts",
9+
"src/vitest.d.ts",
10+
"src/**/*.unit.test.ts",
11+
"src/**/*.d.ts",
12+
"src/**/*.integration.test.ts"
13+
]
14+
}

0 commit comments

Comments
 (0)