[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix: resolve assets imported with `require` (#6159)

authored by

Vladimir and committed by
GitHub
(Jul 18, 2024, 12:44 PM +0200) 807a2cbc 0881023e

+55 -12
+3
pnpm-lock.yaml
··· 1191 1191 url: 1192 1192 specifier: ^0.11.0 1193 1193 version: 0.11.0 1194 + vite-node: 1195 + specifier: workspace:* 1196 + version: link:../../packages/vite-node 1194 1197 vitest: 1195 1198 specifier: workspace:* 1196 1199 version: link:../../packages/vitest
+6
docs/guide/environment.md
··· 13 13 - `happy-dom` emulates browser environment by providing Browser API, and considered to be faster than jsdom, but lacks some API, uses [`happy-dom`](https://github.com/capricorn86/happy-dom) package 14 14 - `edge-runtime` emulates Vercel's [edge-runtime](https://edge-runtime.vercel.app/), uses [`@edge-runtime/vm`](https://www.npmjs.com/package/@edge-runtime/vm) package 15 15 16 + ::: info 17 + When using `jsdom` or `happy-dom` environments, Vitest follows the same rules that Vite does when importing [CSS](https://vitejs.dev/guide/features.html#css) and [assets](https://vitejs.dev/guide/features.html#static-assets). If importing external dependency fails with `unknown extension .css` error, you need to inline the whole import chain manually by adding all packages to [`server.deps.external`](/config/#server-deps-external). For example, if the error happens in `package-3` in this import chain: `source code -> package-1 -> package-2 -> package-3`, you need to add all three packages to `server.deps.external`. 18 + 19 + Since Vitest 2.0.4 the `require` of CSS and assets inside the external dependencies are resolved automatically. 20 + ::: 21 + 16 22 ## Environments for Specific Files 17 23 18 24 When setting `environment` option in your config, it will apply to all the test files in your project. To have more fine-grained control, you can use control comments to specify environment for specific files. Control comments are comments that start with `@vitest-environment` and are followed by the environment name:
+1
test/core/package.json
··· 28 28 "tinyrainbow": "^1.2.0", 29 29 "tinyspy": "^1.0.2", 30 30 "url": "^0.11.0", 31 + "vite-node": "workspace:*", 31 32 "vitest": "workspace:*", 32 33 "vitest-environment-custom": "file:./vitest-environment-custom", 33 34 "vue": "^3.4.26",
+1
test/core/src/file-txt.txt
··· 1 + text
+10 -4
test/core/test/require.test.ts
··· 1 1 // @vitest-environment jsdom 2 2 3 + // import { KNOWN_ASSET_RE } from 'vite-node/constants' 3 4 import { describe, expect, it } from 'vitest' 4 5 5 6 const _require = require ··· 11 12 const scss = _require('./../src/file-scss.scss') 12 13 const less = _require('./../src/file-less.less') 13 14 14 - expect(css).toEqual({}) 15 - expect(sass).toEqual({}) 16 - expect(scss).toEqual({}) 17 - expect(less).toEqual({}) 15 + expect(css).toEqual('') 16 + expect(sass).toEqual('') 17 + expect(scss).toEqual('') 18 + expect(less).toEqual('') 19 + }) 20 + 21 + it('importing assets works', () => { 22 + const path = _require.resolve('./../src/file-txt.txt') 23 + expect(_require('./../src/file-txt.txt')).toBe(path) 18 24 }) 19 25 })
+17 -4
packages/vitest/src/runtime/runVmTests.ts
··· 4 4 import { performance } from 'node:perf_hooks' 5 5 import { collectTests, startTests } from '@vitest/runner' 6 6 import { installSourcemapsSupport } from 'vite-node/source-map' 7 + import { KNOWN_ASSET_TYPES } from 'vite-node/constants' 7 8 import { setupChaiConfig } from '../integrations/chai/config' 8 9 import { 9 10 startCoverageInsideWorker, ··· 36 37 if (workerState.environment.transformMode === 'web') { 37 38 const _require = createRequire(import.meta.url) 38 39 // always mock "required" `css` files, because we cannot process them 39 - _require.extensions['.css'] = () => ({}) 40 - _require.extensions['.scss'] = () => ({}) 41 - _require.extensions['.sass'] = () => ({}) 42 - _require.extensions['.less'] = () => ({}) 40 + _require.extensions['.css'] = resolveCss 41 + _require.extensions['.scss'] = resolveCss 42 + _require.extensions['.sass'] = resolveCss 43 + _require.extensions['.less'] = resolveCss 44 + // since we are using Vite, we can assume how these will be resolved 45 + KNOWN_ASSET_TYPES.forEach((type) => { 46 + _require.extensions[`.${type}`] = resolveAsset 47 + }) 43 48 } 44 49 45 50 // @ts-expect-error not typed global for patched timers ··· 92 97 } 93 98 94 99 await stopCoverageInsideWorker(config.coverage, executor) 100 + } 101 + 102 + function resolveCss(mod: NodeJS.Module) { 103 + mod.exports = '' 104 + } 105 + 106 + function resolveAsset(mod: NodeJS.Module, url: string) { 107 + mod.exports = url 95 108 }
+17 -4
packages/vitest/src/runtime/setup-node.ts
··· 2 2 import util from 'node:util' 3 3 import timers from 'node:timers' 4 4 import { installSourcemapsSupport } from 'vite-node/source-map' 5 + import { KNOWN_ASSET_TYPES } from 'vite-node/constants' 5 6 import type { 6 7 EnvironmentOptions, 7 8 ResolvedConfig, ··· 44 45 if (environment.transformMode === 'web') { 45 46 const _require = createRequire(import.meta.url) 46 47 // always mock "required" `css` files, because we cannot process them 47 - _require.extensions['.css'] = () => ({}) 48 - _require.extensions['.scss'] = () => ({}) 49 - _require.extensions['.sass'] = () => ({}) 50 - _require.extensions['.less'] = () => ({}) 48 + _require.extensions['.css'] = resolveCss 49 + _require.extensions['.scss'] = resolveCss 50 + _require.extensions['.sass'] = resolveCss 51 + _require.extensions['.less'] = resolveCss 52 + // since we are using Vite, we can assume how these will be resolved 53 + KNOWN_ASSET_TYPES.forEach((type) => { 54 + _require.extensions[`.${type}`] = resolveAsset 55 + }) 51 56 process.env.SSR = '' 52 57 } 53 58 else { ··· 67 72 if (!config.disableConsoleIntercept) { 68 73 await setupConsoleLogSpy() 69 74 } 75 + } 76 + 77 + function resolveCss(mod: NodeJS.Module) { 78 + mod.exports = '' 79 + } 80 + 81 + function resolveAsset(mod: NodeJS.Module, url: string) { 82 + mod.exports = url 70 83 } 71 84 72 85 export async function setupConsoleLogSpy() {