Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/guide/test-tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,19 @@ You can also pass multiple `--tags-filter` flags. They are combined with AND log
# Run tests that match (unit OR e2e) AND are NOT slow
vitest --tags-filter="unit || e2e" --tags-filter="!slow"
```

### Checking Tags Filter at Runtime

You can use `TestRunner.matchesTagsFilter` (since Vitest 4.1.1) to check whether the current tags filter matches a set of tags. This is useful for conditionally running expensive setup logic only when relevant tests are included:

```ts
import { beforeAll, TestRunner } from 'vitest'

beforeAll(async () => {
if (TestRunner.matchesTagsFilter(['db'])) {
await seedDatabase()
}
})
```

The method accepts an array of tags and returns `true` if the current `--tags-filter` would include a test with those tags. If no tags filter is active, it always returns `true`.
2 changes: 2 additions & 0 deletions packages/runner/src/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export async function collectTests(
'collect_spec',
{ 'code.file.path': filepath },
async () => {
runner._currentSpecification = typeof spec === 'string' ? { filepath: spec } : spec

const testLocations = typeof spec === 'string' ? undefined : spec.testLocations
const testNamePattern = typeof spec === 'string' ? undefined : spec.testNamePattern
const testIds = typeof spec === 'string' ? undefined : spec.testIds
Expand Down
14 changes: 8 additions & 6 deletions packages/runner/src/types/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ export interface FileSpecification {
// file can be marked via a jsdoc comment to have tags,
// these are _not_ tags to filter tests by
fileTags?: string[]
testLocations: number[] | undefined
testNamePattern: RegExp | undefined
testTagsFilter: string[] | undefined
testIds: string[] | undefined
testLocations?: number[] | undefined
testNamePattern?: RegExp | undefined
testTagsFilter?: string[] | undefined
testIds?: string[] | undefined
}

export interface TestTagDefinition extends Omit<TestOptions, 'tags' | 'shuffle'> {
Expand Down Expand Up @@ -231,8 +231,10 @@ export interface VitestRunner {
// eslint-disable-next-line ts/method-signature-style
trace?<T>(name: string, attributes: Record<string, any>, cb: () => T): T

/** @private */
/** @internal */
_currentSpecification?: FileSpecification | undefined
/** @internal */
_currentTaskStartTime?: number
/** @private */
/** @internal */
_currentTaskTimeout?: number
}
2 changes: 1 addition & 1 deletion packages/runner/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export {
} from './collect'
export { limitConcurrency } from './limit-concurrency'
export { partitionSuiteChildren } from './suite'
export { createTagsFilter, validateTags } from './tags'
export { createTagsFilter, matchesTagsFilter, validateTags } from './tags'
export {
createTaskName,
getFullName,
Expand Down
17 changes: 17 additions & 0 deletions packages/runner/src/utils/tags.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
import type { TestTagDefinition, VitestRunnerConfig } from '../types/runner'
import { getRunner } from '../suite'

const filterMap = new WeakMap<string[], (testTags: string[]) => boolean>()

export function matchesTagsFilter(testTags: string[]): boolean {
const runner = getRunner()
const tagsFilter = runner._currentSpecification?.testTagsFilter ?? runner.config.tagsFilter
if (!tagsFilter) {
return true
}
let tagsFilterPredicate = filterMap.get(tagsFilter)
if (!tagsFilterPredicate) {
tagsFilterPredicate = createTagsFilter(tagsFilter, runner.config.tags)
filterMap.set(tagsFilter, tagsFilterPredicate)
}
return tagsFilterPredicate(testTags)
}

export function validateTags(config: VitestRunnerConfig, tags: string[]): void {
if (!config.strictTags) {
Expand Down
3 changes: 2 additions & 1 deletion packages/vitest/src/runtime/runners/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
getFn,
getHooks,
} from '@vitest/runner'
import { createChainable, getNames, getTestName, getTests } from '@vitest/runner/utils'
import { createChainable, getNames, getTestName, getTests, matchesTagsFilter } from '@vitest/runner/utils'
import { processError } from '@vitest/utils/error'
import { normalize } from 'pathe'
import { createExpect } from '../../integrations/chai/index'
Expand Down Expand Up @@ -278,6 +278,7 @@ export class TestRunner implements VitestTestRunner {
static getTestFn: typeof getFn = getFn
static setSuiteHooks: typeof getHooks = getHooks
static setTestFn: typeof getFn = getFn
static matchesTagsFilter: typeof matchesTagsFilter = matchesTagsFilter

/**
* @deprecated
Expand Down
Loading
Loading