Skip to content

Commit

Permalink
feat(vitest): add "provide" option (#6253)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va authored Aug 9, 2024
1 parent 00dfc1a commit 4409d77
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 4 deletions.
52 changes: 49 additions & 3 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,54 @@ afterEach(() => {
globalThis.resetBeforeEachTest = true
```

### provide <Version>2.1.0</Version> {#provide}

- **Type:** `Partial<ProvidedContext>`

Define values that can be accessed inside your tests using `inject` method.

:::code-group
```ts [vitest.config.js]
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
provide: {
API_KEY: '123',
},
},
})
```
```ts [my.test.js]
import { expect, inject, test } from 'vitest'

test('api key is defined', () => {
expect(inject('API_KEY')).toBe('123')
})
```
:::

::: warning
Properties have to be strings and values need to be [serializable](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types) because this object will be transferred between different processes.
:::

::: tip
If you are using TypeScript, you will need to augment `ProvidedContext` type for type safe access:

```ts
// vitest.shims.d.ts

declare module 'vitest' {
export interface ProvidedContext {
API_KEY: string
}
}

// mark this file as a module so augmentation works correctly
export {}
```
:::

### globalSetup

- **Type:** `string | string[]`
Expand All @@ -1018,7 +1066,7 @@ Multiple globalSetup files are possible. setup and teardown are executed sequent
::: warning
Global setup runs only if there is at least one running test. This means that global setup might start running during watch mode after test file is changed (the test file will wait for global setup to finish before running).

Beware that the global setup is running in a different global scope, so your tests don't have access to variables defined here. However, you can pass down serializable data to tests via `provide` method:
Beware that the global setup is running in a different global scope, so your tests don't have access to variables defined here. However, you can pass down serializable data to tests via [`provide`](#provide) method:

:::code-group
```js [globalSetup.js]
Expand All @@ -1033,8 +1081,6 @@ export default function setup({ provide }: GlobalSetupContext) {
provide('wsPort', 3000)
}

// You can also extend `ProvidedContext` type
// to have type safe access to `provide/inject` methods:
declare module 'vitest' {
export interface ProvidedContext {
wsPort: number
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/node/cli/cli-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ export const cliOptionsConfig: VitestCLIOptions = {
compare: null,
outputJson: null,
json: null,
provide: null,
}

export const benchCliOptionsConfig: Pick<
Expand Down
2 changes: 2 additions & 0 deletions packages/vitest/src/node/config/resolveConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ export function resolveConfig(
mode,
} as any as ResolvedConfig

resolved.provide ??= {}

const inspector = resolved.inspect || resolved.inspectBrk

resolved.inspector = {
Expand Down
23 changes: 22 additions & 1 deletion packages/vitest/src/node/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
} from '../reporters'
import type { TestSequencerConstructor } from '../sequencers/types'
import type { ChaiConfig } from '../../integrations/chai/config'
import type { Arrayable, ErrorWithDiff, ParsedStack } from '../../types/general'
import type { Arrayable, ErrorWithDiff, ParsedStack, ProvidedContext } from '../../types/general'
import type { JSDOMOptions } from '../../types/jsdom-options'
import type { HappyDOMOptions } from '../../types/happy-dom-options'
import type { EnvironmentOptions } from '../../types/environment'
Expand Down Expand Up @@ -731,6 +731,27 @@ export interface InlineConfig {
waitForDebugger?: boolean
}

/**
* Define variables that will be returned from `inject` in the test environment.
* @example
* ```ts
* // vitest.config.ts
* export default defineConfig({
* test: {
* provide: {
* someKey: 'someValue'
* }
* }
* })
* ```
* ```ts
* // test file
* import { inject } from 'vitest'
* const value = inject('someKey') // 'someValue'
* ```
*/
provide?: Partial<ProvidedContext>

/**
* Configuration options for expect() matches.
*/
Expand Down
17 changes: 17 additions & 0 deletions packages/vitest/src/node/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,14 @@ export class WorkspaceProject {
project.server = ctx.server
project.runner = ctx.runner
project.config = ctx.config
for (const _providedKey in ctx.config.provide) {
const providedKey = _providedKey as keyof ProvidedContext
// type is very strict here, so we cast it to any
(project.provide as (key: string, value: unknown) => void)(
providedKey,
ctx.config.provide[providedKey],
)
}
project.testProject = new TestProject(project)
return project
}
Expand All @@ -384,6 +392,15 @@ export class WorkspaceProject {
server.config,
this.ctx.logger,
)
for (const _providedKey in this.config.provide) {
const providedKey = _providedKey as keyof ProvidedContext
// type is very strict here, so we cast it to any
(this.provide as (key: string, value: unknown) => void)(
providedKey,
this.config.provide[providedKey],
)
}

this.testProject = new TestProject(this)

this.server = server
Expand Down
2 changes: 2 additions & 0 deletions test/workspaces/globalTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ declare module 'vitest' {
globalSetup: boolean
globalSetupOverriden: boolean
invalidValue: unknown
projectConfigValue: boolean
globalConfigValue: boolean
}
}

Expand Down
2 changes: 2 additions & 0 deletions test/workspaces/space_3/global-provide.space-3-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ import { expect, inject, test } from 'vitest'
test('global setup provides data correctly', () => {
expect(inject('globalSetup')).toBe(true)
expect(inject('globalSetupOverriden')).toBe(true)
expect(inject('projectConfigValue')).toBe(true)
expect(inject('globalConfigValue')).toBe(true)
expect(inject('invalidValue')).toBe(undefined)
})
3 changes: 3 additions & 0 deletions test/workspaces/space_3/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ export default defineProject({
include: ['**/*.space-3-test.ts'],
environment: 'node',
globalSetup: './localSetup.ts',
provide: {
projectConfigValue: true,
},
},
})
3 changes: 3 additions & 0 deletions test/workspaces/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ export default defineConfig({
CONFIG_VAR: 'root',
CONFIG_OVERRIDE: 'root',
},
provide: {
globalConfigValue: true,
},
},
})

0 comments on commit 4409d77

Please sign in to comment.