BlockNote 开发中的 Playwright 请求 Mocking 完全指南:拦截、改写与故障注入
2026/9/24 17:07:15 网站建设 项目流程
  • 前端
  • 富文本
  • UI组件
  • AI 应用

【免费下载链接】BlockNote

A React Rich Text Editor that's block-based (Notion style) and extensible. Built on top of Prosemirror and Tiptap.

项目地址:https://gitcode.com/gh_mirrors/bl/BlockNote
点击查看免费下载

本指南以 request-mocking.md 为骨架,系统讲解 playwright-cli 的网络请求拦截能力:如何用route命令快速 mock、按 URL 模式匹配、以及通过run-code编写任意复杂的请求处理逻辑。在本仓库(BlockNote)中,这些能力直接服务于 tests/src/end-to-end 下的端到端测试,例如在 images.test.tsx 中通过外部图片 URL 断言图片块的嵌入行为——当真实网络不可用或需要稳定复现时,拦截与 mock 就是让测试确定性的关键手段。读完本文,你将掌握 CLI 级别与代码级别两套请求操控方案,并能把它们落地到自己的 Playwright 测试流程中。

概述:为什么需要请求 Mocking

端到端测试与人工验证中最不稳定的因素往往不是前端逻辑,而是网络:图片加载失败、接口延迟、服务端 500、登录态过期……任何一次外部依赖波动都可能让一次本应通过的验证功亏一篑。请求 Mocking(Request Mocking)的核心思想是:在浏览器发起网络请求之前把它拦截下来,然后按需伪造、修改或直接丢弃,让被测页面始终面对一个确定性的"网络环境"。

playwright-cli 为这一需求提供了两层能力:

  • CLI 命令层route/route-list/unroute,适合快速、临时、低成本的拦截与替换;
  • 代码层run-code+page.route(),适合需要读取请求体、按条件分支、修改真实响应或注入延迟的复杂场景。

快速上手:route 命令基础用法

playwright-cli route是最直接的拦截入口,它的通用形态是:

playwright-cli route <URL模式> [选项]

用自定义状态码 mock

最常见的需求是模拟接口失败。例如让所有 jpg 图片请求返回 404,用于验证图片块的降级渲染:

playwright-cli route "**/*.jpg" --status=404

用 JSON 体 mock

模拟接口返回数据,需要同时指定响应体和 Content-Type。下面的命令让所有/api/users请求固定返回两条用户记录:

playwright-cli route "**/api/users" --body='[{"id":1,"name":"Alice"}]' --content-type=application/json

注意:当--body提供 JSON 字符串时,务必同时给出--content-type=application/json,否则浏览器端按默认 MIME 处理可能解析异常。

带自定义响应头 mock

对于需要验证响应头行为的场景,用--header追加自定义头:

playwright-cli route "**/api/data" --body='{"ok":true}' --header="X-Custom: value"

--header可重复使用,以注入多个响应头。

从请求中剥离敏感头

真实环境下浏览器会带上 Cookie、Authorization 等凭据头。如果要模拟"未登录/匿名访问"场景,可以按头名剥离:

playwright-cli route "**/*" --remove-header=cookie,authorization

多个头名用逗号分隔,该命令会拦截所有请求并移除指定的请求头。

查看与清理路由

  • 列出当前会话中所有生效的路由:
playwright-cli route-list
  • 删除某一条路由:
playwright-cli unroute "**/*.jpg"
  • 不带参数删除全部路由:
playwright-cli unroute

URL 模式语法

route的 URL 模式基于 glob 风格通配符,正确理解它才能精确命中目标请求:

**/api/users - 精确匹配路径(不限域名与端口) **/api/*/details - 路径中的单段通配 **/*.{png,jpg,jpeg} - 匹配多种文件扩展名 **/search?q=* - 匹配带查询参数的地址

要点说明:

  • **匹配任意层级的路径前缀,因此**/api/users可以同时命中https://example.com/api/usershttps://api.example.com/users
  • *只匹配路径中的单段内容;
  • {a,b,c}花括号用于枚举扩展名等备选值;
  • 模式同样适用于查询字符串(如**/search?q=*),可按参数形态精确圈定拦截范围。

在 SKILL.md 的 Network 一节(见 .claude/skills/playwright-cli/SKILL.md)中,还给出了按完整域名限定的示例:playwright-cli route "https://api.example.com/**" --body='{"mock": true}',说明模式既可以松散(**前缀)也可以严格(完整域名)。

进阶:run-code 驱动的动态 Mock

CLI 选项适合"静态替换",但当拦截逻辑依赖请求内容、真实响应或时间时,就需要完整调用 Playwright 的page.route()API。run-code的通用语法如下(详见 running-code.md):

playwright-cli run-code "async page => { // 此处可访问 page 与 page.context() }"

代码必须是一个单一的函数表达式(会被包在(...)中求值),不支持 import/export/require 语法;也可以用--filename=script.js从文件加载。

