diff --git a/docs/api/index.md b/docs/api/index.md index 96b3f5ead..d7a2dc8f9 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -1483,6 +1483,31 @@ Vitest provides utility functions to help you out through it's **vi** helper. Yo Imports a module with all of its properties (including nested properties) mocked. Follows the same rules that [`vi.mock`](#vi-mock) follows. For the rules applied, see [algorithm](/guide/mocking#automocking-algorithm). +### vi.resetModules + +- **Type**: `() => Vitest` + + Resets modules registry by clearing cache of all modules. Might be useful to isolate modules where local state conflicts between tests. + + ```ts + import { vi } from 'vitest' + + beforeAll(() => { + vi.resetModules() + }) + + test('change state', async() => { + const mod = await import('./some/path') + mod.changeLocalState('new value') + expect(mod.getlocalState()).toBe('new value') + }) + + test('module has old state', async() => { + const mod = await import('./some/path') + expect(mod.getlocalState()).toBe('old value') + }) + ``` + ### vi.restoreCurrentDate - **Type**: `() => void` diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 3ecf8a873..3eac9c9dd 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -2,6 +2,7 @@ import { parseStacktrace } from '../utils/source-map' import type { VitestMocker } from '../runtime/mocker' +import { resetModules } from '../utils' import { FakeTimers } from './timers' import type { EnhancedSpy, MaybeMocked, MaybeMockedDeep } from './spy' import { fn, isMockFunction, spies, spyOn } from './spy' @@ -210,6 +211,11 @@ class VitestUtils { return this } + + public resetModules() { + resetModules() + return this + } } export const vitest = new VitestUtils() diff --git a/packages/vitest/src/runtime/entry.ts b/packages/vitest/src/runtime/entry.ts index 2799b631d..87c0cf238 100644 --- a/packages/vitest/src/runtime/entry.ts +++ b/packages/vitest/src/runtime/entry.ts @@ -1,6 +1,6 @@ import { promises as fs } from 'fs' import type { BuiltinEnvironment, ResolvedConfig } from '../types' -import { getWorkerState } from '../utils' +import { getWorkerState, resetModules } from '../utils' import { setupGlobalEnv, withEnv } from './setup' import { startTests } from './run' @@ -9,10 +9,10 @@ export async function run(files: string[], config: ResolvedConfig): Promise { + if (vitestPaths.some(re => re.test(path))) + return + modules.delete(path) + }) +} + export function getFullName(task: Task) { return getNames(task).join(c.dim(' > ')) } diff --git a/test/core/test/vi.spec.ts b/test/core/test/vi.spec.ts index c85114197..63406c3f6 100644 --- a/test/core/test/vi.spec.ts +++ b/test/core/test/vi.spec.ts @@ -12,4 +12,20 @@ describe('testing vi utils', () => { expect(window.IntersectionObserver).toBe(IntersectionObserverMock) expect(IntersectionObserver).toBe(IntersectionObserverMock) }) + + test('reseting modules', async() => { + const mod1 = await import('../src/env') + vi.resetModules() + const mod2 = await import('../src/env') + const mod3 = await import('../src/env') + expect(mod1).not.toBe(mod2) + expect(mod2).toBe(mod3) + }) + + test('reseting modules doesnt reset vitest', async() => { + const v1 = await import('vitest') + vi.resetModules() + const v2 = await import('vitest') + expect(v1).toBe(v2) + }) })