[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

feat: allow a custom note when calling `ctx.skip()` dynamically (#6805)

authored by

Vladimir and committed by
GitHub
(Nov 13, 2024, 5:03 PM +0100) 697c35c5 8d179afc

+71 -11
+2 -2
packages/runner/src/context.ts
··· 67 67 68 68 context.task = test 69 69 70 - context.skip = () => { 70 + context.skip = (note?: string) => { 71 71 test.pending = true 72 - throw new PendingError('test is skipped; abort execution', test) 72 + throw new PendingError('test is skipped; abort execution', test, note) 73 73 } 74 74 75 75 context.onTestFailed = (fn) => {
+1 -1
packages/runner/src/errors.ts
··· 4 4 public code = 'VITEST_PENDING' 5 5 public taskId: string 6 6 7 - constructor(public message: string, task: TaskBase) { 7 + constructor(public message: string, task: TaskBase, public note: string | undefined) { 8 8 super(message) 9 9 this.taskId = task.id 10 10 }
+2 -1
packages/runner/src/run.ts
··· 257 257 // skipped with new PendingError 258 258 if (test.pending || test.result?.state === 'skip') { 259 259 test.mode = 'skip' 260 - test.result = { state: 'skip' } 260 + test.result = { state: 'skip', note: test.result?.note } 261 261 updateTask(test, runner) 262 262 setCurrentTest(undefined) 263 263 return ··· 336 336 function failTask(result: TaskResult, err: unknown, diffOptions: DiffOptions | undefined) { 337 337 if (err instanceof PendingError) { 338 338 result.state = 'skip' 339 + result.note = err.note 339 340 return 340 341 } 341 342
+30
test/cli/test/skip-note.test.ts
··· 1 + import type { TestCase } from 'vitest/node' 2 + import { resolve } from 'node:path' 3 + import { expect, test } from 'vitest' 4 + import { runVitest } from '../../test-utils' 5 + 6 + const root = resolve(import.meta.dirname, '../fixtures/skip-note') 7 + 8 + test.for([ 9 + { reporter: 'default', isTTY: true }, 10 + { reporter: 'verbose', isTTY: false }, 11 + ])('can leave a note when skipping in the $reporter reporter', async ({ reporter, isTTY }) => { 12 + const { ctx, stdout, stderr } = await runVitest({ 13 + root, 14 + reporters: [ 15 + [reporter, { isTTY }], 16 + ], 17 + }) 18 + 19 + expect(stderr).toBe('') 20 + expect(stdout).toContain('my skipped test [custom message]') 21 + 22 + expect(ctx).toBeDefined() 23 + const testTask = ctx!.state.getFiles()[0].tasks[0] 24 + const test = ctx!.state.getReportedEntity(testTask) as TestCase 25 + const result = test.result() 26 + expect(result).toEqual({ 27 + state: 'skipped', 28 + note: 'custom message', 29 + }) 30 + })
+3 -1
packages/runner/src/types/tasks.ts
··· 147 147 * `repeats` option is set. This number also contains `retryCount`. 148 148 */ 149 149 repeatCount?: number 150 + /** @private */ 151 + note?: string 150 152 } 151 153 152 154 /** ··· 611 613 * Mark tests as skipped. All execution after this call will be skipped. 612 614 * This function throws an error, so make sure you are not catching it accidentally. 613 615 */ 614 - skip: () => void 616 + skip: (note?: string) => void 615 617 } 616 618 617 619 export type ExtendedContext<T extends Custom | Test> = TaskContext<T> &
+1
packages/vitest/src/node/state.ts
··· 40 40 task.mode = 'skip' 41 41 task.result ??= { state: 'skip' } 42 42 task.result.state = 'skip' 43 + task.result.note = _err.note 43 44 } 44 45 return 45 46 }
+5
test/cli/fixtures/skip-note/basic.test.ts
··· 1 + import { test } from 'vitest'; 2 + 3 + test('my skipped test', ctx => { 4 + ctx.skip('custom message') 5 + })
+22 -5
packages/vitest/src/node/reporters/reported-tasks.ts
··· 119 119 return undefined 120 120 } 121 121 const state = result.state === 'fail' 122 - ? 'failed' 122 + ? 'failed' as const 123 123 : result.state === 'pass' 124 - ? 'passed' 125 - : 'skipped' 124 + ? 'passed' as const 125 + : 'skipped' as const 126 + if (state === 'skipped') { 127 + return { 128 + state, 129 + note: result.note, 130 + errors: undefined, 131 + } satisfies TestResultSkipped 132 + } 133 + if (state === 'passed') { 134 + return { 135 + state, 136 + errors: result.errors as TestError[] | undefined, 137 + } satisfies TestResultPassed 138 + } 126 139 return { 127 140 state, 128 - errors: result.errors as TestError[] | undefined, 129 - } as TestResult 141 + errors: (result.errors || []) as TestError[], 142 + } satisfies TestResultFailed 130 143 } 131 144 132 145 /** ··· 441 454 * Skipped tests have no errors. 442 455 */ 443 456 errors: undefined 457 + /** 458 + * A custom note. 459 + */ 460 + note: string | undefined 444 461 } 445 462 446 463 export interface TestDiagnostic {
+3
packages/vitest/src/node/reporters/verbose.ts
··· 43 43 ` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`, 44 44 ) 45 45 } 46 + if (task.result?.note) { 47 + title += c.dim(c.gray(` [${task.result.note}]`)) 48 + } 46 49 this.ctx.logger.log(title) 47 50 if (task.result.state === 'fail') { 48 51 task.result.errors?.forEach((error) => {
+2 -1
packages/vitest/src/node/reporters/renderers/listRenderer.ts
··· 144 144 } 145 145 146 146 if (task.mode === 'skip' || task.mode === 'todo') { 147 - suffix += ` ${c.dim(c.gray('[skipped]'))}` 147 + const note = task.result?.note || 'skipped' 148 + suffix += ` ${c.dim(c.gray(`[${note}]`))}` 148 149 } 149 150 150 151 if (