Skip to content

Browser Mode Experimental

This page provides information about the experimental browser mode feature in the Vitest API, which allows you to run your tests in the browser natively, providing access to browser globals like window and document. This feature is currently under development, and APIs may change in the future.

Installation

For easier setup, you can use vitest init browser command to install required dependencies and create browser configuration.

bash
npx vitest init browser
bash
yarn exec vitest init browser
bash
pnpx vitest init browser
bash
bunx vitest init browser

Manual Installation

You can also install packages manually. By default, Browser Mode doesn't require any additional E2E provider to run tests locally because it reuses your existing browser.

bash
npm install -D vitest @vitest/browser
bash
yarn add -D vitest @vitest/browser
bash
pnpm add -D vitest @vitest/browser
bash
bun add -D vitest @vitest/browser

WARNING

However, to run tests in CI you need to install either playwright or webdriverio. We also recommend switching to either one of them for testing locally instead of using the default preview provider since it relies on simulating events instead of using Chrome DevTools Protocol.

Using Playwright

bash
npm install -D vitest @vitest/browser playwright
bash
yarn add -D vitest @vitest/browser playwright
bash
pnpm add -D vitest @vitest/browser playwright
bash
bun add -D vitest @vitest/browser playwright

Using Webdriverio

bash
npm install -D vitest @vitest/browser webdriverio
bash
yarn add -D vitest @vitest/browser webdriverio
bash
pnpm add -D vitest @vitest/browser webdriverio
bash
bun add -D vitest @vitest/browser webdriverio

Configuration

To activate browser mode in your Vitest configuration, you can use the --browser flag or set the browser.enabled field to true in your Vitest configuration file. Here is an example configuration using the browser field:

ts
export default defineConfig({
  test: {
    browser: {
      provider: 'playwright', // or 'webdriverio'
      enabled: true,
      name: 'chrome', // browser name is required
    },
  }
})

If you have not used Vite before, make sure you have your framework's plugin installed and specified in the config. Some frameworks might require extra configuration to work - check their Vite related documentation to be sure.

ts
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chrome',
    }
  }
})
ts
import { defineConfig } from 'vitest/config'
import { svelte } from '@sveltejs/vite-plugin-svelte'

export default defineConfig({
  plugins: [svelte()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chrome',
    }
  }
})
ts
import { defineConfig } from 'vitest/config'
import solidPlugin from 'vite-plugin-solid'

export default defineConfig({
  plugins: [solidPlugin()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chrome',
    }
  }
})
ts
import { defineConfig } from 'vitest/config'
import marko from '@marko/vite'

export default defineConfig({
  plugins: [marko()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chrome',
    }
  }
})

TIP

react doesn't require a plugin to work, but preact requires extra configuration to make aliases work.

If you need to run some tests using Node-based runner, you can define a workspace file with separate configurations for different testing strategies:

ts
// vitest.workspace.ts
import { defineWorkspace } from 'vitest/config'

export default defineWorkspace([
  {
    test: {
      // an example of file based convention,
      // you don't have to follow it
      include: [
        'tests/unit/**/*.{test,spec}.ts',
        'tests/**/*.unit.{test,spec}.ts',
      ],
      name: 'unit',
      environment: 'node',
    },
  },
  {
    test: {
      // an example of file based convention,
      // you don't have to follow it
      include: [
        'tests/browser/**/*.{test,spec}.ts',
        'tests/**/*.browser.{test,spec}.ts',
      ],
      name: 'browser',
      browser: {
        enabled: true,
        name: 'chrome',
      },
    },
  },
])

Browser Option Types

The browser option in Vitest depends on the provider. Vitest will fail, if you pass --browser and don't specify its name in the config file. Available options:

  • webdriverio supports these browsers:
    • firefox
    • chrome
    • edge
    • safari
  • playwright supports these browsers:
    • firefox
    • webkit
    • chromium

Browser Compatibility

