如何系统测试富文本编辑器?Draftail 的 Jest、Storyshots 与 Puppeteer 集成测试全景
2026/8/25 17:12:11 网站建设 项目流程

如何系统测试富文本编辑器?Draftail 的 Jest、Storyshots 与 Puppeteer 集成测试全景

【免费下载链接】draftail📝🍸 A configurable rich text editor built with Draft.js项目地址: https://gitcode.com/gh_mirrors/dr/draftail

富文本编辑器(Rich Text Editor)是最难测试的组件之一:键盘快捷键、工具栏交互、粘贴、截图回归、内存占用……任何一个环节都可能悄悄坏掉。Draftail 是基于 Draft.js 构建的可配置富文本编辑器组件,它用Jest 单元测试 + Storyshots 冒烟测试 + Puppeteer 浏览器集成测试 + 性能基准这套四层组合拳,把编辑器测试覆盖得相当完整。本文带你拆解这套富文本编辑器测试方案,新手也能照搬到自己的项目中。

一、测试体系全景:四层防线各司其职

🛡️ 先看全局。Draftail 把测试分成四个层次,从快到慢、从细到粗:

层级工具测试什么代表文件
单元测试Jest + Enzyme + Testing Library单个组件、行为逻辑src/api/behavior.test.ts
冒烟测试Storyshots所有 Story 能否正常渲染tests/smoke/storyshots.test.js
集成测试Puppeteer + Storybook真实浏览器中的完整交互tests/integration/examples.test.js
性能基准react-benchmark内存占用与编辑速度tests/performance/markov_draftjs_41.js

对应的 npm 脚本在 package.json 中定义:npm test(单测)、npm run test:coverage(覆盖率)、npm run test:integration(集成测试)、npm run test:performance(性能)。

二、第一层:Jest 单元测试——在 jsdom 中跑组件

单元测试的配置写在根目录的jest.config.js中,几个关键设置值得学习:

  • ts-jest 转换:直接运行 TypeScript / React 源码,无需预编译;
  • 样式打桩:所有.scss导入被映射到tests/styleMock.js,测试不关心样式细节;
  • jsdom 环境:模拟浏览器 DOM,让 React 组件可以挂载;
  • Enzyme + enzyme-to-json:配合快照序列化,把组件渲染成易读文本。

全局初始化逻辑在tests/setupTest.js中完成:配置 Enzyme 适配器、引入@testing-library/jest-dom断言库。例如tests/rtl.test.js就用 Testing Library 验证了编辑器的 ARIA 属性可访问性——按role="textbox"就能选中编辑器,这是无障碍测试的正确姿势。

单元测试贴近源码编写,比如src/api/DraftUtils.test.ts测试内容状态转换、src/components/DraftailEditor.test.tsx测试主组件渲染。

三、第二层:Storyshots 冒烟测试——所有示例一次过

Storyshots 的思路非常巧妙:Draftail 用 Storybook 组织了大量编辑器示例(简单编辑器、自定义工具栏、各插件场景),tests/smoke/storyshots.test.js自动遍历每一个 Story 并用 Enzyme mount 挂载

initStoryshots({ suite: "Storyshots smoke tests", test: ({ story }) => { const storyElement = story.render(); mount(storyElement); }, });

只要有任何一个示例渲染时抛错,CI 立刻失败。对于"示例即文档"的组件库来说,这是成本最低的一道回归防线。

四、第三层:Puppeteer 集成测试——真浏览器里的真操作

这是全文最值得借鉴的部分。编辑器很多行为(快捷键、选区、输入自动转换)在 jsdom 里根本模拟不出来,Draftail 直接开一个真实 Chrome。

1. 自定义 Jest 环境,全局只启一个浏览器

