Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: stubGlobals helper #1079

Merged
merged 1 commit into from Apr 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 10 additions & 1 deletion docs/api/index.md
Expand Up @@ -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.

Expand Down
4 changes: 4 additions & 0 deletions docs/guide/migration.md
Expand Up @@ -14,6 +14,10 @@ If you decide to keep globals disabled, be aware that common libraries like [`te

Unlike Jest, mocked modules in `<root>/__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/).
Expand Down
19 changes: 19 additions & 0 deletions docs/guide/mocking.md
Expand Up @@ -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.
Expand Down
15 changes: 15 additions & 0 deletions packages/vitest/src/integrations/vi.ts
Expand Up @@ -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()
Expand Down
15 changes: 15 additions & 0 deletions 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)
})
})