close

testEnvironment

  • Type: 'node' | 'jsdom' | 'happy-dom' | string | { name: EnvironmentName, options?: EnvironmentOptions }
  • Default: 'node'
  • CLI: --testEnvironment=node

The environment that will be used for testing.

The default environment in Rstest is a Node.js environment. If you are building a web application, you can use a browser-like environment through jsdom or happy-dom instead.

CLI
rstest.config.ts
npx rstest --testEnvironment=jsdom

DOM testing

Rstest supports jsdom and happy-dom for mocking DOM and browser APIs.

If you want to enable DOM testing, you can use the following configuration:

rstest.config.ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
  testEnvironment: 'jsdom', // or 'happy-dom'
});

You also need to install the corresponding package:

For jsdom

npm
yarn
pnpm
bun
deno
npm add jsdom -D

For happy-dom

npm
yarn
pnpm
bun
deno
npm add happy-dom -D

After enabling DOM testing, you can write tests that use browser APIs like document and window.

test('DOM test', () => {
  document.body.innerHTML = '<p class="content">hello world</p>';
  const paragraph = document.querySelector('.content');
  expect(paragraph?.innerHTML).toBe('hello world');
});

Environment options

You can also pass options to the test environment. This is useful for configuring jsdom or happy-dom. For example, you can set the url for jsdom:

rstest.config.ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
  testEnvironment: {
    name: 'jsdom',
    options: {
      // jsdom-specific options
      url: 'https://example.com',
    },
  },
});

The options object is passed directly to the environment's constructor.

  • For jsdom, it's passed to the JSDOM constructor. You can find available options in the jsdom documentation.
  • For happy-dom, it's passed to the Window constructor. You can find available options in the happy-dom documentation.

Custom environments

Rstest also supports custom environments through testEnvironment.name.

  • Use a package name.
  • Use a relative or absolute JavaScript file path such as .js or .mjs.
  • For package names, testEnvironment: 'foo' also tries to resolve rstest-environment-foo.

Custom environments should export an environment object as the default export or as a named environment export.

my-environment.mjs
import { builtinEnvironments } from '@rstest/core';

/** @type {import('@rstest/core').TestEnvironment<typeof globalThis, { marker: string }>} */
const environment = {
  name: 'custom-jsdom',
  async setup(global, options) {
    const base = await builtinEnvironments.jsdom.setup(global, {
      url: 'https://example.com',
    });

    global.__MARKER__ = options.marker;

    return {
      async teardown() {
        delete global.__MARKER__;
        await base.teardown();
      },
    };
  },
};

export default environment;
rstest.config.ts
import { defineConfig } from '@rstest/core';

export default defineConfig({
  testEnvironment: {
    name: './my-environment.mjs',
    options: {
      marker: 'custom-marker',
    },
  },
});

@rstest/core exports builtinEnvironments so you can extend node, jsdom, or happy-dom instead of rebuilding them from scratch.

Rstest currently loads custom environment files as JavaScript modules. Direct .ts custom environment file paths are not supported yet. If you want type checking, write the environment in TypeScript and compile it to .mjs or .js, or use JSDoc types in a JavaScript file.

Rstest temporarily does not support file-level @vitest-environment or @jest-environment comments. If you need per-file environment switching, use separate projects or config files for now.

Custom environment vs setupFiles

Use a custom environment when you need to define or wrap the host runtime itself for each test file.

  • Switching or extending node, jsdom, or happy-dom.
  • Creating globals before test modules execute.
  • Managing environment-level teardown, such as closing a browser-like runtime or cleaning injected globals.

Use setupFiles when the environment is already correct and you only need to configure the test runtime inside it.

  • Registering matchers such as @testing-library/jest-dom.
  • Installing fake timers, serializers, mocks, or hooks.
  • Running project-level initialization code that depends on the selected environment already being available.

In short: testEnvironment decides what globals and host APIs exist; setupFiles configures how your tests use that environment.

Examples