ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Vitest @vitest/browser-playwright:用 Playwright Provider 运行浏览器测试的原理与配置详解

Vitest @vitest/browser-playwright:用 Playwright Provider 运行浏览器测试的原理与配置详解 Vitest vitest/browser-playwright用 Playwright Provider 运行浏览器测试的原理与配置详解【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest本篇围绕 Vitest 官方 Playwright 浏览器 Provider 包vitest/browser-playwright展开它只负责“把浏览器跑起来”browser provider而非替代 Playwright 测试框架。读完本文你将掌握该包的完整安装与browser.provider配置方式、五个 Provider 选项launchOptions、connectOptions、contextOptions、actionTimeout、persistentContext的取值语义与默认行为以及从源码层面理解浏览器预热prewarm、按测试文件隔离 Context/Page、基于 Playwright 路由拦截的模块 Mock 机制等底层实现。定位是浏览器 Provider不是测试运行器packages/browser-playwright/README.md开宗明义Run your Vitest browser tests using playwright API. Note that Vitest does not use playwright as a test runner, but only as a browser provider.也就是说Vitest 仍然用自己的describe/it执行测试、做断言与报告Playwright 在这里的角色是浏览器驱动层——负责启动浏览器进程、创建 Context/Page、执行点击/填写/截图等交互命令、拦截请求以支持模块 Mock。官方给出的选型建议是如果你的项目已经在用 Playwright或者还没有 E2E 测试框架推荐使用这个包。从包元信息可以确认其定位packages/browser-playwright/package.json版本5.0.0ESM 包type: module导出入口为./dist/index.js另有./context子路径仅导出类型声明packages/browser-playwright/context.d.ts 只做export * from vitest/browser/contextpeerDependencies中playwright为必需optional: falsevitest为同 workspace 版本——说明它必须与 Playwright 本体共同安装才能复用其浏览器驱动dependencies中的vitest/browser、vitest/mocker说明它与 Vitest 浏览器层和 Mock 引擎强耦合。安装使用你喜欢的包管理器安装继承自 packages/browser-playwright/README.mdnpm install -D vitest/browser-playwright # or yarn add -D vitest/browser-playwright # or pnpm add -D vitest/browser-playwright注意还需要安装playwright本身peer dependency并按 Playwright 的常规流程安装浏览器内核如npx playwright install。基本配置browser.provider与--browser运行在 Vitest 配置的browser.provider字段指定playwright()工厂的返回值并通过browser.instances声明要跑的浏览器packages/browser-playwright/README.md// vitest.config.ts import { defineConfig } from vitest/config import { playwright } from vitest/browser-playwright export default defineConfig({ test: { browser: { provider: playwright({ // ...custom playwright options }), instances: [ { browser: chromium }, ], }, }, })随后以浏览器模式运行npx vitest --browser该写法与全局配置文档 docs/config/browser/provider.md 一致browser.provider的类型是BrowserProviderOption即 Provider 工厂的返回值你也可以像webdriverio()、preview()一样换成其他 Provider 工厂配置结构不变。Provider 支持共享选项 按实例覆盖顶层provider的选项对所有实例生效单个实例内再写provider: playwright({...})时是整体覆盖而非合并docs/config/browser/playwright.mdimport { playwright } from vitest/browser-playwright import { defineConfig } from vitest/config export default defineConfig({ test: { browser: { // shared provider options between all instances provider: playwright({ launchOptions: { slowMo: 50, channel: chrome-beta, }, actionTimeout: 5_000, }), instances: [ { browser: chromium }, { browser: firefox, // overriding options only for a single instance // this will NOT merge options with the parent one provider: playwright({ launchOptions: { firefoxUserPrefs: { browser.startup.homepage: https://example.com, }, }, }), }, ], }, }, })五个 Provider 选项详解PlaywrightProviderOptions的完整定义在 packages/browser-playwright/src/playwright.ts共五个字段逐一说明launchOptions透传给playwright[browser].launch()源码中做了OmitLaunchOptions, tracesDir处理。常用项如channel、slowMo、args、firefoxUserPrefs均可直接使用。两个重要约束docs/config/browser/playwright.mdVitest 会忽略launch.headless无头/有头统一由test.browser.headless控制。源码印证了这一点——resolveLaunchOptions在展开用户传入的launchOptions之后会用browser.headless覆盖headless字段playwright.ts#L193-L227。开启--inspect时Vitest 会向launch.args追加--remote-debugging-portport默认 9229且 Chromium 只允许 localhost 远程调试非 localhost 的 inspector host 会被忽略并给出警告playwright.ts#L304-L312。另外若配置了browser.ui且浏览器为 chromium源码会自动追加--start-maximized让 Vitest UI 以最大化窗口打开playwright.ts#L217-L224。connectOptions透传给playwright[browser].connect()并在其基础上要求必须提供wsEndpoint类型定义为ConnectOptions { wsEndpoint: string }。用于连接已有的 Playwright 服务端playwright run-server典型场景是把浏览器放进 Docker/CI/远端机器。一个关键细节Vitest 会把自己的启动参数 JSON 序列化后塞进x-playwright-launch-options请求头转发给远端playwright.ts#L316-L334如果你自己在 headers 里已带了该键则说明远端自行控制启动参数Vitest 只会打印黄色警告而不覆盖。contextOptions透传给browser.newContext()。类型上Omit掉了ignoreHTTPSErrors和serviceWorkers——因为源码getContextOptions中强制ignoreHTTPSErrors: trueplaywright.ts#L551-L565以兼容 HTTPS 部署同时当开启 UI 且非 headless 时会强制viewport null让页面采用真实窗口尺寸避免无头/有头两种模式截图产生 deviceScaleFactor 差异。官方还建议 viewport 优先用test.browser.viewport配置而不是写在这里。actionTimeout默认0不超时源码中表现为context.setDefaultTimeout(actionTimeout)仅在非 null 时设置playwright.ts#L543-L545。该值控制 Playwright 等待可访问性检查通过、交互动作真正完成的最长时间。也可以逐次动作覆盖import { page, userEvent } from vitest/browser await userEvent.click(page.getByRole(button), { timeout: 1_000, })persistentContext类型boolean | string默认false4.1.0 引入。启用后改用launchPersistentContext启动浏览器使 cookies、localStorage、DevTools 设置等状态在多次测试运行间保留设为true用户数据目录为./node_modules/.cache/vitest-playwright-user-data设为字符串作为自定义用户数据目录路径。源码中的处理逻辑playwright.ts#L336-L357若测试并行运行如 headless 且开启fileParallelism该选项会被静默降级为false并打印警告因为持久化 Context 无法在并行会话间共享。export default defineConfig({ test: { browser: { provider: playwright({ persistentContext: true, // or specify a custom directory: // persistentContext: ./my-browser-data, }), instances: [{ browser: chromium }], }, }, })支持哪些浏览器源码中硬编码了支持列表playwright.ts#L41const playwrightBrowsers [firefox, webkit, chromium] as constplaywright()工厂通过defineBrowserProvider声明了name: playwright与supportedBrowser: playwrightBrowsersplaywright.ts#L94-L106。因此instances中这三个值均可用若配置了connectOptions之外的远端方案也可以借此列表之外的浏览器名工厂会原样调用playwright[browserName]。源码深读一启动链路、预热与 Context/Page 生命周期PlaywrightBrowserProvider类playwright.ts#L229是核心几个值得注意的实现事实1. 支持文件级并行。supportsParallelism true表明该 Provider 已加入 Vitest 的并行实验特性这也是persistentContext在并行下被禁用的原因。2. 浏览器预热prewarm。源码维护了两个WeakMapwarmBrowsers按解析后的 browser 配置键控、pendingWarmBrowsers按 vitest 实例键控playwright.ts#L121-L124。prewarm()在 Node 端还在创建 Vite dev server 时就提前import(playwright)并发起launch把浏览器启动延迟与 Vite 启动时间重叠。安全性由一条规则保证预热与真实启动用同一函数resolveLaunchOptions计算启动参数真实打开时若两份参数 JSON 不一致或预热失败预热的浏览器实例会被丢弃/关闭、走正常启动路径重试playwright.ts#L359-L372。注意connectOptions、persistentContext、inspector 开启三种情况会跳过预热。3. 一个 Context/Page 对应一个测试文件。createContext(sessionId, ...)以会话 ID即测试文件维度为键缓存 Contextplaywright.ts#L524-L549官方文档也明确警告与 Playwright 测试框架不同Vitest 为同一测试文件中的所有测试打开同一个 Page隔离粒度是测试文件而非单个测试docs/config/browser/playwright.md。重开同一 sessionId 的 Page 时旧 Page 会先close()再创建新 Pageplaywright.ts#L608-L616。4. 崩溃与信号兜底。Page 触发crash事件时Vitest 会把归因明确的错误“页面崩溃可能是浏览器内存耗尽”直接 fail 给对应会话而不是留成一个模糊的 WebSocket 断连playwright.ts#L626-L630。构造函数中还注册了SIGTERM监听在进程被杀时尽力把未完成的 tracing chunk 落盘playwright.ts#L262-L278close()时按 Page → Context或 persistentContext→ Browser 的顺序级联关闭。5. Service Worker 网络拦截。模块顶部有一行process.env.PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS ?? 1playwright.ts#L44-L46。注释说明这是 Playwright 的实验性 API仅 Chromium 系可用目的是让 Service Worker 发出的请求也能被context.route()拦截——这是 Mock Service WorkerMSW等基于 SW 的网络 Mock 方案在 Vitest 浏览器模式下能工作的底层前提。源码深读二模块 Mock 如何实现Vitest 的浏览器模块 Mock 依赖“请求拦截 路由改写”。createMocker()返回register/delete/clear三个方法playwright.ts#L382-L522核心机制精确匹配 URLcreatePredicate用模块 URL 构造谓词先剔除t、v、import等缓存/内部查询参数再逐参数比较避免对同一模块的不同变体误拦截manual mock直接route.fulfill一段由vitest/mocker/node的createManualModuleSource生成的 JS 源码automock / autospyroute.fulfill({ status: 302, Location: 原URL?mocktype })用 302 重定向让浏览器带 mock 标记重新请求由 Vitest 的 Vite 转换管线返回自动 Mock 版本redirect mock同样以 302 转发到module.redirectwebkit 特判由于 WebKit 不支持路由重定向响应Playwright 已知限制webkit 分支改为通过vite.transformRequest直接拿到转换后代码、内联 base64 source map 后fulfillplaywright.ts#L446-L474。register之前若同一 sessionId 已有旧谓词会先unroute再替换保证 mock 的增删清语义与 Node 环境一致。源码深读三交互命令与 Locator 扩展命令注册。Provider 构造函数遍历commands对象把 24 个以__vitest_前缀的命令注册到当前 TestProjectplaywright.ts#L258-L260。命令清单见 packages/browser-playwright/src/commands/index.ts点击/双击/三击__vitest_click等、填写/输入/清空fill/type/clear、拖拽dragAndDrop、悬停hover、滚轮wheel、键盘keyboard/cleanup、选项选择selectOptions、Tab 切换、文件上传upload、视口viewport、截图takeScreenshot以及一组 tracing 命令startTracing/startChunkTrace/stopChunkTrace/markTrace/annotateTraces/groupTraceStart/groupTraceEnd/deleteTracing——对应 Vitest 的 Playwright Traces 集成。Locator 体系。浏览器端初始化脚本dist/locators.js由 packages/browser-playwright/src/locators.ts 构建Provider 的initScripts在 playwright.ts#L247-L249 声明。PlaywrightLocator继承自vitest/browser/locators的通用Locator并借助page.extend暴露getByRole、getByTestId、getByText、getByLabel、getByAltText、getByPlaceholder、getByTitle、elementLocator、frameLocator等 API——这就是测试中page.getByRole(button)的来源。其中getByTestId的测试 ID 属性名取自browser.locators.testIdAttribute配置。一个体现 iframe 细节的实现定位器支持与internal:controlenter-frame的 Playwright 选择器拼接而position类参数在 click/hover/dragAndDrop 时会乘以getIframeScale()换算坐标locators.ts#L129-L138因为 Vitest 浏览器测试实际运行在页面内的 iframe 中UI 缩放会改变坐标比例。类型系统整合。declare module vitest/browser把UserEventClickOptions、ScreenshotOptions等接口扩展为 Playwright 原生类型如Page[click]的参数类型所以你可以把 Playwright 文档里的所有点击/悬停/截图参数直接写进userEvent调用declare module vitest/node则声明了 Provider 给命令上下文的page/frame()/iframe/context四件套playwright.ts#L750-L799并在_BrowserNames中注册playwright浏览器名。调试技巧从源码还能挖出两个实用的调试入口VITEST_PW_DEBUG环境变量设置后每个 Page 会监听requestfailed事件把失败请求的资源类型、URL 与错误文本打印到控制台playwright.ts#L632-L643适合排查容器/网络类问题inspector 远程调试--inspect运行后控制台会输出Debugger listening on ws://127.0.0.1:9229可用 DevTools 附加到测试浏览器playwright.ts#L303-L312。小结vitest/browser-playwright的价值在于把 Playwright 作为可替换的浏览器驱动接入 Vitest五个选项覆盖启动、远端连接、Context、交互超时与持久化状态底层通过“每测试文件一个 Context/Page”实现隔离通过context.route()的 302 重定向/直接 fulfill 实现与 Node 环境一致的模块 Mock并通过浏览器预热、tracing 命令、CSP 式请求头注入等工程细节保证体验。相关文档入口为 docs/config/browser/playwright.md 与 docs/config/browser/provider.md完整实现集中在 packages/browser-playwright/src/playwright.ts。【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表