From 4210c391223e960f5b54c1417f68c3307b55adc6 Mon Sep 17 00:00:00 2001 From: Dewey Ou Date: Sat, 26 Mar 2022 20:12:06 +0800 Subject: [PATCH] feat: add parameter for test name of each (#1031) * feat: add parameter for test name of each api * fix: each test name escaped case * fix: add a judgment --- docs/api/index.md | 43 +++++++++++++++++----------- packages/vitest/src/runtime/suite.ts | 18 ++++++++---- test/core/test/each.test.ts | 8 ++++++ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/docs/api/index.md b/docs/api/index.md index f0e8f4e19a7f..138771b75b53 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -121,22 +121,33 @@ For compatibility with Jest, `TestFunction` can also be of type `(done: DoneCall - **Type:** `(cases: ReadonlyArray) => void` - **Alias:** `it.each` -Use `test.each` when you need to run the same test with different variables. -You can use `%i` or `%s` in the test name in the order of the test function parameters. -```ts -test.each([ - [1, 1, 2], - [1, 2, 3], - [2, 1, 3], -])('add(%i, %i) -> %i', (a, b, expected) => { - expect(a + b).toBe(expected) -}) - -// this will return -// √ add(1, 1) -> 2 -// √ add(1, 2) -> 3 -// √ add(2, 1) -> 3 -``` + Use `test.each` when you need to run the same test with different variables. + You can inject parameters with [printf formmatting](https://nodejs.org/api/util.html#util_util_format_format_args) in the test name in the order of the test function parameters. + + - `%s`: string + - `%d`: number + - `%i`: integer + - `%f`: floating point value + - `%j`: json + - `$o`: object + - `%#`: index of the test case + - `%%`: single precent sign ('%') + + ```ts + test.each([ + [1, 1, 2], + [1, 2, 3], + [2, 1, 3], + ])('add(%i, %i) -> %i', (a, b, expected) => { + expect(a + b).toBe(expected) + }) + + // this will return + // √ add(1, 1) -> 2 + // √ add(1, 2) -> 3 + // √ add(2, 1) -> 3 + ``` + ## describe When you use `test` in the top level of file, they are collected as part of the implicit suite for it. Using `describe` you can define a new suite in the current context, as a set of related tests and other nested suites. A suite lets you organize your tests so reports are more clear. diff --git a/packages/vitest/src/runtime/suite.ts b/packages/vitest/src/runtime/suite.ts index 6cb3ddc08394..835d4bebbccc 100644 --- a/packages/vitest/src/runtime/suite.ts +++ b/packages/vitest/src/runtime/suite.ts @@ -14,7 +14,15 @@ export const test = createTest( }, ) -function formatTitle(template: string, items: any[]) { +function formatTitle(template: string, items: any[], idx: number) { + if (template.includes('%#')) { + // '%#' match index of the test case + template = template + .replace(/%%/g, '__vitest_escaped_%__') + .replace(/%#/g, `${idx}`) + .replace(/__vitest_escaped_%__/g, '%%') + } + const count = template.split('%').length - 1 let formatted = format(template, ...items.slice(0, count)) if (isObject(items[0])) { @@ -146,9 +154,9 @@ function createSuite() { suite.each = (cases: ReadonlyArray) => { return (name: string, fn: (...args: T[]) => void) => { - cases.forEach((i) => { + cases.forEach((i, idx) => { const items = toArray(i) as any - suite(formatTitle(name, items), () => fn(...items)) + suite(formatTitle(name, items, idx), () => fn(...items)) }) } } @@ -164,9 +172,9 @@ function createTest(fn: ((this: Record<'concurrent'| 'skip'| 'only'| 'todo'| 'fa test.each = (cases: ReadonlyArray) => { return (name: string, fn: (...args: T[]) => void) => { - cases.forEach((i) => { + cases.forEach((i, idx) => { const items = toArray(i) as any - test(formatTitle(name, items), () => fn(...items)) + test(formatTitle(name, items, idx), () => fn(...items)) }) } } diff --git a/test/core/test/each.test.ts b/test/core/test/each.test.ts index 1d659760d5d8..2da40bf5b7b7 100644 --- a/test/core/test/each.test.ts +++ b/test/core/test/each.test.ts @@ -75,3 +75,11 @@ describe.each([1, 2, 0])('%s (describe.each 1d)', (num) => { expect(typeof num).toEqual('number') }) }) + +test.each([ + [1, 1, 2], + [1, 2, 3], + [2, 1, 3], +])('the index of the test case is %#', (a, b, expected) => { + expect(a + b).toBe(expected) +})