From 084e929c8ed668aae004a94f0706c39a69e40490 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Fri, 16 Dec 2022 15:33:42 +0100 Subject: [PATCH] fix!: correctly interop nested default for external and inlined modules (#2512) * fix: correctly interop nested default for external and inlined modules, if environment is not node * chore: cleanup * chore: cleanup * test: update default interop test * chore: update module interop tests * fix: add environment to enzym example * chore: update tests * test: don't run module tests without threads, because we don't clear ESM cache * chore: correctly reset current test environment --- examples/react-enzyme/package.json | 1 + examples/react-enzyme/vite.config.ts | 1 + packages/vite-node/src/client.ts | 68 ++++++++++------ .../vitest/src/integrations/chai/index.ts | 6 +- packages/vitest/src/runtime/entry.ts | 9 ++- packages/vitest/src/runtime/execute.ts | 6 +- packages/vitest/src/runtime/worker.ts | 4 +- packages/vitest/src/utils/global.ts | 5 ++ packages/vitest/src/utils/index.ts | 1 + pnpm-lock.yaml | 78 ++++++++++--------- test/cjs/test/function-default.test.ts | 2 +- test/cjs/test/named-default.test.ts | 15 ---- test/cjs/vitest.config.ts | 6 +- test/core/src/cjs/nested-default-cjs.js | 8 ++ test/core/src/external/default-cjs.js | 7 ++ test/core/src/external/nested-default-cjs.js | 8 ++ test/core/test/module-dom.test.ts | 33 ++++++++ test/core/test/module.test.ts | 26 ++++++- test/core/vitest.config.ts | 2 +- 19 files changed, 196 insertions(+), 90 deletions(-) delete mode 100644 test/cjs/test/named-default.test.ts create mode 100644 test/core/src/cjs/nested-default-cjs.js create mode 100644 test/core/src/external/default-cjs.js create mode 100644 test/core/src/external/nested-default-cjs.js create mode 100644 test/core/test/module-dom.test.ts diff --git a/examples/react-enzyme/package.json b/examples/react-enzyme/package.json index 4b0270674302..983a3b3dc01e 100644 --- a/examples/react-enzyme/package.json +++ b/examples/react-enzyme/package.json @@ -16,6 +16,7 @@ "@vitest/ui": "latest", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.7", "enzyme": "^3.11.0", + "jsdom": "^20.0.3", "vite": "latest", "vitest": "latest" }, diff --git a/examples/react-enzyme/vite.config.ts b/examples/react-enzyme/vite.config.ts index 9777dccc1993..099da056e701 100644 --- a/examples/react-enzyme/vite.config.ts +++ b/examples/react-enzyme/vite.config.ts @@ -6,6 +6,7 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ plugins: [react()], test: { + environment: 'jsdom', setupFiles: ['./vitest.setup.ts'], }, }) diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts index 4a19239b680a..d43dc93c116d 100644 --- a/packages/vite-node/src/client.ts +++ b/packages/vite-node/src/client.ts @@ -273,9 +273,17 @@ export class ViteNodeRunner { enumerable: false, configurable: false, }) - // this prosxy is triggered only on exports.name and module.exports access + // this prosxy is triggered only on exports.{name} and module.exports access const cjsExports = new Proxy(exports, { - set(_, p, value) { + set: (_, p, value) => { + // treat "module.exports =" the same as "exports.default =" to not have nested "default.default", + // so "exports.default" becomes the actual module + if (p === 'default' && this.shouldInterop(url, { default: value })) { + exportAll(cjsExports, value) + exports.default = value + return true + } + if (!Reflect.has(exports, 'default')) exports.default = {} @@ -378,35 +386,45 @@ export class ViteNodeRunner { * Import a module and interop it */ async interopedImport(path: string) { - const mod = await import(path) - - if (this.shouldInterop(path, mod)) { - const tryDefault = this.hasNestedDefault(mod) - return new Proxy(mod, { - get: proxyMethod('get', tryDefault), - set: proxyMethod('set', tryDefault), - has: proxyMethod('has', tryDefault), - deleteProperty: proxyMethod('deleteProperty', tryDefault), - }) - } + const importedModule = await import(path) - return mod - } + if (!this.shouldInterop(path, importedModule)) + return importedModule - hasNestedDefault(target: any) { - return '__esModule' in target && target.__esModule && 'default' in target.default + const { mod, defaultExport } = interopModule(importedModule) + + return new Proxy(mod, { + get(mod, prop) { + if (prop === 'default') + return defaultExport + return mod[prop] ?? defaultExport?.[prop] + }, + has(mod, prop) { + if (prop === 'default') + return defaultExport !== undefined + return prop in mod || (defaultExport && prop in defaultExport) + }, + }) } } -function proxyMethod(name: 'get' | 'set' | 'has' | 'deleteProperty', tryDefault: boolean) { - return function (target: any, key: string | symbol, ...args: [any?, any?]): any { - const result = Reflect[name](target, key, ...args) - if (isPrimitive(target.default)) - return result - if ((tryDefault && key === 'default') || typeof result === 'undefined') - return Reflect[name](target.default, key, ...args) - return result +function interopModule(mod: any) { + if (isPrimitive(mod)) { + return { + mod: { default: mod }, + defaultExport: mod, + } } + + let defaultExport = 'default' in mod ? mod.default : mod + + if (!isPrimitive(defaultExport) && '__esModule' in defaultExport) { + mod = defaultExport + if ('default' in defaultExport) + defaultExport = defaultExport.default + } + + return { mod, defaultExport } } // keep consistency with Vite on how exports are defined diff --git a/packages/vitest/src/integrations/chai/index.ts b/packages/vitest/src/integrations/chai/index.ts index c3290c4f13f3..76cddfac59eb 100644 --- a/packages/vitest/src/integrations/chai/index.ts +++ b/packages/vitest/src/integrations/chai/index.ts @@ -1,13 +1,11 @@ import * as chai from 'chai' import './setup' import type { Test } from '../../types' -import { getFullName, getWorkerState } from '../../utils' +import { getCurrentEnvironment, getFullName } from '../../utils' import type { MatcherState } from '../../types/chai' import { getState, setState } from './jest-expect' import { GLOBAL_EXPECT } from './constants' -const workerState = getWorkerState() - export function createExpect(test?: Test) { const expect = ((value: any, message?: string): Vi.Assertion => { const { assertionCalls } = getState(expect) @@ -30,7 +28,7 @@ export function createExpect(test?: Test) { isExpectingAssertionsError: null, expectedAssertionsNumber: null, expectedAssertionsNumberErrorGen: null, - environment: workerState.config.environment, + environment: getCurrentEnvironment(), testPath: test?.suite.file?.filepath, currentTestName: test ? getFullName(test) : undefined, }, expect) diff --git a/packages/vitest/src/runtime/entry.ts b/packages/vitest/src/runtime/entry.ts index fa43ceb5fca4..a815718fe5a6 100644 --- a/packages/vitest/src/runtime/entry.ts +++ b/packages/vitest/src/runtime/entry.ts @@ -53,6 +53,9 @@ export async function run(files: string[], config: ResolvedConfig): Promise JSON.stringify(envOptions)) for (const options of Object.keys(filesByOptions)) { @@ -63,9 +66,9 @@ export async function run(files: string[], config: ResolvedConfig): Promise { for (const { file } of files) { - // it doesn't matter if running with --threads - // if running with --no-threads, we usually want to reset everything before running a test - // but we have --isolate option to disable this + // it doesn't matter if running with --threads + // if running with --no-threads, we usually want to reset everything before running a test + // but we have --isolate option to disable this if (config.isolate) { workerState.mockMap.clear() resetModules(workerState.moduleCache, true) diff --git a/packages/vitest/src/runtime/execute.ts b/packages/vitest/src/runtime/execute.ts index e126bfea4764..cd358480fea6 100644 --- a/packages/vitest/src/runtime/execute.ts +++ b/packages/vitest/src/runtime/execute.ts @@ -2,7 +2,7 @@ import { ViteNodeRunner } from 'vite-node/client' import type { ViteNodeRunnerOptions } from 'vite-node' import { normalizePath } from 'vite' import type { MockMap } from '../types/mocker' -import { getWorkerState } from '../utils' +import { getCurrentEnvironment, getWorkerState } from '../utils' import { VitestMocker } from './mocker' export interface ExecuteOptions extends ViteNodeRunnerOptions { @@ -60,4 +60,8 @@ export class VitestRunner extends ViteNodeRunner { __vitest_mocker__: this.mocker, }) } + + shouldInterop(path: string, mod: any) { + return this.options.interopDefault ?? (getCurrentEnvironment() !== 'node' && super.shouldInterop(path, mod)) + } } diff --git a/packages/vitest/src/runtime/worker.ts b/packages/vitest/src/runtime/worker.ts index 0428c26dae02..20264039c600 100644 --- a/packages/vitest/src/runtime/worker.ts +++ b/packages/vitest/src/runtime/worker.ts @@ -50,7 +50,7 @@ async function startViteNode(ctx: WorkerContext) { }, moduleCache, mockMap, - interopDefault: config.deps.interopDefault ?? true, + interopDefault: config.deps.interopDefault, root: config.root, base: config.base, }))[0] @@ -70,6 +70,8 @@ function init(ctx: WorkerContext) { process.env.VITEST_WORKER_ID = String(workerId) process.env.VITEST_POOL_ID = String(poolId) + // @ts-expect-error untyped global + globalThis.__vitest_environment__ = config.environment // @ts-expect-error I know what I am doing :P globalThis.__vitest_worker__ = { ctx, diff --git a/packages/vitest/src/utils/global.ts b/packages/vitest/src/utils/global.ts index 2d714ad33d05..02db76c687b0 100644 --- a/packages/vitest/src/utils/global.ts +++ b/packages/vitest/src/utils/global.ts @@ -4,3 +4,8 @@ export function getWorkerState(): WorkerGlobalState { // @ts-expect-error untyped global return globalThis.__vitest_worker__ } + +export function getCurrentEnvironment(): string { + // @ts-expect-error untyped global + return globalThis.__vitest_environment__ +} diff --git a/packages/vitest/src/utils/index.ts b/packages/vitest/src/utils/index.ts index 5f9927ae72a0..e4f8bd3c61c8 100644 --- a/packages/vitest/src/utils/index.ts +++ b/packages/vitest/src/utils/index.ts @@ -49,6 +49,7 @@ export function resetModules(modules: ModuleCacheMap, resetMocks = false) { const skipPaths = [ // Vitest /\/vitest\/dist\//, + /\/vite-node\/dist\//, // yarn's .store folder /vitest-virtual-\w+\/dist/, // cnpm diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2aad968fb539..94159cf4a101 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -236,7 +236,7 @@ importers: react-dom: 18.0.0_react@18.0.0 devDependencies: '@testing-library/react': 13.3.0_zpnidt7m3osuk7shl3s4oenomq - '@types/node': 18.11.14 + '@types/node': 18.11.15 '@types/react': 18.0.26 '@vitejs/plugin-react': 3.0.0 jsdom: 20.0.3 @@ -303,6 +303,7 @@ importers: '@vitest/ui': latest '@wojtekmaj/enzyme-adapter-react-17': ^0.6.7 enzyme: ^3.11.0 + jsdom: ^20.0.3 react: ^17.0.2 react-dom: ^17.0.2 vite: ^4.0.0 @@ -318,6 +319,7 @@ importers: '@vitest/ui': link:../../packages/ui '@wojtekmaj/enzyme-adapter-react-17': 0.6.7_7ltvq4e2railvf5uya4ffxpe2a enzyme: 3.11.0 + jsdom: 20.0.3 vite: 4.0.0 vitest: link:../../packages/vitest @@ -532,11 +534,11 @@ importers: vite: ^4.0.0 vitest: workspace:* devDependencies: - '@sveltejs/vite-plugin-svelte': 2.0.0_svelte@3.54.0+vite@4.0.0 - '@testing-library/svelte': 3.2.2_svelte@3.54.0 + '@sveltejs/vite-plugin-svelte': 2.0.0_svelte@3.55.0+vite@4.0.0 + '@testing-library/svelte': 3.2.2_svelte@3.55.0 '@vitest/ui': link:../../packages/ui jsdom: 20.0.3 - svelte: 3.54.0 + svelte: 3.55.0 vite: 4.0.0 vitest: link:../../packages/vitest @@ -4836,7 +4838,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 18.11.14 + '@types/node': 18.11.15 '@types/yargs': 15.0.14 chalk: 4.1.2 dev: true @@ -4848,7 +4850,7 @@ packages: '@jest/schemas': 29.0.0 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 18.11.14 + '@types/node': 18.11.15 '@types/yargs': 17.0.12 chalk: 4.1.2 dev: true @@ -5361,7 +5363,7 @@ packages: engines: {node: '>=14'} hasBin: true dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 playwright-core: 1.28.0 dev: true @@ -6976,7 +6978,7 @@ packages: string.prototype.matchall: 4.0.7 dev: true - /@sveltejs/vite-plugin-svelte/2.0.0_svelte@3.54.0+vite@4.0.0: + /@sveltejs/vite-plugin-svelte/2.0.0_svelte@3.55.0+vite@4.0.0: resolution: {integrity: sha512-oUFrYQarRv4fppmxdrv00qw3wX8Ycdj0uv33MfpRZyR8K67dyxiOcHnqkB0zSy5sDJA8RC/2aNtYhXJ8NINVHQ==} engines: {node: ^14.18.0 || >= 16} peerDependencies: @@ -6987,8 +6989,8 @@ packages: deepmerge: 4.2.2 kleur: 4.1.5 magic-string: 0.27.0 - svelte: 3.54.0 - svelte-hmr: 0.15.1_svelte@3.54.0 + svelte: 3.55.0 + svelte-hmr: 0.15.1_svelte@3.55.0 vite: 4.0.0 vitefu: 0.2.3_vite@4.0.0 transitivePeerDependencies: @@ -7105,14 +7107,14 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: true - /@testing-library/svelte/3.2.2_svelte@3.54.0: + /@testing-library/svelte/3.2.2_svelte@3.55.0: resolution: {integrity: sha512-IKwZgqbekC3LpoRhSwhd0JswRGxKdAGkf39UiDXTywK61YyLXbCYoR831e/UUC6EeNW4hiHPY+2WuovxOgI5sw==} engines: {node: '>= 10'} peerDependencies: svelte: 3.x dependencies: '@testing-library/dom': 8.17.1 - svelte: 3.54.0 + svelte: 3.55.0 dev: true /@testing-library/user-event/13.5.0: @@ -7187,7 +7189,7 @@ packages: /@types/cheerio/0.22.31: resolution: {integrity: sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/codemirror/5.60.5: @@ -7253,27 +7255,27 @@ packages: /@types/fs-extra/9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/glob/7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.1 - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/glob/8.0.0: resolution: {integrity: sha512-l6NQsDDyQUVeoTynNpC9uRvCUint/gSUXQA2euwmTuWGvPY5LSDUu6tkCtJB2SvGQlJQzLaKqcGZP4//7EDveA==} dependencies: '@types/minimatch': 5.1.1 - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/graceful-fs/4.1.5: resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/hast/2.3.4: @@ -7334,7 +7336,7 @@ packages: /@types/jsdom/20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 '@types/tough-cookie': 4.0.2 parse5: 7.1.1 dev: true @@ -7378,7 +7380,7 @@ packages: /@types/node-fetch/2.6.2: resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 form-data: 3.0.1 dev: true @@ -7394,6 +7396,10 @@ packages: resolution: {integrity: sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==} dev: true + /@types/node/18.11.15: + resolution: {integrity: sha512-VkhBbVo2+2oozlkdHXLrb3zjsRkpdnaU2bXmX8Wgle3PUi569eLRaHGlgETQHR7lLL1w7GiG3h9SnePhxNDecw==} + dev: true + /@types/node/18.7.13: resolution: {integrity: sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==} dev: false @@ -7424,7 +7430,7 @@ packages: /@types/prompts/2.4.2: resolution: {integrity: sha512-TwNx7qsjvRIUv/BCx583tqF5IINEVjCNqg9ofKHRlSoUHE62WBHrem4B1HGXcIrG511v29d1kJ9a/t2Esz7MIg==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 kleur: 3.0.3 dev: true @@ -7497,7 +7503,7 @@ packages: /@types/resolve/1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/resolve/1.20.2: @@ -7514,7 +7520,7 @@ packages: /@types/set-cookie-parser/2.4.2: resolution: {integrity: sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/sinonjs__fake-timers/8.1.1: @@ -7597,7 +7603,7 @@ packages: /@types/webpack-sources/3.2.0: resolution: {integrity: sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 '@types/source-list-map': 0.1.2 source-map: 0.7.4 dev: true @@ -7605,7 +7611,7 @@ packages: /@types/webpack/4.41.32: resolution: {integrity: sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 '@types/tapable': 1.0.8 '@types/uglify-js': 3.17.0 '@types/webpack-sources': 3.2.0 @@ -7616,7 +7622,7 @@ packages: /@types/ws/8.5.3: resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true /@types/yargs-parser/21.0.0: @@ -7639,7 +7645,7 @@ packages: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 dev: true optional: true @@ -14567,7 +14573,7 @@ packages: dependencies: '@jest/types': 26.6.2 '@types/graceful-fs': 4.1.5 - '@types/node': 18.11.14 + '@types/node': 18.11.15 anymatch: 3.1.2 fb-watchman: 2.0.1 graceful-fs: 4.2.10 @@ -14635,7 +14641,7 @@ packages: resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} engines: {node: '>= 10.14.2'} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 graceful-fs: 4.2.10 dev: true @@ -14644,7 +14650,7 @@ packages: engines: {node: '>= 10.14.2'} dependencies: '@jest/types': 26.6.2 - '@types/node': 18.11.14 + '@types/node': 18.11.15 chalk: 4.1.2 graceful-fs: 4.2.10 is-ci: 2.0.0 @@ -14656,7 +14662,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.0.1 - '@types/node': 18.11.14 + '@types/node': 18.11.15 chalk: 4.1.2 ci-info: 3.7.0 graceful-fs: 4.2.10 @@ -14667,7 +14673,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -14676,7 +14682,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.11.14 + '@types/node': 18.11.15 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -19240,17 +19246,17 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - /svelte-hmr/0.15.1_svelte@3.54.0: + /svelte-hmr/0.15.1_svelte@3.55.0: resolution: {integrity: sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==} engines: {node: ^12.20 || ^14.13.1 || >= 16} peerDependencies: svelte: '>=3.19.0' dependencies: - svelte: 3.54.0 + svelte: 3.55.0 dev: true - /svelte/3.54.0: - resolution: {integrity: sha512-tdrgeJU0hob0ZWAMoKXkhcxXA7dpTg6lZGxUeko5YqvPdJBiyRspGsCwV27kIrbrqPP2WUoSV9ca0gnLlw8YzQ==} + /svelte/3.55.0: + resolution: {integrity: sha512-uGu2FVMlOuey4JoKHKrpZFkoYyj0VLjJdz47zX5+gVK5odxHM40RVhar9/iK2YFRVxvfg9FkhfVlR0sjeIrOiA==} engines: {node: '>= 8'} dev: true diff --git a/test/cjs/test/function-default.test.ts b/test/cjs/test/function-default.test.ts index 51b4b6b930c0..bf640d2c77a0 100644 --- a/test/cjs/test/function-default.test.ts +++ b/test/cjs/test/function-default.test.ts @@ -8,6 +8,6 @@ describe('correctly puts default on default', () => { it('works on nested default function', () => { // @ts-expect-error types defined only default - expect(format.default()).toBe('') + expect(format.default).toBeUndefined() }) }) diff --git a/test/cjs/test/named-default.test.ts b/test/cjs/test/named-default.test.ts deleted file mode 100644 index 5e7cd5d01d60..000000000000 --- a/test/cjs/test/named-default.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import * as other from '../src/other.cjs' -import defaultOther from '../src/other.cjs' - -describe('correctly identified named default', () => { - it('default should be on default', () => { - expect(other.default).toBe(defaultOther) - }) - - it('default is an object with default', () => { - expect(other.default).toMatchObject({ default: 2 }) - expect(defaultOther).toMatchObject({ default: 2 }) - }) -}) diff --git a/test/cjs/vitest.config.ts b/test/cjs/vitest.config.ts index e61d57a7d115..08d877e33e35 100644 --- a/test/cjs/vitest.config.ts +++ b/test/cjs/vitest.config.ts @@ -1,7 +1,9 @@ -import { defineConfig } from 'vite' +import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - // threads: false, + deps: { + interopDefault: true, + }, }, }) diff --git a/test/core/src/cjs/nested-default-cjs.js b/test/core/src/cjs/nested-default-cjs.js new file mode 100644 index 000000000000..fa3e8e5be993 --- /dev/null +++ b/test/core/src/cjs/nested-default-cjs.js @@ -0,0 +1,8 @@ +exports.default = { + a: 'a', + b: 'b', + object: { + h: 'h', + }, +} +Object.defineProperty(exports, '__esModule', { value: true, enumerable: false }) diff --git a/test/core/src/external/default-cjs.js b/test/core/src/external/default-cjs.js new file mode 100644 index 000000000000..efd596a57228 --- /dev/null +++ b/test/core/src/external/default-cjs.js @@ -0,0 +1,7 @@ +module.exports = { + a: 'a', + b: 'b', + object: { + h: 'h', + }, +} diff --git a/test/core/src/external/nested-default-cjs.js b/test/core/src/external/nested-default-cjs.js new file mode 100644 index 000000000000..fa3e8e5be993 --- /dev/null +++ b/test/core/src/external/nested-default-cjs.js @@ -0,0 +1,8 @@ +exports.default = { + a: 'a', + b: 'b', + object: { + h: 'h', + }, +} +Object.defineProperty(exports, '__esModule', { value: true, enumerable: false }) diff --git a/test/core/test/module-dom.test.ts b/test/core/test/module-dom.test.ts new file mode 100644 index 000000000000..97d80fc762a7 --- /dev/null +++ b/test/core/test/module-dom.test.ts @@ -0,0 +1,33 @@ +/** + * @vitest-environment jsdom + */ + +import { describe, expect, it } from 'vitest' +// @ts-expect-error is not typed with imports +import * as nestedDefaultCjs from '../src/cjs/nested-default-cjs' +// @ts-expect-error is not typed with imports +import * as nestedDefaultExternalCjs from '../src/external/nested-default-cjs' +// @ts-expect-error is not typed with imports +import * as moduleDefaultCjs from '../src/external/default-cjs' + +describe('validating nested defaults in isolation', () => { + it.each([ + nestedDefaultCjs, + nestedDefaultExternalCjs, + ])('nested default should be resolved, because environment is not node', (mod) => { + expect(mod).toHaveProperty('default') + expect(mod.default).not.toHaveProperty('default') + expect(mod.default.a).toBe('a') + expect(mod.default.b).toBe('b') + expect(mod.a).toBe('a') + expect(mod.b).toBe('b') + }) + + it('externalized "module.exports" CJS module interops default', () => { + expect(moduleDefaultCjs).toHaveProperty('default') + expect(moduleDefaultCjs.default).toHaveProperty('a') + expect(moduleDefaultCjs.default.a).toBe('a') + expect(moduleDefaultCjs).toHaveProperty('a') + expect(moduleDefaultCjs.a).toBe('a') + }) +}) diff --git a/test/core/test/module.test.ts b/test/core/test/module.test.ts index 4bc8c2dd26f7..b96b1620da92 100644 --- a/test/core/test/module.test.ts +++ b/test/core/test/module.test.ts @@ -1,4 +1,4 @@ -import { expect, it } from 'vitest' +import { describe, expect, it } from 'vitest' // @ts-expect-error is not typed import cjs, { a, b } from '../src/cjs/module-cjs' // @ts-expect-error is not typed with imports @@ -12,6 +12,12 @@ import * as arrayCjs from '../src/cjs/array-cjs' // @ts-expect-error is not typed with imports import * as classCjs from '../src/cjs/class-cjs' // @ts-expect-error is not typed with imports +import * as nestedDefaultCjs from '../src/cjs/nested-default-cjs' +// @ts-expect-error is not typed with imports +import * as nestedDefaultExternalCjs from '../src/external/nested-default-cjs' +// @ts-expect-error is not typed with imports +import * as moduleDefaultCjs from '../src/external/default-cjs' +// @ts-expect-error is not typed with imports import * as internalEsm from '../src/esm/internal-esm.mjs' import c, { d } from '../src/module-esm' import * as timeout from '../src/timeout' @@ -20,6 +26,24 @@ it('doesn\'t when extending module', () => { expect(() => Object.assign(globalThis, timeout)).not.toThrow() }) +describe('validating nested defaults in isolation', () => { + it.each([ + nestedDefaultCjs, + nestedDefaultExternalCjs, + ])('nested default should stay, because environment is node', (mod) => { + expect(mod).toHaveProperty('default') + expect(mod.default).toHaveProperty('default') + expect(mod.default.default.a).toBe('a') + expect(mod.default.default.b).toBe('b') + }) + + it('don\'t interop external module.exports, because environment is node', () => { + expect(moduleDefaultCjs).toHaveProperty('default') + expect(moduleDefaultCjs.default).toHaveProperty('a') + expect(moduleDefaultCjs).not.toHaveProperty('a') + }) +}) + it('should work when using module.exports cjs', () => { expect(cjs.a).toBe(1) expect(cjs.b).toBe(2) diff --git a/test/core/vitest.config.ts b/test/core/vitest.config.ts index b5cc98d3ddb4..66c422055641 100644 --- a/test/core/vitest.config.ts +++ b/test/core/vitest.config.ts @@ -60,7 +60,7 @@ export default defineConfig({ seed: 101, }, deps: { - external: ['tinyspy'], + external: ['tinyspy', /src\/external/], }, alias: [ {