close
  • English
  • browser (experimental)

    • Type:
    type BrowserViewport =
      | {
          width: number;
          height: number;
        }
      | DevicePreset;
    
    type DevicePreset =
      | 'iPhoneSE'
      | 'iPhoneXR'
      | 'iPhone12Pro'
      | 'iPhone14ProMax'
      | 'Pixel7'
      | 'SamsungGalaxyS8Plus'
      | 'SamsungGalaxyS20Ultra'
      | 'iPadMini'
      | 'iPadAir'
      | 'iPadPro'
      | 'SurfacePro7'
      | 'SurfaceDuo'
      | 'GalaxyZFold5'
      | 'AsusZenbookFold'
      | 'SamsungGalaxyA51A71'
      | 'NestHub'
      | 'NestHubMax';
    
    type BrowserModeConfig = {
      enabled?: boolean;
      provider: 'playwright';
      browser?: 'chromium' | 'firefox' | 'webkit';
      headless?: boolean;
      port?: number;
      viewport?: BrowserViewport;
      strictPort?: boolean;
      providerOptions?: Record<string, unknown>;
    };
    • Default:
    const defaultBrowser = {
      enabled: false,
      provider: 'playwright',
      browser: 'chromium',
      headless: true, // CI environment; false for local development
      port: undefined, // Random available port
      viewport: undefined, // Browser UI fills the preview panel
      strictPort: false,
      providerOptions: {},
    };

    Browser Mode configuration. When enabled, tests run in a real browser instead of the Node.js environment.

    Options

    enabled

    • Type: boolean
    • Default: false
    • CLI: --browser, --browser.enabled

    Enable Browser Mode.

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
      },
    });
    Tip

    Enabling Browser Mode requires installing the @rstest/browser package and Playwright browsers.

    npm add @rstest/browser -D
    npx playwright install chromium

    provider

    • Type: 'playwright'
    • Default: 'playwright'

    Browser driver provider. Currently only Playwright is supported.

    Mixing multiple providers in the same test run is currently not supported.

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
      },
    });

    browser

    • Type: 'chromium' | 'firefox' | 'webkit'
    • Default: 'chromium'
    • CLI: --browser.name <name>

    The browser type to use for testing.

    • chromium - Google Chrome, Microsoft Edge
    • firefox - Mozilla Firefox
    • webkit - Safari
    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        browser: 'firefox',
      },
    });

    You need to install the corresponding browser before use:

    # Install chromium
    npx playwright install chromium
    
    # Install Firefox
    npx playwright install firefox
    
    # Install WebKit
    npx playwright install webkit
    
    # Install all browsers
    npx playwright install

    headless

    • Type: boolean
    • Default: true in CI environments, false for local development
    • CLI: --browser.headless

    Whether to run the browser in headless mode (without UI).

    rstest.config.ts
    CI (GitHub Actions)
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        headless: true,
      },
    });

    During local development, setting headless: false shows the browser window for easier debugging.

    Dynamic Configuration Based on Environment

    If you want headed mode for local debugging and headless in CI, control it with environment variables:

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        headless: process.env.CI === 'true',
      },
    });

    viewport

    • Type: BrowserViewport
    • Default: undefined

    Set the default runner iframe viewport for Browser Mode tests. When not specified, the Browser UI fills the preview panel.

    type BrowserViewport =
      | {
          width: number;
          height: number;
        }
      | DevicePreset;

    Use an explicit size when you want all files in a browser project to run with the same viewport:

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        viewport: { width: 390, height: 844 },
      },
    });

    You can also use a built-in device preset:

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        viewport: 'iPhone12Pro',
      },
    });

    Supported presets:

    PresetSize
    iPhoneSE375 x 667
    iPhoneXR414 x 896
    iPhone12Pro390 x 844
    iPhone14ProMax430 x 932
    Pixel7412 x 915
    SamsungGalaxyS8Plus360 x 740
    SamsungGalaxyS20Ultra412 x 915
    iPadMini768 x 1024
    iPadAir820 x 1180
    iPadPro1024 x 1366
    SurfacePro7912 x 1368
    SurfaceDuo540 x 720
    GalaxyZFold5344 x 882
    AsusZenbookFold853 x 1280
    SamsungGalaxyA51A71412 x 914
    NestHub1024 x 600
    NestHubMax1280 x 800
    Tip

    browser.viewport controls the test runner iframe viewport. If you need Playwright context options such as locale, color scheme, or permissions, configure them through providerOptions.context.

    port

    • Type: number
    • Default: undefined (automatically selects an available port)
    • CLI: --browser.port <port>

    The port number for the Browser Mode Dev Server.

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        port: 5173,
      },
    });

    If you set port and the port is already in use, the behavior is controlled by strictPort: when strictPort: true, Rstest throws an error and exits; when strictPort: false, it falls back to another available port. If port is not specified, an available port is always selected automatically.

    strictPort

    • Type: boolean
    • Default: false
    • CLI: --browser.strictPort

    When port is specified, whether the port must be available:

    • true: throw an error and exit if the port is in use
    • false: fall back to another available port if the port is in use
    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        port: 5173,
        strictPort: true,
      },
    });

    providerOptions

    • Type: Record<string, unknown>
    • Default: {}
    • CLI: --browser.providerOptions.*

    Provider-specific options passed through to the selected browser provider. Rstest does not validate or interpret the contents of this object — it is forwarded as-is to the provider at both browser launch and context creation time.

    The structure of providerOptions is defined by each provider. See the Provider options section below for details.

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        providerOptions: {
          launch: {
            timeout: 60_000,
          },
        },
      },
    });

    You can also pass nested provider options from the CLI:

    npx rstest --browser.providerOptions.launch.channel=chrome

    Current limitation: browser launch options must match in one run

    In one rstest process, all Browser Mode projects must share the same browser launch options:

    • provider
    • browser
    • headless
    • port
    • strictPort
    • providerOptions

    This means mixing multiple providers, or running Chromium/Firefox/WebKit together in the same run, is not supported yet.

    For cross-browser coverage, run tests in separate executions (for example, in a CI matrix):

    npx rstest --browser.name chromium
    npx rstest --browser.name firefox
    npx rstest --browser.name webkit

    Multi-project config isolation

    When using projects in Browser Mode, each project still compiles and executes with its own build config (for example plugins, include, and framework-specific setup).

    Browser launch options still need to stay aligned across browser projects: provider, browser, headless, port, strictPort, and providerOptions.

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      projects: ['./project-b/rstest.config.ts', './project-a/rstest.config.ts'],
    });
    project-a/rstest.config.ts
    import { pluginReact } from '@rsbuild/plugin-react';
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      name: 'project-a',
      plugins: [pluginReact()],
      include: ['tests/**/*.test.tsx'],
      browser: {
        enabled: true,
        provider: 'playwright',
      },
    });

    Mixing with node tests

    You can configure both browser tests and Node.js tests together:

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      projects: [
        {
          name: 'browser',
          include: ['src/**/*.browser.test.ts'],
          browser: {
            enabled: true,
            provider: 'playwright',
          },
        },
        {
          name: 'node',
          include: ['src/**/*.node.test.ts'],
          testEnvironment: 'node',
        },
        {
          name: 'jsdom',
          include: ['src/**/*.test.ts'],
          exclude: ['src/**/*.browser.test.ts', 'src/**/*.node.test.ts'],
          testEnvironment: 'jsdom',
        },
      ],
    });

    Provider options

    Playwright

    When using provider: 'playwright', the Playwright provider recognizes the following fields in providerOptions:

    1. launch — Passed to Playwright's browserType.launch(). Controls how the browser process is started.
    2. context — Passed to Playwright's browser.newContext(). Controls the browser context created for each test file.

    Since providerOptions is typed as Record<string, unknown>, you won't get IntelliSense out of the box. To get type checking and autocompletion, import types directly from the playwright package and use TypeScript's satisfies operator:

    rstest.config.ts
    import type { LaunchOptions, BrowserContextOptions } from 'playwright';
    import { defineConfig } from '@rstest/core';
    
    type PlaywrightProviderOptions = {
      launch?: LaunchOptions;
      context?: BrowserContextOptions;
    };
    
    export default defineConfig({
      browser: {
        enabled: true,
        provider: 'playwright',
        providerOptions: {
          launch: {
            timeout: 60_000,
          },
          context: {
            locale: 'en-US',
            colorScheme: 'dark',
          },
        } satisfies PlaywrightProviderOptions,
      },
    });