|
1 | | -import { format, isNegativeNaN, isObject, objDisplay, objectAttr } from '@vitest/utils' |
| 1 | +import { format, isNegativeNaN, isObject, objDisplay, objectAttr, toArray } from '@vitest/utils' |
2 | 2 | import { parseSingleStack } from '@vitest/utils/source-map' |
3 | 3 | import type { Custom, CustomAPI, File, Fixtures, RunMode, Suite, SuiteAPI, SuiteCollector, SuiteFactory, SuiteHooks, Task, TaskCustomOptions, Test, TestAPI, TestFunction, TestOptions } from './types' |
4 | 4 | import type { VitestRunner } from './types/runner' |
@@ -383,6 +383,36 @@ export function createTaskCollector( |
383 | 383 | } |
384 | 384 | } |
385 | 385 |
|
| 386 | + taskFn.for = function <T>( |
| 387 | + this: { |
| 388 | + withContext: () => SuiteAPI |
| 389 | + setContext: (key: string, value: boolean | undefined) => SuiteAPI |
| 390 | + }, |
| 391 | + cases: ReadonlyArray<T>, |
| 392 | + ...args: any[] |
| 393 | + ) { |
| 394 | + const test = this.withContext() |
| 395 | + |
| 396 | + if (Array.isArray(cases) && args.length) |
| 397 | + cases = formatTemplateString(cases, args) |
| 398 | + |
| 399 | + return ( |
| 400 | + name: string | Function, |
| 401 | + optionsOrFn: ((...args: T[]) => void) | TestOptions, |
| 402 | + fnOrOptions?: ((...args: T[]) => void) | number | TestOptions, |
| 403 | + ) => { |
| 404 | + const _name = formatName(name) |
| 405 | + const { options, handler } = parseArguments(optionsOrFn, fnOrOptions) |
| 406 | + cases.forEach((item, idx) => { |
| 407 | + // monkey-patch handler to allow parsing fixture |
| 408 | + const handlerWrapper = (ctx: any) => handler(item, ctx); |
| 409 | + (handlerWrapper as any).__VITEST_FIXTURE_INDEX__ = 1; |
| 410 | + (handlerWrapper as any).toString = () => handler.toString() |
| 411 | + test(formatTitle(_name, toArray(item), idx), options, handlerWrapper) |
| 412 | + }) |
| 413 | + } |
| 414 | + } |
| 415 | + |
386 | 416 | taskFn.skipIf = function (this: TestAPI, condition: any) { |
387 | 417 | return condition ? this.skip : this |
388 | 418 | } |
|
0 commit comments