集成测试使用独立的 Jest 配置tests/integration/jest.config.js,包含三个角色:

  • tests/integration/setup.js(全局启动):用puppeteer.launch启动无头 Chrome,把 WebSocket 端点写入临时文件;如果不是 watch 模式,还会用 Express 在 5001 端口起一个静态服务,托管构建好的 Storybook 产物;
  • tests/integration/teardown.js(全局收尾):关闭浏览器、清理临时文件、关掉服务;
  • tests/integration/PuppeteerEnvironment.js(测试环境):继承 Node 的 TestEnvironment,从临时文件读取端点并通过puppeteer.connect复用同一个浏览器实例,避免每个测试文件都冷启动 Chrome。

watch 模式下则改为连接本地 Storybook 开发服务器(9001 端口),改代码不用重新构建就能调试测试——这套"双模式"设计很实用。

2. 模拟真人:打字、点工具栏、按快捷键

tests/integration/examples.test.js是"功能验收"的范本。它打开 Storybook 测试页,然后像真人一样操作:

  • 选中 "Bold" 后点击工具栏加粗按钮,校验内容状态与快照一致;
  • 输入### H3* UL---验证 Markdown 自动转换;
  • Shift + Enter验证软换行;
  • 点击 IMAGE / LINK 按钮并在弹窗中填写,验证实体插入。

每个用例结束后,从sessionStorage读出编辑器的 ContentState,删除不稳定的 block key 再与快照比对——用数据快照替代 UI 断言,既稳定又精确。

此外还接入了jest-axe无障碍(a11y)自动审计,任何 ARIA 违规都会让测试失败,富文本编辑器能少踩很多坑。

3. 截图回归:像素级防走样

tests/integration/regression.test.jsjest-image-snapshot对编辑器渲染结果截图比对。两个细节很关键:

  • 先注入normalize-rendering.css,抹掉不同操作系统间的字体渲染差异;
  • 设置failureThreshold: 0.003(0.3% 容差),容忍抗锯齿带来的微小噪点。

基准截图存放在tests/integration/__image_snapshots__/目录,UI 一旦意外变化,CI 就能立刻发现。

4. 性能护栏:内存与速度都有上限

tests/integration/performance.test.js在真实页面里用window.performance.memory读取 JS 堆内存:简单编辑器输入几行文字后堆内存不得超过 75MB(25MB × 3 倍缓冲),加载 Markov 大文档场景不得超过 57MB。同时还会读取基准页面输出的平均编辑耗时,要求不超过约 141ms。给性能设"预算"并纳入 CI,是防止编辑器越改越卡的长效机制。

五、一键跑完所有测试:test:ci

整套流程由一条命令串起来(见 package.json 的test:ci脚本):

npm run test:ci

它依次执行:代码检查(ESLint + Stylelint + Prettier)→ 覆盖率单测 → 构建库与 Storybook → Puppeteer 集成测试 → 性能基准。想自己跑一遍,只需克隆仓库:

git clone https://gitcode.com/gh_mirrors/dr/draftail cd draftail npm install npm run test:ci

六、新手可以直接抄走的 4 个测试思路

📌 从 Draftail 的实践里,可以提炼出测试富文本编辑器(乃至任何复杂前端组件)的通用方法论:

  1. 分层设防:单测保证逻辑,冒烟保证"都能渲染",集成测试保证"真的能用",性能测试保证"不会越用越卡"——四层缺一,防线就有漏洞;
  2. 测试对象就是 Storybook 示例:把文档示例变成可测试资产,一举两得;
  3. 断言数据而非像素:优先比对编辑器内部 ContentState 快照,截图只作 UI 兜底,并用容差吸收渲染噪声;
  4. 把 a11y 和性能预算写进 CI:用 jest-axe 和内存/耗时阈值,让质量指标可量化、可回归。

按这套思路搭建,你的富文本编辑器也能拥有"敢发版"的底气。🚀

【免费下载链接】draftail📝🍸 A configurable rich text editor built with Draft.js项目地址: https://gitcode.com/gh_mirrors/dr/draftail

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

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

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

立即咨询