diff --git a/examples/mocks/package.json b/examples/mocks/package.json index b16de7816f43..106d7e1716d4 100644 --- a/examples/mocks/package.json +++ b/examples/mocks/package.json @@ -19,6 +19,7 @@ "devDependencies": { "@vitest/ui": "latest", "react": "^18.0.0", + "sweetalert2": "^11.6.16", "vite": "latest", "vitest": "latest", "vue": "^3.2.39", diff --git a/examples/mocks/test/nested-default.spec.ts b/examples/mocks/test/nested-default.spec.ts index e242f17ab889..aad8ea323695 100644 --- a/examples/mocks/test/nested-default.spec.ts +++ b/examples/mocks/test/nested-default.spec.ts @@ -1,9 +1,13 @@ // @vitest-environment jsdom +import sweetalert from 'sweetalert2' import * as modDefaultCjs from '../src/external/default-cjs.cjs' +vi.mock('sweetalert2') vi.mock('../src/external/default-cjs.cjs') test('default is mocked', () => { expect(vi.isMockFunction(modDefaultCjs.default.fn)).toBe(true) + expect(vi.isMockFunction(sweetalert)).toBe(true) + expect(vi.isMockFunction(sweetalert.clickCancel)).toBe(true) }) diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts index 6286f0a87c40..b49d43f9dc28 100644 --- a/packages/vite-node/src/client.ts +++ b/packages/vite-node/src/client.ts @@ -424,14 +424,6 @@ export class ViteNodeRunner { const { mod, defaultExport } = interopModule(importedModule) - const modKeys = Reflect.ownKeys(mod) - let defaultKeys = !isPrimitive(defaultExport) ? Reflect.ownKeys(defaultExport) : [] - // remove reserved keys from default keys - if (typeof mod !== 'function' && typeof defaultExport === 'function') { - const reservedKeys = ['arguments', 'caller', 'prototype', 'name', 'length'] - defaultKeys = defaultKeys.filter(n => typeof n === 'string' && !reservedKeys.includes(n)) - } - return new Proxy(mod, { get(mod, prop) { if (prop === 'default') @@ -443,13 +435,6 @@ export class ViteNodeRunner { return defaultExport !== undefined return prop in mod || (defaultExport && prop in defaultExport) }, - // this is needed for mocker to know what is available to mock - ownKeys() { - if (!defaultExport || isPrimitive(defaultExport)) - return modKeys - const allKeys = [...modKeys, 'default', ...defaultKeys] - return Array.from(new Set(allKeys)) - }, getOwnPropertyDescriptor(mod, prop) { const descriptor = Reflect.getOwnPropertyDescriptor(mod, prop) if (descriptor) diff --git a/packages/vitest/src/runtime/mocker.ts b/packages/vitest/src/runtime/mocker.ts index d111f0839570..4c9ba61e9d8d 100644 --- a/packages/vitest/src/runtime/mocker.ts +++ b/packages/vitest/src/runtime/mocker.ts @@ -224,7 +224,7 @@ export class VitestMocker { const mockPropertiesOf = (container: Record, newContainer: Record) => { const containerType = getType(container) const isModule = containerType === 'Module' || !!container.__esModule - for (const { key: property, descriptor } of getAllMockableProperties(container)) { + for (const { key: property, descriptor } of getAllMockableProperties(container, isModule)) { // Modules define their exports as getters. We want to process those. if (!isModule && descriptor.get) { try { diff --git a/packages/vitest/src/utils/base.ts b/packages/vitest/src/utils/base.ts index fe8765cbffb8..dd4faa6838c3 100644 --- a/packages/vitest/src/utils/base.ts +++ b/packages/vitest/src/utils/base.ts @@ -11,8 +11,8 @@ function collectOwnProperties(obj: any, collector: Set | ((key: Object.getOwnPropertySymbols(obj).forEach(collect) } -export function getAllMockableProperties(obj: any) { - const allProps = new Set<{ key: string | symbol; descriptor: PropertyDescriptor }>() +export function getAllMockableProperties(obj: any, isModule: boolean) { + const allProps = new Map() let curr = obj do { // we don't need properties from these @@ -22,11 +22,17 @@ export function getAllMockableProperties(obj: any) { collectOwnProperties(curr, (key) => { const descriptor = Object.getOwnPropertyDescriptor(curr, key) if (descriptor) - allProps.add({ key, descriptor }) + allProps.set(key, { key, descriptor }) }) // eslint-disable-next-line no-cond-assign } while (curr = Object.getPrototypeOf(curr)) - return Array.from(allProps) + // default is not specified in ownKeys, if module is interoped + if (isModule && !allProps.has('default') && 'default' in obj) { + const descriptor = Object.getOwnPropertyDescriptor(obj, 'default') + if (descriptor) + allProps.set('default', { key: 'default', descriptor }) + } + return Array.from(allProps.values()) } export function notNullish(v: T | null | undefined): v is NonNullable { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8fedf0cb7336..e5302ae48c39 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -201,6 +201,7 @@ importers: '@vueuse/integrations': ^8.5.0 axios: ^0.26.1 react: ^18.0.0 + sweetalert2: ^11.6.16 tinyspy: ^0.3.2 vite: ^4.0.0 vitest: workspace:* @@ -213,6 +214,7 @@ importers: devDependencies: '@vitest/ui': link:../../packages/ui react: 18.2.0 + sweetalert2: 11.6.16 vite: 4.0.0 vitest: link:../../packages/vitest vue: 3.2.39 @@ -19473,6 +19475,10 @@ packages: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} dev: true + /sweetalert2/11.6.16: + resolution: {integrity: sha512-T2FO8LptErsjE4r0WMfiSk4YbeUvPadNaUZ/cADMEOnws000znrf8zFX9S5e/spvzJDyRI5En73WQyDZhGypxQ==} + dev: true + /swr/1.3.0_react@18.2.0: resolution: {integrity: sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==} peerDependencies: