READ-ONLY PACKAGE PREVIEW

vitest/references/advanced-environments.md

Version e53a142a2420 · MIT. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.

← Return to resource and package checksum


name: test-environments description: Configure environments like jsdom, happy-dom for browser APIs


Test Environments

Available Environments

  • node (default) - Node.js environment
  • jsdom - Browser-like with DOM APIs
  • happy-dom - Faster alternative to jsdom
  • edge-runtime - Vercel Edge Runtime

Configuration

// vitest.config.ts
defineConfig({
  test: {
    environment: 'jsdom',

    // Environment-specific options
    environmentOptions: {
      jsdom: {
        url: 'http://localhost',
      },
    },
  },
})

Installing Environment Packages

# jsdom
npm i -D jsdom

# happy-dom (faster, fewer APIs)
npm i -D happy-dom

Per-File Environment

Use 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)
})

jsdom Environment

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()
})

jsdom Options

defineConfig({
  test: {
    environmentOptions: {
      jsdom: {
        url: 'http://localhost:3000',
        html: '<!DOCTYPE html><html><body></body></html>',
        userAgent: 'custom-agent',
        resources: 'usable',
      },
    },
  },
})

happy-dom Environment

Faster but fewer APIs:

// @vitest-environment happy-dom

test('basic DOM', () => {
  const el = document.createElement('div')
  el.className = 'test'
  expect(el.className).toBe('test')
})

Multiple Environments per Project

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',
        },
      },
    ],
  },
})

Custom Environment

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',
  },
})

Environment with VM

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() {} }
  },
}

Browser Mode (Separate from Environments)

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 exact/strict by default (getByText('Item') no longer matches Item 1). browser.api is deprecated — move it to the top-level api option. Browser mode adds a built-in Trace View (browser.traceView: true).

CSS and Assets

In jsdom/happy-dom, configure CSS handling:

defineConfig({
  test: {
    css: true, // Process CSS

    // Or with options
    css: {
      include: /\.module\.css$/,
      modules: {
        classNameStrategy: 'non-scoped',
      },
    },
  },
})

Fixing External Dependencies

If external deps fail with CSS/asset errors:

defineConfig({
  test: {
    server: {
      deps: {
        inline: ['problematic-package'],
      },
    },
  },
})

Key Points

  • Default is node - no browser APIs
  • Use jsdom for full browser simulation
  • Use happy-dom for faster tests with basic DOM
  • Per-file environment via // @vitest-environment comment
  • Use projects for multiple environment configurations
  • Browser Mode is for real browser testing, not environment