Skip to content

Commit cd0ed32

Browse files
authored
Support Vitest projects configuration for dynamic project discovery (#1171)
1 parent 07439ef commit cd0ed32

File tree

11 files changed

+130
-1
lines changed

11 files changed

+130
-1
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "@fixtures/vitest9",
3+
"workspaces": ["packages/*"],
4+
"devDependencies": {
5+
"vitest": "*"
6+
}
7+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function setup() {
2+
// E2E test setup
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { test, expect } from 'vitest';
2+
3+
test('client e2e test', () => {
4+
expect(true).toBe(true);
5+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "@fixtures/vitest9-client",
3+
"devDependencies": {
4+
"vitest": "*"
5+
}
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default {
2+
test: {
3+
name: 'client-e2e',
4+
include: ['e2e/**/*.test.ts'],
5+
setupFiles: ['./e2e-setup.ts'],
6+
environment: 'happy-dom',
7+
},
8+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Unit test file
2+
import { describe, it, expect } from 'vitest';
3+
4+
describe('example unit test', () => {
5+
it('should work', () => {
6+
expect(1 + 1).toBe(2);
7+
});
8+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function setup() {
2+
// Unit test setup
3+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export default {
2+
test: {
3+
projects: [
4+
{
5+
name: 'unit',
6+
test: {
7+
include: ['src/**/*.test.ts'],
8+
setupFiles: ['./src/unit.setup.ts'],
9+
environment: 'jsdom',
10+
},
11+
},
12+
'packages/*/vitest.config.e2e.ts',
13+
],
14+
coverage: {
15+
enabled: false,
16+
},
17+
},
18+
};

packages/knip/src/plugins/vitest/index.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { DEFAULT_EXTENSIONS } from '../../constants.js';
22
import type { IsPluginEnabled, Plugin, PluginOptions, ResolveConfig } from '../../types/config.js';
33
import type { PackageJson } from '../../types/package-json.js';
4-
import { type Input, toAlias, toDeferResolve, toDependency, toEntry } from '../../util/input.js';
4+
import { _glob } from '../../util/glob.js';
5+
import { type Input, toAlias, toConfig, toDeferResolve, toDependency, toEntry } from '../../util/input.js';
56
import { join, toPosix } from '../../util/path.js';
67
import { hasDependency } from '../../util/plugin.js';
78
import { getEnvPackageName, getExternalReporters } from './helpers.js';
@@ -50,11 +51,21 @@ const findConfigDependencies = (localConfig: ViteConfig, options: PluginOptions)
5051
}
5152
}
5253

54+
const projectsDependencies: Input[] = [];
55+
if (testConfig.projects !== undefined) {
56+
for (const projectConfig of testConfig.projects) {
57+
if (typeof projectConfig !== 'string') {
58+
projectsDependencies.push(...findConfigDependencies(projectConfig, options));
59+
}
60+
}
61+
}
62+
5363
return [
5464
...[...environments, ...reporters, ...coverage].map(id => toDependency(id)),
5565
...setupFiles,
5666
...globalSetup,
5767
...workspaceDependencies,
68+
...projectsDependencies,
5869
];
5970
};
6071

@@ -67,10 +78,24 @@ const getConfigs = async (localConfig: ViteConfigOrFn | VitestWorkspaceConfig) =
6778
for (const mode of ['development', 'production'] as MODE[]) {
6879
const cfg = await config({ command, mode, ssrBuild: undefined });
6980
configs.push(cfg);
81+
if (cfg.test?.projects) {
82+
for (const project of cfg.test.projects) {
83+
if (typeof project !== 'string') {
84+
configs.push(project);
85+
}
86+
}
87+
}
7088
}
7189
}
7290
} else {
7391
configs.push(config);
92+
if (config.test?.projects) {
93+
for (const project of config.test.projects) {
94+
if (typeof project !== 'string') {
95+
configs.push(project);
96+
}
97+
}
98+
}
7499
}
75100
}
76101
}
@@ -84,6 +109,23 @@ export const resolveConfig: ResolveConfig<ViteConfigOrFn | VitestWorkspaceConfig
84109

85110
const configs = await getConfigs(localConfig);
86111

112+
for (const cfg of configs) {
113+
if (cfg.test?.projects) {
114+
for (const project of cfg.test.projects) {
115+
if (typeof project === 'string') {
116+
const projectFiles = await _glob({
117+
cwd: options.cwd,
118+
patterns: [project],
119+
gitignore: false,
120+
});
121+
for (const projectFile of projectFiles) {
122+
inputs.add(toConfig('vitest', projectFile, { containingFilePath: options.configFilePath }));
123+
}
124+
}
125+
}
126+
}
127+
}
128+
87129
const addStar = (value: string) => (value.endsWith('*') ? value : join(value, '*').replace(/\/\*\*$/, '/*'));
88130
const addAliases = (aliasOptions: AliasOptions) => {
89131
for (const [alias, value] of Object.entries(aliasOptions)) {

packages/knip/src/plugins/vitest/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface VitestConfig {
1919
reporters?: (string | [string, unknown] | unknown)[];
2020
setupFiles?: string | string[];
2121
workspace?: (ViteConfig & { test: VitestConfig['test'] & { workspace: never } })[];
22+
projects?: (string | (ViteConfig & { test: VitestConfig['test'] & { projects: never } }))[];
2223
alias?: AliasOptions;
2324
};
2425
}

0 commit comments

Comments
 (0)