···176176 ],
177177})
178178179179-test('', () => {})
179179+test('works correctly')
180180```
181181+182182+#### Default fixture
183183+184184+Since Vitest 2.2, you can provide different values in different [projects](/guide/workspace). To enable this feature, pass down `{ injected: true }` to the options. If the key is not specified in the [project configuration](/config/#provide), then the default value will be used.
185185+186186+:::code-group
187187+```ts [fixtures.test.ts]
188188+import { test as base } from 'vitest'
189189+190190+const test = base.extend({
191191+ url: [
192192+ // default value if "url" is not defined in the config
193193+ 'default',
194194+ // mark the fixure as "injected" to allow the override
195195+ { injected: true },
196196+ ],
197197+})
198198+199199+test('works correctly', ({ url }) => {
200200+ // url is "/default" in "project-new"
201201+ // url is "/full" in "project-full"
202202+ // url is "/empty" in "project-empty"
203203+})
204204+```
205205+```ts [vitest.workspace.ts]
206206+import { defineWorkspace } from 'vitest/config'
207207+208208+export default defineWorkspace([
209209+ {
210210+ test: {
211211+ name: 'project-new',
212212+ },
213213+ },
214214+ {
215215+ test: {
216216+ name: 'project-full',
217217+ provide: {
218218+ url: '/full',
219219+ },
220220+ },
221221+ },
222222+ {
223223+ test: {
224224+ name: 'project-empty',
225225+ provide: {
226226+ url: '/empty',
227227+ },
228228+ },
229229+ },
230230+])
231231+```
232232+:::
181233182234#### TypeScript
183235···194246 archive: []
195247})
196248197197-myTest('', (context) => {
249249+myTest('types are defined correctly', (context) => {
198250 expectTypeOf(context.todos).toEqualTypeOf<number[]>()
199251 expectTypeOf(context.archive).toEqualTypeOf<number[]>()
200252})
···44 const testValue: string
55}
6677+const custom = it.extend({
88+ providedConfigValue: ['default value', { injected: true }],
99+})
1010+1111+custom('provided config value is injected', ({ providedConfigValue }) => {
1212+ expect(providedConfigValue).toBe(
1313+ // happy-dom provides the value in the workspace config
1414+ expect.getState().environment === 'node'
1515+ ? 'default value'
1616+ : 'actual config value',
1717+ )
1818+})
1919+720it('the same file works with different projects', () => {
821 expect(testValue).toBe(expect.getState().environment === 'node' ? 'node' : 'jsdom')
922})
+4
packages/runner/src/types/runner.ts
···148148 */
149149 importFile: (filepath: string, source: VitestRunnerImportSource) => unknown
150150 /**
151151+ * Function that is called when the runner attempts to get the value when `test.extend` is used with `{ injected: true }`
152152+ */
153153+ injectValue?: (key: string) => unknown
154154+ /**
151155 * Publicly available configuration.
152156 */
153157 config: VitestRunnerConfig
+7
packages/vitest/src/runtime/runners/test.ts
···1616import { getState, GLOBAL_EXPECT, setState } from '@vitest/expect'
1717import { getNames, getTestName, getTests } from '@vitest/runner/utils'
1818import { createExpect } from '../../integrations/chai/index'
1919+import { inject } from '../../integrations/inject'
1920import { getSnapshotClient } from '../../integrations/snapshot/chai'
2021import { vi } from '../../integrations/vi'
2122import { rpc } from '../rpc'
···87888889 onCancel(_reason: CancelReason) {
8990 this.cancelRun = true
9191+ }
9292+9393+ injectValue(key: string) {
9494+ // inject has a very limiting type controlled by ProvidedContext
9595+ // some tests override it which causes the build to fail
9696+ return (inject as any)(key)
9097 }
91989299 async onBeforeRunTask(test: Task) {