diff --git a/packages/mocker/src/automocker.ts b/packages/mocker/src/automocker.ts index c90f3b274859..d363688ab35e 100644 --- a/packages/mocker/src/automocker.ts +++ b/packages/mocker/src/automocker.ts @@ -134,9 +134,28 @@ export function mockObject( continue } + if (options.type === 'autospy' && type === 'Module') { + // Replace with clean object to recursively autospy exported module objects: + // export * as ns from "./ns" + // or + // import * as ns from "./ns" + // export { ns } + const exports = Object.create(null) + Object.defineProperty(exports, Symbol.toStringTag, { + value: 'Module', + configurable: true, + writable: true, + }) + try { + newContainer[property] = exports + } + catch { + continue + } + } // Sometimes this assignment fails for some unknown reason. If it does, // just move along. - if (!define(newContainer, property, isFunction || options.type === 'autospy' ? value : {})) { + else if (!define(newContainer, property, isFunction || options.type === 'autospy' ? value : {})) { continue } diff --git a/test/core/src/mocks/autospying-namespace/index.ts b/test/core/src/mocks/autospying-namespace/index.ts new file mode 100644 index 000000000000..f52813cf63cf --- /dev/null +++ b/test/core/src/mocks/autospying-namespace/index.ts @@ -0,0 +1 @@ +export * as NamespaceTarget from './namespaceTarget.js' diff --git a/test/core/src/mocks/autospying-namespace/namespaceTarget.ts b/test/core/src/mocks/autospying-namespace/namespaceTarget.ts new file mode 100644 index 000000000000..510523429bba --- /dev/null +++ b/test/core/src/mocks/autospying-namespace/namespaceTarget.ts @@ -0,0 +1 @@ +export const computeSquare = (n: number) => n * n diff --git a/test/core/test/mocking/autospying.test.ts b/test/core/test/mocking/autospying.test.ts index 8760fdbacfd7..f4999dde98c7 100644 --- a/test/core/test/mocking/autospying.test.ts +++ b/test/core/test/mocking/autospying.test.ts @@ -1,10 +1,12 @@ import axios from 'axios' import { expect, test, vi } from 'vitest' import { getAuthToken } from '../../src/env' +import * as NamespaceModule from '../../src/mocks/autospying-namespace/index.js' vi.mock(import('../../src/env'), { spy: true }) vi.mock('axios', { spy: true }) +vi.mock('../../src/mocks/autospying-namespace/index.js', { spy: true }) test('getAuthToken is spied', async () => { import.meta.env.AUTH_TOKEN = '123' @@ -23,3 +25,9 @@ test('package in __mocks__ has lower priority', async () => { expect(axios.isAxiosError(new Error('test'))).toBe(false) expect(axios.isAxiosError).toHaveBeenCalled() }) + +test('spies on namespace re-exports', async () => { + expect(vi.isMockFunction(NamespaceModule.NamespaceTarget.computeSquare)).toBe(true) + expect(NamespaceModule.NamespaceTarget.computeSquare(5)).toBe(25) + expect(NamespaceModule.NamespaceTarget.computeSquare).toHaveBeenCalledTimes(1) +})