按请求内容条件返回

下面的示例拦截登录接口,检查请求体中的用户名:admin用户返回伪造 token,其他用户一律 401。这是"读取请求体 → 分支处理"的典型模式:

playwright-cli run-code "async page => { await page.route('**/api/login', route => { const body = route.request().postDataJSON(); if (body.username === 'admin') { route.fulfill({ body: JSON.stringify({ token: 'mock-token' }) }); } else { route.fulfill({ status: 401, body: JSON.stringify({ error: 'Invalid' }) }); } }); }"

修改真实响应(响应透传 + 篡改)

不想完全伪造接口,而是"请求照发、回来改一改",可以使用route.fetch()先取真实响应,再修改后fulfill

playwright-cli run-code "async page => { await page.route('**/api/user', async route => { const response = await route.fetch(); const json = await response.json(); json.isPremium = true; await route.fulfill({ response, json }); }); }"

route.fulfill({ response, json })会把原始响应的状态码与头保留下来,仅替换响应体,非常适合在保留真实接口语义的前提下做 A/B 式注入。

模拟网络故障

直接放弃请求并返回一个"网络层错误",可用于验证应用的错误提示与重试逻辑:

playwright-cli run-code "async page => { await page.route('**/api/offline', route => route.abort('internetdisconnected')); }" # 可选错误码: # connectionrefused - 连接被拒绝 # timedout - 连接超时 # connectionreset - 连接被重置 # internetdisconnected - 模拟断网

注入延迟

模拟慢接口,验证 loading 态与超时处理:

playwright-cli run-code "async page => { await page.route('**/api/slow', async route => { await new Promise(r => setTimeout(r, 3000)); route.fulfill({ body: JSON.stringify({ data: 'loaded' }) }); }); }"

在本仓库中的落地场景

本仓库(BlockNote)的端到端测试位于 tests/src/end-to-end,基于 vitest-browser-react 渲染真实编辑器组件,并大量断言截图与文档快照。以图片块测试 images.test.tsx 为例,其中嵌入测试固定使用外部图床地址:

const IMAGE_EMBED_URL = "https://placehold.co/800x540.png";

随后通过waitForSelector(\img[src="${IMAGE_EMBED_URL}"]`)` 等待图片真正加载完成(images.test.tsx)。这类依赖外部网络的断言正是请求 Mocking 的典型适用场景:在无外网或 CI 网络受限的环境下,可以用

playwright-cli route "**/placehold.co/**" --body='<svg .../>' --content-type=image/svg+xml

或借助run-code拦截后返回一张本地图片字节,让图片块渲染路径在不依赖公网的前提下被稳定验证。同理,AI 接口、协作同步、文件上传等依赖后端服务的测试(见 tests/src/end-to-end/ai 与 tests/src/end-to-end/comments/comments.test.tsx),都可以先route出固定响应,再逐步替换为真实接口回归。

从更广的视角看,拦截能力还能与 playwright-tests.md 描述的调试流程配合:PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli启动后,用playwright-cli attach连上测试会话,在逐步探索页面时用route动态改写网络行为,从而隔离"应用 bug"与"网络环境问题"。

常见问题与注意事项

  • route 作用范围route作用于当前浏览器会话内的全部页面与 iframe,route-list可随时查看已注册的规则,避免规则叠加造成意外拦截。
  • --body--content-type需成对出现:伪造 JSON 时忘记指定 Content-Type 会导致响应被浏览器按错误类型解析。
  • run-code代码限制:函数体内不能使用 import/export/require;复杂逻辑建议写成独立脚本文件后用--filename加载,便于维护。
  • route.fetch()的用途边界:它发起的是真实网络请求,仅适合网络可用、且需要保留真实语义的场景;纯离线环境请直接用route.fulfill伪造。
  • 调试建议:先用route-list确认规则已注册,再配合 running-code.md 中的console/requests命令观察实际请求是否被命中。

小结

请求 Mocking 把"不可控的网络"变成"可控的测试夹具":route系列命令负责快速替换与清理,run-code负责条件分支、响应篡改、故障注入与延迟模拟。两者结合 URL 模式语法,足以覆盖从"图片 404"到"登录鉴权分支"再到"断网演练"的绝大多数验证场景。配合本仓库的端到端测试体系,你可以在无外网、弱网或后端未就绪时,依然对 BlockNote 编辑器(图片、AI、协作等模块)进行确定性验证。

  • 前端
  • 富文本
  • UI组件
  • AI 应用

【免费下载链接】BlockNote

A React Rich Text Editor that's block-based (Notion style) and extensible. Built on top of Prosemirror and Tiptap.

项目地址:https://gitcode.com/gh_mirrors/bl/BlockNote
点击查看免费下载

相关推荐

上一篇:NBTExplorer:Minecraft 存档 NBT 编辑器使用指南,6 种数据格式全支持
下一篇:手把手原神模型导入教程:20 分钟跑通 GIMI,把任何模型换进游戏

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询