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(mock): expose a importOriginal helper to the factory #2551

Merged
merged 1 commit into from Dec 22, 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
29 changes: 27 additions & 2 deletions docs/api/index.md
Expand Up @@ -2594,11 +2594,36 @@ Vitest provides utility functions to help you out through it's **vi** helper. Yo

Makes all `imports` to passed module to be mocked. Inside a path you _can_ use configured Vite aliases. 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 `factory` is defined, will return its result. Factory function can be asynchronous. You may call [`vi.importActual`](#vi-importactual) inside to get the original module. Since the call to `vi.mock` is hoisted, you don't have access to variables declared in the global file scope!
- If `factory` is defined, will return its result. The factory function can be asynchronous. A helper to import the original module is passed to the factory function, or you call [`vi.importActual`](#vi-importactual) inside to get other modules. Since the call to `vi.mock` is hoisted, you don't have access to variables declared in the global file scope!

```ts
vi.mock('./path/to/module', async (importOriginal) => {
const mod = await importOriginal()
return {
...mod,
// replace some exports
namedExport: vi.fn(),
}
})
```

or

```ts
vi.mock('./path/to/module', async () => {
const mod = await vi.importActual('./path/to/module')
return {
...mod,
// replace some exports
namedExport: vi.fn(),
}
})
```

- If mocking a module with a default export, you'll need to provide a `default` key within the returned factory function object. This is an ES modules specific caveat, therefore `jest` documentation may differ as `jest` uses commonJS modules. *Example:*

```ts
vi.mock('path', () => {
vi.mock('./path/to/module', () => {
return {
default: { myDefaultKey: vi.fn() },
namedExport: vi.fn(),
Expand Down
2 changes: 2 additions & 0 deletions examples/mocks/src/moduleB.ts
@@ -0,0 +1,2 @@
export const A = 'A'
export const B = 'B'
16 changes: 16 additions & 0 deletions examples/mocks/test/factory.test.ts
@@ -1,6 +1,7 @@
import axios from 'axios'
import * as example from '../src/example'
import * as moduleA from '../src/moduleA'
import * as moduleB from '../src/moduleB'
import logger from '../src/log'

vi
Expand All @@ -25,6 +26,15 @@ vi.mock('../src/moduleA', async () => {
}
})

vi.mock('../src/moduleB', async (importOriginal) => {
const actual = await importOriginal<any>()
return {
...actual,
B: 'mockedB',
C: 'addedC',
}
})

vi.mock('axios', () => {
return {
default: {
Expand Down Expand Up @@ -73,6 +83,12 @@ describe('mocking with factory', () => {
expect((moduleA as any).B).toBe('B')
})

test('successfully with factory helper', () => {
expect(moduleB.A).toBe('A')
expect(moduleB.B).toBe('mockedB')
expect((moduleB as any).C).toBe('addedC')
})

test('mocks node_modules', () => {
axios.get('./path')

Expand Down