Vitest uses Vite dev server to run your tests, so we only support features specified in the esbuild.target option (esnext by default).

By default, Vite targets browsers which support the native ES Modules, native ESM dynamic import, and import.meta. On top of that, we utilize BroadcastChannel to communicate between iframes:

  • Chrome >=87
  • Firefox >=78
  • Safari >=15.4
  • Edge >=88

Motivation

We developed the Vitest browser mode feature to help improve testing workflows and achieve more accurate and reliable test results. This experimental addition to our testing API allows developers to run tests in a native browser environment. In this section, we'll explore the motivations behind this feature and its benefits for testing.

Different Ways of Testing

There are different ways to test JavaScript code. Some testing frameworks simulate browser environments in Node.js, while others run tests in real browsers. In this context, jsdom is an example of a spec implementation that simulates a browser environment by being used with a test runner like Jest or Vitest, while other testing tools such as WebdriverIO or Cypress allow developers to test their applications in a real browser or in case of Playwright provide you a browser engine.

The Simulation Caveat

Testing JavaScript programs in simulated environments such as jsdom or happy-dom has simplified the test setup and provided an easy-to-use API, making them suitable for many projects and increasing confidence in test results. However, it is crucial to keep in mind that these tools only simulate a browser environment and not an actual browser, which may result in some discrepancies between the simulated environment and the real environment. Therefore, false positives or negatives in test results may occur.

To achieve the highest level of confidence in our tests, it's crucial to test in a real browser environment. This is why we developed the browser mode feature in Vitest, allowing developers to run tests natively in a browser and gain more accurate and reliable test results. With browser-level testing, developers can be more confident that their application will work as intended in a real-world scenario.

Drawbacks

When using Vitest browser, it is important to consider the following drawbacks:

Early Development

The browser mode feature of Vitest is still in its early stages of development. As such, it may not yet be fully optimized, and there may be some bugs or issues that have not yet been ironed out. It is recommended that users augment their Vitest browser experience with a standalone browser-side test runner like WebdriverIO, Cypress or Playwright.

Longer Initialization

Vitest browser requires spinning up the provider and the browser during the initialization process, which can take some time. This can result in longer initialization times compared to other testing patterns.

Cross-Browser Testing

When you specify a browser name in the browser option, Vitest will try to run the specified browser using WebdriverIO by default, and then run the tests there. This feature makes cross-browser testing easy to use and configure in environments like a CI. If you don't want to use WebdriverIO, you can configure the custom browser provider by using browser.provider option.

To specify a browser using the CLI, use the --browser flag followed by the browser name, like this:

sh
npx vitest --browser=chrome

Or you can provide browser options to CLI with dot notation:

sh
npx vitest --browser.name=chrome --browser.headless

Headless

Headless mode is another option available in the browser mode. In headless mode, the browser runs in the background without a user interface, which makes it useful for running automated tests. The headless option in Vitest can be set to a boolean value to enable or disable headless mode.

Here's an example configuration enabling headless mode:

ts
export default defineConfig({
  test: {
    browser: {
      provider: 'playwright',
      enabled: true,
      headless: true,
    },
  }
})

You can also set headless mode using the --browser.headless flag in the CLI, like this:

sh
npx vitest --browser.name=chrome --browser.headless

In this case, Vitest will run in headless mode using the Chrome browser.

WARNING

Headless mode is not available by default. You need to use either playwright or webdriverio providers to enable this feature.

Limitations

Thread Blocking Dialogs

When using Vitest Browser, it's important to note that thread blocking dialogs like alert or confirm cannot be used natively. This is because they block the web page, which means Vitest cannot continue communicating with the page, causing the execution to hang.

In such situations, Vitest provides default mocks with default returned values for these APIs. This ensures that if the user accidentally uses synchronous popup web APIs, the execution would not hang. However, it's still recommended for the user to mock these web APIs for better experience. Read more in Mocking.

Released under the MIT License.