Setting the file. One moment.
Subchapter 13.1
references/advanced-environments.mdMarkdown5 KBView on GitHub
node (default) - Node.js environmentjsdom - Browser-like with DOM APIshappy-dom - Faster alternative to jsdomedge-runtime - Vercel Edge Runtime// vitest.config.ts
defineConfig({
test: {
environment: 'jsdom',
// Environment-specific options
environmentOptions: {
jsdom: {
url: 'http://localhost',
},
},
},
})# jsdom
npm i -D jsdom
# happy-dom (faster, fewer APIs)
npm i -D happy-domUse magic comment at top of file:
// @vitest-environment jsdom
import { expect, test } from 'vitest'
test('DOM test', () => {
const div = document.createElement('div')
expect(div).toBeInstanceOf(HTMLDivElement)
})Full browser environment simulation:
// @vitest-environment jsdom
test('DOM manipulation', () => {
document.body.innerHTML = '<div id="app"></div>'
const app = document.getElementById('app')
app.textContent = 'Hello'
expect(app.textContent).toBe('Hello')
})
test('window APIs', () => {
expect(window.location.href).toBeDefined()
expect(localStorage).toBeDefined()
})defineConfig({
test: {
environmentOptions: {
jsdom: {
url: 'http://localhost:3000',
html: '<!DOCTYPE html><html><body></body></html>',
userAgent: 'custom-agent',
resources: 'usable',
},
},
},
})Faster but fewer APIs:
// @vitest-environment happy-dom
test('basic DOM', () => {
const el = document.createElement('div')
el.className = 'test'
expect(el.className).toBe('test')
})Use projects for different environments:
defineConfig({
test: {
projects: [
{
test: {
name: 'unit',
include: ['tests/unit/**/*.test.ts'],
environment: 'node',
},
},
{
test: {
name: 'dom',
include: ['tests/dom/**/*.test.ts'],
environment: 'jsdom',
},
},
],
},
})Create custom environment package:
// vitest-environment-custom/index.ts
import type { Environment } from 'vitest/runtime'
export default <Environment>{
name: 'custom',
viteEnvironment: 'ssr', // or 'client'
setup() {
// Setup global state
globalThis.myGlobal = 'value'
return {
teardown() {
delete globalThis.myGlobal
},
}
},
}Use with:
defineConfig({
test: {
environment: 'custom',
},
})For full isolation:
export default <Environment>{
name: 'isolated',
viteEnvironment: 'ssr',
async setupVM() {
const vm = await import('node:vm')
const context = vm.createContext()
return {
getVmContext() {
return context
},
teardown() {},
}
},
setup() {
return { teardown() {} }
},
}For real browser testing, use Vitest Browser Mode. In v4 the provider is an object (not a string), and the context imports from vitest/browser:
import { playwright } from '@vitest/browser-playwright'
defineConfig({
test: {
browser: {
enabled: true,
provider: playwright({ launchOptions: { slowMo: 100 } }),
instances: [{ browser: 'chromium' }], // or 'firefox', 'webkit'
},
},
})import { page } from 'vitest/browser' // v4: was '@vitest/browser/context'v5: DOM-environment global assignments (e.g.
window.innerWidth) now propagate to the underlying jsdom/happy-dom implementation. Locators are also exact/strict by default.
In jsdom/happy-dom, configure CSS handling:
defineConfig({
test: {
css: true, // Process CSS
// Or with options
css: {
include: /\.module\.css$/,
modules: {
classNameStrategy: 'non-scoped',
},
},
},
})If external deps fail with CSS/asset errors:
defineConfig({
test: {
server: {
deps: {
inline: ['problematic-package'],
},
},
},
})node - no browser APIsjsdom for full browser simulationhappy-dom for faster tests with basic DOM// @vitest-environment comment