browser(实验性)
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;
screenshotFailures?: boolean;
port?: number;
viewport?: BrowserViewport;
strictPort?: boolean;
providerOptions?: Record<string, unknown>;
expect?: {
toMatchScreenshot?: {
comparatorOptions?: {
threshold?: number;
maxDiffPixels?: number;
maxDiffPixelRatio?: number;
};
stabilityTimeout?: number;
maskColor?: string;
style?: string;
caret?: 'hide' | 'initial';
scale?: 'css' | 'device';
omitBackground?: boolean;
screenshotDirectory?: string;
resolveScreenshotPath?: (options: BrowserScreenshotPathOptions) => string;
};
};
};
type BrowserScreenshotPathOptions = {
testFilePath: string;
projectName: string;
testName: string;
browserName: 'chromium' | 'firefox' | 'webkit';
platform: string;
screenshotAssertionOrdinal?: number;
};
const defaultBrowser = {
enabled: false,
provider: 'playwright',
browser: 'chromium',
headless: true, // CI 环境;本地开发为 false
screenshotFailures: true, // 默认与 headless 设置一致
port: undefined, // 随机可用端口
viewport: undefined, // Browser UI 填满预览面板
strictPort: false,
providerOptions: {},
};
浏览器模式配置。启用后,测试将在真实浏览器中运行,而非 Node.js 环境。
选项
screenshotFailures
每个失败的浏览器测试都会保存一张 PNG 截图,默认值与 headless 设置一致。截图位于项目根目录下的 .rstest/screenshots/,文件名包含测试文件和测试名称。设为 false 可关闭截图。
- 类型:
boolean
- 默认值:
browser.headless
- CLI:
--browser.screenshotFailures
enabled
- 类型:
boolean
- 默认值:
false
- CLI:
--browser、--browser.enabled
启用浏览器模式。
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
},
});
Tip
启用浏览器模式需要安装 @rstest/browser 包和 Playwright 浏览器。
npm add @rstest/browser -D
npx playwright install chromium
provider
- 类型:
'playwright'
- 默认值:
'playwright'
浏览器驱动提供者。目前仅支持 Playwright。
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
},
});
browser
- 类型:
'chromium' | 'firefox' | 'webkit'
- 默认值:
'chromium'
- CLI:
--browser.name <name>
用于测试的浏览器类型。
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',
},
});
使用前需要安装对应的浏览器:
# 安装 Chromium
npx playwright install chromium
# 安装 Firefox
npx playwright install firefox
# 安装 WebKit
npx playwright install webkit
# 安装所有浏览器
npx playwright install
headless
- 类型:
boolean
- 默认值: CI 环境为
true,本地开发为 false
- CLI:
--browser.headless
是否以无界面模式运行浏览器。
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
headless: true,
},
});
# .github/workflows/test.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install
- run: npx playwright install chromium
- run: npm test
在本地开发时,设置 headless: false 可以看到浏览器窗口,便于调试。
根据环境动态配置
如果你希望本地调试时使用 headed 模式,CI 中使用 headless,可以通过环境变量控制:
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
headless: process.env.CI === 'true',
},
});
viewport
- 类型:
BrowserViewport
- 默认值:
undefined
设置 Browser Mode 测试的默认 runner iframe viewport。如果未指定,Browser UI 会填满预览面板。
type BrowserViewport =
| {
width: number;
height: number;
}
| DevicePreset;
如果你希望一个 browser 项目中的所有文件都使用同一个 viewport,可以显式指定尺寸:
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
viewport: { width: 390, height: 844 },
},
});
你也可以使用内置设备 preset:
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
viewport: 'iPhone12Pro',
},
});
支持的 preset:
Tip
browser.viewport 控制测试 runner iframe 的 viewport。如果你需要 Playwright context 选项,例如 locale、color scheme 或 permissions,请通过 providerOptions.context 配置。
port
- 类型:
number
- 默认值:
undefined(自动选择可用端口)
- CLI:
--browser.port <port>
浏览器模式 Dev Server 的端口号。
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
port: 5173,
},
});
如果指定了 port 且端口已被占用,是否报错由 strictPort 控制:当 strictPort: true 时会报错退出;当 strictPort: false 时会尝试使用其他可用端口。如果未指定 port,则始终会自动选择一个可用端口。
strictPort
- 类型:
boolean
- 默认值:
false
- CLI:
--browser.strictPort
当指定 port 时,是否要求端口必须可用:
true:如果端口被占用则直接报错退出
false:如果端口被占用则自动回退到其他可用端口
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
port: 5173,
strictPort: true,
},
});
providerOptions
- 类型:
Record<string, unknown>
- 默认值:
{}
- CLI:
--browser.providerOptions.*
传递给 Playwright 浏览器启动和 context 创建过程的选项。Rstest 不会验证或解析该对象,而是将值原样转发给 Playwright。
支持的字段详见下方 Playwright provider 选项。
rstest.config.ts
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
providerOptions: {
launch: {
timeout: 60_000,
},
},
},
});
也可以通过 CLI 传入嵌套的 Playwright 选项:
npx rstest --browser.providerOptions.launch.channel=chrome
expect.toMatchScreenshot
- 类型:
BrowserScreenshotMatcherConfig
- 默认值:
{
comparatorOptions: {
threshold: 0.1,
maxDiffPixels: 0,
},
stabilityTimeout: 2000,
maskColor: '#FF00FF',
caret: 'hide',
scale: 'device',
omitBackground: false,
}
maxDiffPixelRatio 的默认值同样为 0;如需按比例设置容差,请用它替代 maxDiffPixels。默认不注入额外的 style,也不遮罩任何元素;mask 仅支持在断言中配置。
为 Browser Mode 项目中的 toMatchScreenshot() 配置全局默认值。像素比较容差配置在 comparatorOptions 下;截图和路径选项与它同级。单次断言传入的值会覆盖对应的全局值。mask 仍需在断言中单独传入,因为它需要浏览器中的 Locator 对象。
省略选项时会使用以下默认行为。maskColor、caret、scale 和 omitBackground 的截图默认值由 Playwright 提供。
comparatorOptions.maxDiffPixels 和 comparatorOptions.maxDiffPixelRatio 只能配置其中一个。相对路径的 screenshotDirectory 从各测试文件所在目录解析;未配置时默认为 __screenshots__。共用同一截图目录时,Rstest 会按项目名和测试文件隔离基线,切换 checkout 后路径仍保持稳定。如果所选目录就是测试文件所在目录,基线会存入其中的 __screenshots__ 子目录。
默认路径如下:
<测试文件目录>/__screenshots__/<测试文件名>/<基线名>-<浏览器>-<平台>.png
基线名来自显式传入的名称或测试名,并会转换为适合文件系统的路径;可能因清理规则产生冲突的名称会追加稳定后缀。每个未命名断言都会从 1 开始编号,即使测试中只有一张截图,例如 <测试名>-1。显式命名的断言不加序号。
默认路径不包含项目名,因此测试文件、截图名、浏览器和平台相同的项目会共用一份基线。如需按项目隔离基线,可通过 resolveScreenshotPath 自定义路径。Rstest 旧哈希布局中的基线不会自动迁移;请将其移动到新路径,或使用 --update 重新生成。
如需自定义路径布局,可使用 resolveScreenshotPath。回调会收到测试文件绝对路径、项目名、测试名、浏览器、平台,以及未命名断言使用的可选序号。第一个未命名断言不传序号,后续断言从 2 开始。返回绝对路径或相对于项目根目录的路径。配置此回调后,它的优先级高于 screenshotDirectory。
rstest.config.ts
import path from 'node:path';
import { defineConfig } from '@rstest/core';
export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
expect: {
toMatchScreenshot: {
comparatorOptions: {
threshold: 0.1,
maxDiffPixels: 10,
},
resolveScreenshotPath: ({
testFilePath,
projectName,
testName,
browserName,
platform,
}) =>
path.join(
'visual-baselines',
projectName,
path.relative(process.cwd(), testFilePath),
`${testName}-${browserName}-${platform}.png`,
),
},
},
},
});
当前限制:同一次 run 的 browser 启动配置必须一致
在一个 rstest 进程内,所有启用 Browser Mode 的项目需要共享同一组 browser 启动配置:
provider
browser
headless
providerOptions
同一次 run 中的所有 Browser Mode 项目共用一个 browser engine,因此 Chromium、Firefox 和 WebKit 需要分开执行。
如果你需要跨浏览器覆盖,建议拆成多次执行(例如在 CI matrix 中分别跑):
npx rstest --browser.name chromium
npx rstest --browser.name firefox
npx rstest --browser.name webkit
多项目配置隔离
在 Browser Mode 下使用 projects 时,每个项目会按自己的构建配置独立编译和执行(如 plugins、include、框架设置),不会复用其他项目的构建配置。
但 browser 启动配置仍需保持一致:provider、browser、headless、providerOptions 必须在所有 browser 项目中对齐。
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',
},
});
与 Node 测试混合
可以同时配置浏览器测试和 Node.js 测试:
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 选项
Playwright
使用 provider: 'playwright' 时,Playwright provider 识别 providerOptions 中的以下字段:
launch — 传递给 Playwright browserType.launch(),控制浏览器进程的启动方式。
context — 传递给 Playwright browser.newContext(),控制每个测试文件创建的 browser context。
由于 providerOptions 的类型是 Record<string, unknown>,默认不会提供 IntelliSense。如需类型检查和自动补全,可以直接从 playwright 包导入类型,并配合 TypeScript 的 satisfies 运算符使用:
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,
},
});
相关链接
- 浏览器模式指南 - 浏览器模式介绍和使用指南
- 快速开始 - 配置浏览器模式测试
- 浏览器交互 - 使用
page + expect.element 编写语义化测试