You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guide/projects.md
+48-1Lines changed: 48 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,7 +42,54 @@ export default defineConfig({
42
42
})
43
43
```
44
44
45
-
Vitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If this glob pattern matches _any file_, it will be considered a Vitest config even if it doesn't have a `vitest` in its name or has an obscure file extension.
45
+
Vitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If the glob pattern matches a file, it will validate that the name starts with `vitest.config`/`vite.config` or matches `(vite|vitest).*.config.*` pattern to ensure it's a Vitest configuration file. For example, these config files are valid:
46
+
47
+
-`vitest.config.ts`
48
+
-`vite.config.js`
49
+
-`vitest.unit.config.ts`
50
+
-`vite.e2e.config.js`
51
+
-`vitest.config.unit.js`
52
+
-`vite.config.e2e.js`
53
+
54
+
To exclude folders and files, you can use the negation pattern:
55
+
56
+
```ts [vitest.config.ts]
57
+
import { defineConfig } from'vitest/config'
58
+
59
+
exportdefaultdefineConfig({
60
+
test: {
61
+
// include all folders inside "packages" except "excluded"
62
+
projects: [
63
+
'packages/*',
64
+
'!packages/excluded'
65
+
],
66
+
},
67
+
})
68
+
```
69
+
70
+
If you have a nested structure where some folders need to be projects, but other folders have their own subfolders, you have to use brackets to avoid matching the parent folder:
71
+
72
+
```ts [vitest.config.ts]
73
+
import { defineConfig } from'vitest/config'
74
+
75
+
// For example, this will create projects:
76
+
// packages/a
77
+
// packages/b
78
+
// packages/business/c
79
+
// packages/business/d
80
+
// Notice that "packages/business" is not a project itself
81
+
82
+
exportdefaultdefineConfig({
83
+
test: {
84
+
projects: [
85
+
// matches every folder inside "packages" except "business"
86
+
'packages/!(business)',
87
+
// matches every folder inside "packages/business"
88
+
'packages/business/*',
89
+
],
90
+
},
91
+
})
92
+
```
46
93
47
94
::: warning
48
95
Vitest does not treat the root `vitest.config` file as a project unless it is explicitly specified in the configuration. Consequently, the root configuration will only influence global options such as `reporters` and `coverage`. Note that Vitest will always run certain plugin hooks, like `apply`, `config`, `configResolved` or `configureServer`, specified in the root config file. Vitest also uses the same plugins to execute global setups and custom coverage provider.
`Project name "test" from "vitest2.config.js" is not unique. The project is already defined by "vitest1.config.js".
41
+
`Project name "test" from "vitest.config.two.js" is not unique. The project is already defined by "vitest.config.one.js".
42
42
43
43
Your config matched these files:
44
-
- vitest1.config.js
45
-
- vitest2.config.js
44
+
- vitest.config.one.js
45
+
- vitest.config.two.js
46
46
47
47
All projects should have unique names. Make sure your configuration is correct.`,
48
48
)
@@ -138,3 +138,60 @@ it('fails if workspace is filtered by the project', async () => {
138
138
"./vitest.config.js"
139
139
].`)
140
140
})
141
+
142
+
describe('the config file names',()=>{
143
+
it('[glob] the name has "unit" between "vitest" and "config" and works',async()=>{
144
+
const{ exitCode }=awaitrunInlineTests({
145
+
'vitest.unit.config.js': {},
146
+
'vitest.config.js': {
147
+
test: {
148
+
passWithNoTests: true,
149
+
projects: ['./vitest.*.config.js'],
150
+
},
151
+
},
152
+
})
153
+
154
+
expect(exitCode).toBe(0)
155
+
})
156
+
157
+
it('[glob] the name does not start with "vite"/"vitest" and throws an error',async()=>{
158
+
const{ stderr }=awaitrunInlineTests({
159
+
'unit.config.js': {},
160
+
'vitest.config.js': {
161
+
test: {
162
+
projects: ['./*.config.js'],
163
+
},
164
+
},
165
+
},{},{fails: true})
166
+
167
+
expect(stderr).toContain('The projects glob matched a file "unit.config.js", but it should also either start with "vitest.config"/"vite.config" or match the pattern "(vitest|vite).*.config.*".')
168
+
})
169
+
170
+
it('[file] the name has "unit" between "vitest" and "config" and works',async()=>{
171
+
const{ exitCode }=awaitrunInlineTests({
172
+
'vitest.unit.config.js': {},
173
+
'vitest.config.js': {
174
+
test: {
175
+
passWithNoTests: true,
176
+
projects: ['./vitest.unit.config.js'],
177
+
},
178
+
},
179
+
})
180
+
181
+
expect(exitCode).toBe(0)
182
+
})
183
+
184
+
it('[file] the name does not start with "vite"/"vitest" and throws an error',async()=>{
185
+
const{ stderr }=awaitrunInlineTests({
186
+
'unit.config.js': {},
187
+
'vitest.config.js': {
188
+
test: {
189
+
passWithNoTests: true,
190
+
projects: ['./unit.config.js'],
191
+
},
192
+
},
193
+
},{},{fails: true})
194
+
195
+
expect(stderr).toContain('The file "unit.config.js" must start with "vitest.config"/"vite.config" or match the pattern "(vitest|vite).*.config.*" to be a valid project config.')
0 commit comments