From 15829489eb50ee176f0084c7636ca2ff63b4e4a6 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Sat, 2 Apr 2022 19:10:50 +0300 Subject: [PATCH] feat: stubGlobals helper (#1079) --- docs/api/index.md | 11 ++++++++++- docs/guide/migration.md | 4 ++++ docs/guide/mocking.md | 19 +++++++++++++++++++ packages/vitest/src/integrations/vi.ts | 15 +++++++++++++++ test/core/test/vi.spec.ts | 15 +++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 test/core/test/vi.spec.ts diff --git a/docs/api/index.md b/docs/api/index.md index f77ca8e59c7b..9e79ab686002 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -1547,9 +1547,18 @@ Vitest provides utility functions to help you out through it's **vi** helper. Yo expect(spy).toHaveBeenCalled() expect(spy).toHaveReturnedWith(1) ``` + +### vi.stubGlobal + +- **Type**: `(key: keyof globalThis & Window, value: any) => Vitest` + + Puts a value on global variable. If you are using `jsdom` or `happy-dom`, also puts the value on `window` object. + + Read more in ["Mocking Globals" section](/guide/mocking.html#globals). + ### vi.unmock -**Type**: `(path: string) => void` +- **Type**: `(path: string) => void` Removes module from mocked registry. All subsequent calls to import will return original module even if it was mocked. diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 28b5e6ff8f26..b1e2355663c3 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -14,6 +14,10 @@ If you decide to keep globals disabled, be aware that common libraries like [`te Unlike Jest, mocked modules in `/__mocks__` are not loaded unless `vi.mock()` is called. If you need them to be mocked in every test, like in Jest, you can mock them inside [`setupFiles`](/config/#setupfiles). +**Mocking globals** + +In Jest, you could mock global variables by putting them on `window` object. Vitest treats `globalThis` and `window` as different objects, so you would need to either put it on both `window` and `globalThis`, or use [`vi.stubGlobal`](/api/#vi-stubglobal) helper. + **Jasmine API** Jest exports various [`jasmine`](https://jasmine.github.io/) globals (such as `jasmine.any()`). Any such instances will need to be migrated to [their Vitest counterparts](/api/). diff --git a/docs/guide/mocking.md b/docs/guide/mocking.md index ba7a6a6bdbd9..16a8586579c6 100644 --- a/docs/guide/mocking.md +++ b/docs/guide/mocking.md @@ -126,6 +126,25 @@ describe('reading messages', () => { - [Jest's Mock Functions](https://jestjs.io/docs/mock-function-api) +## Globals + +You can mock global variables that are not present with `jsdom` or `node` by using [`vi.stubGlobal`](/api/#vi-stubglobal) helper. It will put the value of the global variable into a `globalThis` object. + +```ts +import { vi } from 'vitest' + +const IntersectionObserverMock = vi.fn(() => ({ + disconnect: vi.fn(), + observe: vi.fn(), + takeRecords: vi.fn(), + unobserve: vi.fn(), +})) + +vi.stubGlobal('IntersectionObserver', IntersectionObserverMock) + +// now you can access it as `IntersectionObserver` or `window.IntersectionObserver` +``` + ## Modules Mock modules observe third-party-libraries, that are invoked in some other code, allowing you to test arguments, output or even redeclare its implementation. diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 5a1953f35b13..48a2c9efc5b4 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -195,6 +195,21 @@ class VitestUtils { spies.forEach(spy => spy.mockRestore()) return this } + + /** + * Will put a value on global scope. Useful, if you are + * using jsdom/happy-dom and want to mock global variables, like + * `IntersectionObserver`. + */ + public stubGlobal(name: string, value: any) { + // @ts-expect-error we can do anything! + globalThis[name] = value + if (globalThis.window) + // @ts-expect-error we can do anything! + globalThis.window[name] = value + + return this + } } export const vitest = new VitestUtils() diff --git a/test/core/test/vi.spec.ts b/test/core/test/vi.spec.ts new file mode 100644 index 000000000000..c8511419764e --- /dev/null +++ b/test/core/test/vi.spec.ts @@ -0,0 +1,15 @@ +/** + * @vitest-environment jsdom + */ + +import { describe, expect, test, vi } from 'vitest' + +describe('testing vi utils', () => { + test('global scope has variable', () => { + const IntersectionObserverMock = vi.fn() + vi.stubGlobal('IntersectionObserver', IntersectionObserverMock) + expect(globalThis.IntersectionObserver).toBe(IntersectionObserverMock) + expect(window.IntersectionObserver).toBe(IntersectionObserverMock) + expect(IntersectionObserver).toBe(IntersectionObserverMock) + }) +})