Skip to content

Commit 6ce8102

Browse files
9aoyCopilot
andauthored
feat!: merge exclude values by default (#588)
Co-authored-by: Copilot <[email protected]>
1 parent 3b4c84f commit 6ce8102

File tree

12 files changed

+366
-42
lines changed

12 files changed

+366
-42
lines changed

e2e/exclude/fixtures/index.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { describe, expect, it } from '@rstest/core';
2+
3+
describe('test a', () => {
4+
it('test a-1', () => {
5+
expect(1 + 1).toBe(2);
6+
});
7+
});
8+
9+
it('test a-2', () => {
10+
expect(2 - 1).toBe(1);
11+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { defineConfig } from '@rstest/core';
2+
3+
export default defineConfig({
4+
exclude: { patterns: ['**/aaa/**'], override: true },
5+
});

e2e/exclude/index.test.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import fs from 'node:fs';
2+
import { dirname, join } from 'node:path';
3+
import { fileURLToPath } from 'node:url';
4+
import { beforeAll, describe, it } from '@rstest/core';
5+
import { runRstestCli } from '../scripts';
6+
7+
const __filename = fileURLToPath(import.meta.url);
8+
const __dirname = dirname(__filename);
9+
10+
describe('test exclude option', () => {
11+
beforeAll(() => {
12+
const distPath = join(__dirname, 'fixtures', 'dist');
13+
fs.mkdirSync(distPath, { recursive: true });
14+
const fileName = 'index.test.ts';
15+
16+
fs.writeFileSync(
17+
join(distPath, fileName),
18+
`
19+
import { expect, it } from '@rstest/core';
20+
it('should add two numbers correctly', () => {
21+
expect(1 + 1).toBe(3);
22+
});
23+
`,
24+
);
25+
});
26+
27+
it('should exclude dist by default', async () => {
28+
const { expectLog, expectExecSuccess } = await runRstestCli({
29+
command: 'rstest',
30+
args: ['run'],
31+
options: {
32+
nodeOptions: {
33+
cwd: join(__dirname, 'fixtures'),
34+
},
35+
},
36+
});
37+
38+
await expectExecSuccess();
39+
40+
expectLog('Test Files 1 passed');
41+
});
42+
43+
it('should exclude dist correctly with custom exclude', async () => {
44+
const { expectLog, expectExecSuccess } = await runRstestCli({
45+
command: 'rstest',
46+
args: ['run', '--exclude', '**/aaa/**'],
47+
options: {
48+
nodeOptions: {
49+
cwd: join(__dirname, 'fixtures'),
50+
},
51+
},
52+
});
53+
54+
await expectExecSuccess();
55+
56+
expectLog('Test Files 1 passed');
57+
});
58+
59+
it('should not exclude dist when override is true', async () => {
60+
const { expectLog, expectExecFailed } = await runRstestCli({
61+
command: 'rstest',
62+
args: ['run', '-c', 'rstest.override.config.ts'],
63+
options: {
64+
nodeOptions: {
65+
cwd: join(__dirname, 'fixtures'),
66+
},
67+
},
68+
});
69+
70+
await expectExecFailed();
71+
72+
expectLog('Test Files 1 failed | 1 passed (2)');
73+
});
74+
});

packages/core/src/config.ts

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,48 @@ export async function loadConfig({
7676
return { content: content as RstestConfig, filePath: configFilePath };
7777
}
7878

79-
export const mergeRstestConfig = (...configs: RstestConfig[]): RstestConfig =>
80-
mergeRsbuildConfig<RstestConfig>(...configs);
79+
export const mergeRstestConfig = (...configs: RstestConfig[]): RstestConfig => {
80+
return configs.reduce<RstestConfig>((result, config) => {
81+
const merged = mergeRsbuildConfig(result, {
82+
...config,
83+
exclude: Array.isArray(config.exclude)
84+
? {
85+
patterns: config.exclude,
86+
override: false,
87+
}
88+
: config.exclude,
89+
});
90+
91+
if (!Array.isArray(config.exclude) && config.exclude?.override) {
92+
merged.exclude = {
93+
patterns: config.exclude.patterns,
94+
};
95+
}
96+
97+
// The following configurations need overrides
98+
merged.include = config.include ?? merged.include;
99+
merged.reporters = config.reporters ?? merged.reporters;
100+
if (merged.coverage) {
101+
merged.coverage.reporters =
102+
config.coverage?.reporters ?? merged.coverage?.reporters;
103+
}
104+
105+
return merged;
106+
}, {});
107+
};
81108

82109
const createDefaultConfig = (): NormalizedConfig => ({
83110
root: process.cwd(),
84111
name: 'rstest',
85112
include: ['**/*.{test,spec}.?(c|m)[jt]s?(x)'],
86-
exclude: [
87-
'**/node_modules/**',
88-
'**/dist/**',
89-
'**/.{idea,git,cache,output,temp}/**',
90-
],
113+
exclude: {
114+
patterns: [
115+
'**/node_modules/**',
116+
'**/dist/**',
117+
'**/.{idea,git,cache,output,temp}/**',
118+
],
119+
override: false,
120+
},
91121
setupFiles: [],
92122
includeSource: [],
93123
pool: {
@@ -145,15 +175,9 @@ export const withDefaultConfig = (config: RstestConfig): NormalizedConfig => {
145175
) as NormalizedConfig;
146176

147177
merged.setupFiles = castArray(merged.setupFiles);
148-
// The following configurations need overrides
149-
merged.include = config.include || merged.include;
150-
merged.exclude = (config.exclude || merged.exclude || []).concat([
151-
TEMP_RSTEST_OUTPUT_DIR_GLOB,
152-
]);
153-
merged.reporters = config.reporters ?? merged.reporters;
154-
155-
merged.coverage.reporters =
156-
config.coverage?.reporters ?? merged.coverage?.reporters;
178+
179+
merged.exclude.patterns.push(TEMP_RSTEST_OUTPUT_DIR_GLOB);
180+
157181
const reportsDirectory = formatRootStr(
158182
merged.coverage.reportsDirectory,
159183
merged.root,
@@ -172,7 +196,12 @@ export const withDefaultConfig = (config: RstestConfig): NormalizedConfig => {
172196
return {
173197
...merged,
174198
include: merged.include.map((p) => formatRootStr(p, merged.root)),
175-
exclude: merged.exclude.map((p) => formatRootStr(p, merged.root)),
199+
exclude: {
200+
...merged.exclude,
201+
patterns: merged.exclude.patterns.map((p) =>
202+
formatRootStr(p, merged.root),
203+
),
204+
},
176205
setupFiles: merged.setupFiles.map((p) => formatRootStr(p, merged.root)),
177206
includeSource: merged.includeSource.map((p) =>
178207
formatRootStr(p, merged.root),

packages/core/src/core/listTests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export async function listTests(
3232

3333
const entries = await getTestEntries({
3434
include,
35-
exclude,
35+
exclude: exclude.patterns,
3636
rootPath,
3737
projectRoot: root,
3838
fileFilters: context.fileFilters || [],

packages/core/src/core/runTests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export async function runTests(context: Rstest): Promise<void> {
3131
)!.normalizedConfig;
3232
const entries = await getTestEntries({
3333
include,
34-
exclude,
34+
exclude: exclude.patterns,
3535
includeSource,
3636
rootPath,
3737
projectRoot: root,
@@ -244,7 +244,7 @@ export async function runTests(context: Rstest): Promise<void> {
244244
);
245245
logger.log(
246246
color.gray('exclude:'),
247-
p.normalizedConfig.exclude.join(color.gray(', ')),
247+
p.normalizedConfig.exclude.patterns.join(color.gray(', ')),
248248
);
249249
});
250250
}

packages/core/src/types/config.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,16 @@ export interface RstestConfig {
5959
*
6060
* @default ['**\/node_modules/**', '**\/dist/**']
6161
*/
62-
exclude?: string[];
62+
exclude?:
63+
| string[]
64+
| {
65+
patterns: string[];
66+
/**
67+
* override default exclude patterns
68+
* @default false
69+
*/
70+
override?: boolean;
71+
};
6372
/**
6473
* A list of glob patterns that match your in-source test files
6574
*
@@ -248,14 +257,18 @@ type OptionalKeys =
248257
export type NormalizedConfig = Required<
249258
Omit<
250259
RstestConfig,
251-
OptionalKeys | 'pool' | 'projects' | 'coverage' | 'setupFiles'
260+
OptionalKeys | 'pool' | 'projects' | 'coverage' | 'setupFiles' | 'exclude'
252261
>
253262
> & {
254263
[key in OptionalKeys]?: RstestConfig[key];
255264
} & {
256265
pool: RstestPoolOptions;
257266
coverage: NormalizedCoverageOptions;
258267
setupFiles: string[];
268+
exclude: {
269+
patterns: string[];
270+
override?: boolean;
271+
};
259272
};
260273

261274
export type NormalizedProjectConfig = Required<
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Rstest Snapshot v1
2+
3+
exports[`mergeRstestConfig > should merge config correctly with default config 1`] = `
4+
{
5+
"clearMocks": false,
6+
"coverage": {
7+
"clean": true,
8+
"enabled": false,
9+
"exclude": [
10+
"**/node_modules/**",
11+
"**/[.]*",
12+
"**/dist/**",
13+
"**/test/**",
14+
"**/__tests__/**",
15+
"**/__mocks__/**",
16+
"**/*.d.ts",
17+
"**/*.{test,spec}.[jt]s",
18+
"**/*.{test,spec}.[c|m][jt]s",
19+
"**/*.{test,spec}.[jt]sx",
20+
"**/*.{test,spec}.[c|m][jt]sx",
21+
],
22+
"provider": "istanbul",
23+
"reporters": [
24+
"text",
25+
"html",
26+
"clover",
27+
"json",
28+
],
29+
"reportsDirectory": "<ROOT>/packages/core/tests/coverage",
30+
},
31+
"disableConsoleIntercept": false,
32+
"exclude": {
33+
"override": false,
34+
"patterns": [
35+
"**/node_modules/**",
36+
"**/dist/**",
37+
"**/.{idea,git,cache,output,temp}/**",
38+
"**/aa/**",
39+
"**/dist/.rstest-temp",
40+
],
41+
},
42+
"globals": false,
43+
"hookTimeout": 10000,
44+
"include": [
45+
"tests/**/*.test.ts",
46+
],
47+
"includeSource": [],
48+
"isolate": true,
49+
"maxConcurrency": 5,
50+
"name": "rstest",
51+
"passWithNoTests": false,
52+
"pool": {
53+
"type": "forks",
54+
},
55+
"printConsoleTrace": false,
56+
"reporters": [
57+
"verbose",
58+
],
59+
"resetMocks": false,
60+
"restoreMocks": false,
61+
"retry": 0,
62+
"root": "<ROOT>/packages/core/tests",
63+
"setupFiles": [
64+
"./setup.ts",
65+
],
66+
"slowTestThreshold": 300,
67+
"testEnvironment": "node",
68+
"testTimeout": 5000,
69+
"unstubEnvs": false,
70+
"unstubGlobals": false,
71+
"update": false,
72+
}
73+
`;

packages/core/tests/config.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { mergeRstestConfig, withDefaultConfig } from '../src/config';
2+
3+
describe('mergeRstestConfig', () => {
4+
it('should merge config correctly with default config', () => {
5+
const merged = withDefaultConfig({
6+
include: ['tests/**/*.test.ts'],
7+
root: __dirname,
8+
exclude: ['**/aa/**'],
9+
setupFiles: ['./setup.ts'],
10+
reporters: ['verbose'],
11+
});
12+
13+
expect(merged).toMatchSnapshot();
14+
});
15+
16+
it('should merge exclude correctly', () => {
17+
expect(
18+
mergeRstestConfig(
19+
{
20+
exclude: ['**/node_modules/**'],
21+
},
22+
{
23+
exclude: {
24+
patterns: ['**/dist/**'],
25+
override: true,
26+
},
27+
},
28+
),
29+
).toEqual({
30+
exclude: {
31+
patterns: ['**/dist/**'],
32+
},
33+
});
34+
35+
expect(
36+
mergeRstestConfig(
37+
{
38+
exclude: ['**/node_modules/**'],
39+
},
40+
{
41+
exclude: {
42+
patterns: ['**/dist/**'],
43+
override: false,
44+
},
45+
},
46+
),
47+
).toEqual({
48+
exclude: {
49+
patterns: ['**/node_modules/**', '**/dist/**'],
50+
override: false,
51+
},
52+
});
53+
54+
expect(
55+
mergeRstestConfig(
56+
{
57+
exclude: {
58+
patterns: ['**/dist/**'],
59+
override: false,
60+
},
61+
},
62+
{
63+
exclude: ['**/node_modules/**'],
64+
},
65+
{
66+
exclude: {
67+
patterns: ['**/aa/**'],
68+
override: true,
69+
},
70+
},
71+
),
72+
).toEqual({
73+
exclude: {
74+
patterns: ['**/aa/**'],
75+
},
76+
});
77+
});
78+
});

0 commit comments

Comments
 (0)