From f6bb50c8ee05d1e51851960546ee650607bf6a41 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Mon, 15 Jul 2024 23:57:45 +0900 Subject: [PATCH 01/10] fix: add return type and promisable mockFactory --- packages/vitest/src/integrations/vi.ts | 6 +++++- packages/vitest/src/types/mocker.ts | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 3c6296b49b9a..0d853b5608c7 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -3,7 +3,7 @@ import { assertTypes, createSimpleStackTrace } from '@vitest/utils' import { parseSingleStack } from '../utils/source-map' import type { VitestMocker } from '../runtime/mocker' import type { ResolvedConfig, RuntimeConfig } from '../types' -import type { MockFactoryWithHelper } from '../types/mocker' +import type { MockFactoryWithHelper, PromiseMockFactoryWithHelper } from '../types/mocker' import { getWorkerState } from '../utils/global' import { resetModules, waitForImportsToResolve } from '../utils/modules' import { isChildProcess } from '../utils/base' @@ -194,6 +194,8 @@ export interface VitestUtils { mock(path: string, factory?: MockFactoryWithHelper): void // eslint-disable-next-line ts/method-signature-style mock(module: Promise, factory?: MockFactoryWithHelper): void + // eslint-disable-next-line ts/method-signature-style + mock(module: Promise, factory?: PromiseMockFactoryWithHelper): void /** * Removes module from mocked registry. All calls to import will return the original module even if it was mocked before. @@ -219,6 +221,8 @@ export interface VitestUtils { doMock(path: string, factory?: MockFactoryWithHelper): void // eslint-disable-next-line ts/method-signature-style doMock(module: Promise, factory?: MockFactoryWithHelper): void + // eslint-disable-next-line ts/method-signature-style + doMock(module: Promise, factory?: PromiseMockFactoryWithHelper): void /** * Removes module from mocked registry. All subsequent calls to import will return original module. * diff --git a/packages/vitest/src/types/mocker.ts b/packages/vitest/src/types/mocker.ts index fc64b140e85e..cb2fb090dc32 100644 --- a/packages/vitest/src/types/mocker.ts +++ b/packages/vitest/src/types/mocker.ts @@ -1,6 +1,9 @@ export type MockFactoryWithHelper = ( - importOriginal: () => Promise -) => any + importOriginal: () => Promise +) => Partial> +export type PromiseMockFactoryWithHelper = ( + importOriginal: () => Promise +) => Promise>> export type MockFactory = () => any export type MockMap = Map> From 01332f428a9db95c1b148885f412a7418f7e0a06 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Tue, 16 Jul 2024 00:27:29 +0900 Subject: [PATCH 02/10] fix: remove importOriginal generic because of type error --- packages/vitest/src/types/mocker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vitest/src/types/mocker.ts b/packages/vitest/src/types/mocker.ts index cb2fb090dc32..5d0e8986b199 100644 --- a/packages/vitest/src/types/mocker.ts +++ b/packages/vitest/src/types/mocker.ts @@ -1,8 +1,8 @@ export type MockFactoryWithHelper = ( - importOriginal: () => Promise + importOriginal: () => Promise ) => Partial> export type PromiseMockFactoryWithHelper = ( - importOriginal: () => Promise + importOriginal: () => Promise ) => Promise>> export type MockFactory = () => any From e441e4a01794acd695d4ba45eb5aac9612d71b92 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Tue, 16 Jul 2024 00:59:33 +0900 Subject: [PATCH 03/10] fix: remove partial --- packages/vitest/src/types/mocker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vitest/src/types/mocker.ts b/packages/vitest/src/types/mocker.ts index 5d0e8986b199..31b97a0c03df 100644 --- a/packages/vitest/src/types/mocker.ts +++ b/packages/vitest/src/types/mocker.ts @@ -1,9 +1,9 @@ export type MockFactoryWithHelper = ( - importOriginal: () => Promise -) => Partial> + importOriginal: () => Promise +) => Record | null export type PromiseMockFactoryWithHelper = ( - importOriginal: () => Promise -) => Promise>> + importOriginal: () => Promise +) => Promise> | null export type MockFactory = () => any export type MockMap = Map> From c30f0fc74a77fe9fb20eb9f0d0e89a0ae532f480 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Wed, 24 Jul 2024 02:07:49 +0900 Subject: [PATCH 04/10] fix: change to promise union type --- packages/vitest/src/integrations/vi.ts | 6 +----- packages/vitest/src/types/mocker.ts | 7 +++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 0d853b5608c7..3c6296b49b9a 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -3,7 +3,7 @@ import { assertTypes, createSimpleStackTrace } from '@vitest/utils' import { parseSingleStack } from '../utils/source-map' import type { VitestMocker } from '../runtime/mocker' import type { ResolvedConfig, RuntimeConfig } from '../types' -import type { MockFactoryWithHelper, PromiseMockFactoryWithHelper } from '../types/mocker' +import type { MockFactoryWithHelper } from '../types/mocker' import { getWorkerState } from '../utils/global' import { resetModules, waitForImportsToResolve } from '../utils/modules' import { isChildProcess } from '../utils/base' @@ -194,8 +194,6 @@ export interface VitestUtils { mock(path: string, factory?: MockFactoryWithHelper): void // eslint-disable-next-line ts/method-signature-style mock(module: Promise, factory?: MockFactoryWithHelper): void - // eslint-disable-next-line ts/method-signature-style - mock(module: Promise, factory?: PromiseMockFactoryWithHelper): void /** * Removes module from mocked registry. All calls to import will return the original module even if it was mocked before. @@ -221,8 +219,6 @@ export interface VitestUtils { doMock(path: string, factory?: MockFactoryWithHelper): void // eslint-disable-next-line ts/method-signature-style doMock(module: Promise, factory?: MockFactoryWithHelper): void - // eslint-disable-next-line ts/method-signature-style - doMock(module: Promise, factory?: PromiseMockFactoryWithHelper): void /** * Removes module from mocked registry. All subsequent calls to import will return original module. * diff --git a/packages/vitest/src/types/mocker.ts b/packages/vitest/src/types/mocker.ts index 31b97a0c03df..b569c82d0726 100644 --- a/packages/vitest/src/types/mocker.ts +++ b/packages/vitest/src/types/mocker.ts @@ -1,9 +1,8 @@ +type Promisable = T | Promise + export type MockFactoryWithHelper = ( importOriginal: () => Promise -) => Record | null -export type PromiseMockFactoryWithHelper = ( - importOriginal: () => Promise -) => Promise> | null +) => Promisable | null> export type MockFactory = () => any export type MockMap = Map> From 221209c3c89ce6f9c42d9e8ccc561140c3978935 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Sun, 4 Aug 2024 23:58:18 +0900 Subject: [PATCH 05/10] fix: remove record --- packages/vitest/src/types/mocker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vitest/src/types/mocker.ts b/packages/vitest/src/types/mocker.ts index b569c82d0726..e8b59ef49780 100644 --- a/packages/vitest/src/types/mocker.ts +++ b/packages/vitest/src/types/mocker.ts @@ -2,7 +2,7 @@ type Promisable = T | Promise export type MockFactoryWithHelper = ( importOriginal: () => Promise -) => Promisable | null> +) => Promisable export type MockFactory = () => any export type MockMap = Map> From 8e23ed043cec16e6728386d28f43dc181fe4a1e9 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Sun, 4 Aug 2024 23:58:35 +0900 Subject: [PATCH 06/10] test: fix test --- test/config/test/workers-option.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/config/test/workers-option.test.ts b/test/config/test/workers-option.test.ts index a31fa95f46bf..099cfca10064 100644 --- a/test/config/test/workers-option.test.ts +++ b/test/config/test/workers-option.test.ts @@ -4,6 +4,7 @@ import { getWorkersCountByPercentage } from 'vitest/src/utils/workers.js' import * as testUtils from '../../test-utils' vi.mock(import('node:os'), async importOriginal => ({ + ...(await importOriginal()), default: { ...(await importOriginal()).default, availableParallelism: () => 10, From a23b8cf5c9d82a4f44c28ca7bed36d4f132d9641 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Mon, 5 Aug 2024 16:58:51 +0900 Subject: [PATCH 07/10] fix: add partial and remove null --- packages/vitest/src/types/mocker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vitest/src/types/mocker.ts b/packages/vitest/src/types/mocker.ts index e8b59ef49780..4937955f512b 100644 --- a/packages/vitest/src/types/mocker.ts +++ b/packages/vitest/src/types/mocker.ts @@ -2,7 +2,7 @@ type Promisable = T | Promise export type MockFactoryWithHelper = ( importOriginal: () => Promise -) => Promisable +) => Promisable> export type MockFactory = () => any export type MockMap = Map> From 5603801e6740a31c198195743e10dbeef2a4dbd5 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Mon, 5 Aug 2024 17:29:42 +0900 Subject: [PATCH 08/10] add ts-expect-error comment --- test/core/test/mocking/factory.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/test/mocking/factory.test.ts b/test/core/test/mocking/factory.test.ts index 39183c9ae8f1..88c2113f0604 100644 --- a/test/core/test/mocking/factory.test.ts +++ b/test/core/test/mocking/factory.test.ts @@ -54,7 +54,7 @@ vi.mock('../../src/mocks/log.ts', async () => { }, } }) - +// @ts-expect-error null is not allowed to mocked implementation vi.mock('../../src/mocks/default.ts', () => null) describe('mocking with factory', () => { From 679af8af2a468df96090c4bad8ee706948ac7fa8 Mon Sep 17 00:00:00 2001 From: syi0808 Date: Tue, 6 Aug 2024 21:35:58 +0900 Subject: [PATCH 09/10] docs: add changes about mock and doMock --- docs/api/vi.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/api/vi.md b/docs/api/vi.md index 4f2d967b11b9..5bb711f945af 100644 --- a/docs/api/vi.md +++ b/docs/api/vi.md @@ -17,7 +17,28 @@ This section describes the API that you can use when [mocking a module](/guide/m ### vi.mock - **Type**: `(path: string, factory?: (importOriginal: () => unknown) => unknown) => void` -- **Type**: `(path: Promise, factory?: (importOriginal: () => T) => unknown) => void` +- **Type**: `(path: Promise, factory?: (importOriginal: () => T) => T | Promise) => void` + +::: warning +`vi.mock` forces the type to return all exports in the module by default. +You can skip this with call importOriginal +```ts +vi.mock(import('./path/to/module.js'), async (importOriginal) => { + return { + ...(await importOriginal()), + namedExport: vi.fn(), + } +}) +``` +or through type assertion. +```ts +vi.mock(import('./path/to/module.js'), () => { + return { + namedExport: vi.fn(), + } as typeof import('./path/to/module.js') +}) +``` +::: Substitutes all imported modules from provided `path` with another module. You can use configured Vite aliases inside a path. The call to `vi.mock` is hoisted, so it doesn't matter where you call it. It will always be executed before all imports. If you need to reference some variables outside of its scope, you can define them inside [`vi.hoisted`](#vi-hoisted) and reference them inside `vi.mock`. @@ -163,6 +184,28 @@ If there is no `__mocks__` folder or a factory provided, Vitest will import the ### vi.doMock - **Type**: `(path: string, factory?: (importOriginal: () => unknown) => unknown) => void` +- **Type**: `(path: Promise, factory?: (importOriginal: () => T) => T | Promise) => void` + +::: warning +`vi.doMock` forces the type to return all exports in the module by default. +You can skip this with call importOriginal +```ts +vi.doMock(import('./path/to/module.js'), async (importOriginal) => { + return { + ...(await importOriginal()), + namedExport: vi.fn(), + } +}) +``` +or through type assertion. +```ts +vi.doMock(import('./path/to/module.js'), () => { + return { + namedExport: vi.fn(), + } as typeof import('./path/to/module.js') +}) +``` +::: The same as [`vi.mock`](#vi-mock), but it's not hoisted to the top of the file, so you can reference variables in the global file scope. The next [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) of the module will be mocked. From 78143bd32736aad292203a7175e7fa5608f1eba7 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 6 Aug 2024 15:06:04 +0200 Subject: [PATCH 10/10] docs: remove incorrect information, add a note about return types --- docs/api/vi.md | 46 +++------------------------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/docs/api/vi.md b/docs/api/vi.md index 3b0a26b87593..f5d52200273a 100644 --- a/docs/api/vi.md +++ b/docs/api/vi.md @@ -19,27 +19,6 @@ This section describes the API that you can use when [mocking a module](/guide/m - **Type**: `(path: string, factory?: (importOriginal: () => unknown) => unknown) => void` - **Type**: `(path: Promise, factory?: (importOriginal: () => T) => T | Promise) => void` -::: warning -`vi.mock` forces the type to return all exports in the module by default. -You can skip this with call importOriginal -```ts -vi.mock(import('./path/to/module.js'), async (importOriginal) => { - return { - ...(await importOriginal()), - namedExport: vi.fn(), - } -}) -``` -or through type assertion. -```ts -vi.mock(import('./path/to/module.js'), () => { - return { - namedExport: vi.fn(), - } as typeof import('./path/to/module.js') -}) -``` -::: - Substitutes all imported modules from provided `path` with another module. You can use configured Vite aliases inside a path. The call to `vi.mock` is hoisted, so it doesn't matter where you call it. It will always be executed before all imports. If you need to reference some variables outside of its scope, you can define them inside [`vi.hoisted`](#vi-hoisted) and reference them inside `vi.mock`. ::: warning @@ -52,7 +31,9 @@ Vitest will not mock modules that were imported inside a [setup file](/config/#s If `factory` is defined, all imports will return its result. Vitest calls factory only once and caches results for all subsequent imports until [`vi.unmock`](#vi-unmock) or [`vi.doUnmock`](#vi-dounmock) is called. -Unlike in `jest`, the factory can be asynchronous. You can use [`vi.importActual`](#vi-importactual) or a helper with the factory passed in as the first argument, and get the original module inside. Vitest also supports a module promise instead of a string in `vi.mock` method for better IDE support (when file is moved, path will be updated, `importOriginal` also inherits the type automatically). +Unlike in `jest`, the factory can be asynchronous. You can use [`vi.importActual`](#vi-importactual) or a helper with the factory passed in as the first argument, and get the original module inside. + +Vitest also supports a module promise instead of a string in the `vi.mock` and `vi.doMock` methods for better IDE support. When the file is moved, the path will be updated, and `importOriginal` also inherits the type automatically. Using this signature will also enforce factory return type to be compatible with the original module (but every export is optional). ```ts twoslash // @filename: ./path/to/module.js @@ -162,27 +143,6 @@ If there is no `__mocks__` folder or a factory provided, Vitest will import the - **Type**: `(path: string, factory?: (importOriginal: () => unknown) => unknown) => void` - **Type**: `(path: Promise, factory?: (importOriginal: () => T) => T | Promise) => void` -::: warning -`vi.doMock` forces the type to return all exports in the module by default. -You can skip this with call importOriginal -```ts -vi.doMock(import('./path/to/module.js'), async (importOriginal) => { - return { - ...(await importOriginal()), - namedExport: vi.fn(), - } -}) -``` -or through type assertion. -```ts -vi.doMock(import('./path/to/module.js'), () => { - return { - namedExport: vi.fn(), - } as typeof import('./path/to/module.js') -}) -``` -::: - The same as [`vi.mock`](#vi-mock), but it's not hoisted to the top of the file, so you can reference variables in the global file scope. The next [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) of the module will be mocked. ::: warning