Skip to content

Commit

Permalink
feat: stubGlobals helper (#1079)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Apr 2, 2022
1 parent f04a427 commit 1582948
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 1 deletion.
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)
})
})

0 comments on commit 1582948

Please sign in to comment.