From 1497134e4bcc77e61fc73fbfc713547cc8b74ceb Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 1 Oct 2024 15:58:53 +0200 Subject: [PATCH] fix(runner): guard test hook callback (#6604) --- packages/runner/src/hooks.ts | 7 +++++++ test/cli/fixtures/fails/hooks-fail-afterAll.test.ts | 7 +++++++ test/cli/fixtures/fails/hooks-fail-afterEach.test.ts | 7 +++++++ test/cli/fixtures/fails/hooks-fail-beforeAll.test.ts | 7 +++++++ test/cli/fixtures/fails/hooks-fail-beforeEach.test.ts | 7 +++++++ test/cli/test/__snapshots__/fails.test.ts.snap | 8 ++++++++ 6 files changed, 43 insertions(+) create mode 100644 test/cli/fixtures/fails/hooks-fail-afterAll.test.ts create mode 100644 test/cli/fixtures/fails/hooks-fail-afterEach.test.ts create mode 100644 test/cli/fixtures/fails/hooks-fail-beforeAll.test.ts create mode 100644 test/cli/fixtures/fails/hooks-fail-beforeEach.test.ts diff --git a/packages/runner/src/hooks.ts b/packages/runner/src/hooks.ts index aa8ae3a82cf6..88fc0901fe1e 100644 --- a/packages/runner/src/hooks.ts +++ b/packages/runner/src/hooks.ts @@ -1,3 +1,4 @@ +import { assertTypes } from '@vitest/utils' import type { AfterAllListener, AfterEachListener, @@ -35,6 +36,7 @@ function getDefaultHookTimeout() { * ``` */ export function beforeAll(fn: BeforeAllListener, timeout?: number): void { + assertTypes(fn, '"beforeAll" callback', ['function']) return getCurrentSuite().on( 'beforeAll', withTimeout(fn, timeout ?? getDefaultHookTimeout(), true), @@ -59,6 +61,7 @@ export function beforeAll(fn: BeforeAllListener, timeout?: number): void { * ``` */ export function afterAll(fn: AfterAllListener, timeout?: number): void { + assertTypes(fn, '"afterAll" callback', ['function']) return getCurrentSuite().on( 'afterAll', withTimeout(fn, timeout ?? getDefaultHookTimeout(), true), @@ -86,6 +89,7 @@ export function beforeEach( fn: BeforeEachListener, timeout?: number, ): void { + assertTypes(fn, '"beforeEach" callback', ['function']) return getCurrentSuite().on( 'beforeEach', withTimeout(withFixtures(fn), timeout ?? getDefaultHookTimeout(), true), @@ -113,6 +117,7 @@ export function afterEach( fn: AfterEachListener, timeout?: number, ): void { + assertTypes(fn, '"afterEach" callback', ['function']) return getCurrentSuite().on( 'afterEach', withTimeout(withFixtures(fn), timeout ?? getDefaultHookTimeout(), true), @@ -183,6 +188,8 @@ function createTestHook( handler: (test: TaskPopulated, handler: T, timeout?: number) => void, ): TaskHook { return (fn: T, timeout?: number) => { + assertTypes(fn, `"${name}" callback`, ['function']) + const current = getCurrentTest() if (!current) { diff --git a/test/cli/fixtures/fails/hooks-fail-afterAll.test.ts b/test/cli/fixtures/fails/hooks-fail-afterAll.test.ts new file mode 100644 index 000000000000..3a0487894c2b --- /dev/null +++ b/test/cli/fixtures/fails/hooks-fail-afterAll.test.ts @@ -0,0 +1,7 @@ +import { describe, test, afterAll } from 'vitest'; + +describe('afterAll hooks fail', () => { + // @ts-ignore expects a function + afterAll('fail') + test.todo('todo') +}) diff --git a/test/cli/fixtures/fails/hooks-fail-afterEach.test.ts b/test/cli/fixtures/fails/hooks-fail-afterEach.test.ts new file mode 100644 index 000000000000..df0ef9e653b8 --- /dev/null +++ b/test/cli/fixtures/fails/hooks-fail-afterEach.test.ts @@ -0,0 +1,7 @@ +import { afterEach, describe, test } from 'vitest'; + +describe('afterEach hooks fail', () => { + // @ts-ignore expects a function + afterEach('fail') + test.todo('todo') +}) diff --git a/test/cli/fixtures/fails/hooks-fail-beforeAll.test.ts b/test/cli/fixtures/fails/hooks-fail-beforeAll.test.ts new file mode 100644 index 000000000000..502e936fcf9b --- /dev/null +++ b/test/cli/fixtures/fails/hooks-fail-beforeAll.test.ts @@ -0,0 +1,7 @@ +import { beforeAll, describe, test } from 'vitest'; + +describe('beforeAll hooks fail', () => { + // @ts-ignore expects a function + beforeAll('fail') + test.todo('todo') +}) diff --git a/test/cli/fixtures/fails/hooks-fail-beforeEach.test.ts b/test/cli/fixtures/fails/hooks-fail-beforeEach.test.ts new file mode 100644 index 000000000000..4858d4657ba8 --- /dev/null +++ b/test/cli/fixtures/fails/hooks-fail-beforeEach.test.ts @@ -0,0 +1,7 @@ +import { beforeEach, describe, test } from 'vitest'; + +describe('beforeEach hooks fail', () => { + // @ts-ignore expects a function + beforeEach('fail') + test.todo('todo') +}) diff --git a/test/cli/test/__snapshots__/fails.test.ts.snap b/test/cli/test/__snapshots__/fails.test.ts.snap index 391d0c063a0a..3ae6946dadf5 100644 --- a/test/cli/test/__snapshots__/fails.test.ts.snap +++ b/test/cli/test/__snapshots__/fails.test.ts.snap @@ -28,6 +28,14 @@ exports[`should fail hooks-called.test.ts > hooks-called.test.ts 1`] = ` Error: before all" `; +exports[`should fail hooks-fail-afterAll.test.ts > hooks-fail-afterAll.test.ts 1`] = `"TypeError: "afterAll" callback value must be function, received "string""`; + +exports[`should fail hooks-fail-afterEach.test.ts > hooks-fail-afterEach.test.ts 1`] = `"TypeError: "afterEach" callback value must be function, received "string""`; + +exports[`should fail hooks-fail-beforeAll.test.ts > hooks-fail-beforeAll.test.ts 1`] = `"TypeError: "beforeAll" callback value must be function, received "string""`; + +exports[`should fail hooks-fail-beforeEach.test.ts > hooks-fail-beforeEach.test.ts 1`] = `"TypeError: "beforeEach" callback value must be function, received "string""`; + exports[`should fail inline-snapshop-inside-each.test.ts > inline-snapshop-inside-each.test.ts 1`] = ` "Error: InlineSnapshot cannot be used inside of test.each or describe.each Error: InlineSnapshot cannot be used inside of test.each or describe.each