news 2026/10/14 15:59:21

放心发布的底气:Bulwark Webmail Vitest + Playwright + Stalwart 真机测试矩阵全揭秘

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
放心发布的底气:Bulwark Webmail Vitest + Playwright + Stalwart 真机测试矩阵全揭秘

【免费下载链接】webmail

Self-hosted JMAP webmail for Stalwart Mail Server. Mail, calendar, contacts, and files in one client.

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

Bulwark Webmail 是一款面向 Stalwart Mail Server 的自托管 JMAP webmail 客户端,把邮件、日历、联系人和文件收纳进同一个界面。而它真正让人"放心发布"的底气,来自一套Vitest + Playwright + Stalwart 真机三层测试矩阵:543 个单元测试文件、5700+ 测试用例、17 个 Playwright 集成场景,全部跑在真实邮件服务器上。本文带你完整看懂这套测试体系是如何搭起来的。

为什么 Webmail 测试不能只靠"假数据"

Webmail 最难测的不是界面,而是同步:

  • 邮件从别的客户端发进来,未读角标会不会跳?
  • 服务器端删了一封邮件,列表会不会消失?
  • 多账号统一收件箱的计数,切回来还是不是最新的?

这类"我的计数不对 / 文件夹没刷新"的 Bug,用 Mock 数据几乎测不出来。Bulwark Webmail 的答案很直接:测试时拉起一台真的 Stalwart 邮件服务器,浏览器直接和它说 JMAP。

三层测试矩阵一览

层级工具规模运行方式
单元层Vitest(jsdom 环境)543 个测试文件 / 5700+ 用例npx vitest run
集成层Playwright + Docker 内 Stalwart17 个 spec / 55 个场景npm run test:integration
静态层Playwright Lite 冒烟静态导出 + Stalwart 模拟器npm run test:lite-smoke

三层各司其职:快、深、真。下面逐层拆解。

第一层:Vitest 单元测试——把每个角落锁死

入口配置在 vitest.config.ts:jsdom 环境、React 插件、@路径别名,并明确排除集成目录,避免和 Playwright 套件混跑。全局桩写在 vitest.setup.ts 里——mock 掉next-intl、next/navigation,补齐 jsdom 缺失的matchMedia和localStorage,让组件在测试里"开箱即渲染"。

用例分布基本和项目结构一一对应:

  • lib/__tests__/:约 275 个文件,覆盖 JMAP 客户端、邮件线程化、HTML 净化、日历工具、主题编译等核心逻辑;
  • stores/__tests__/:90 个文件,重点打磨 Zustand 状态库——账号切换竞态、登出孤儿、断网恢复等"手快点就炸"的场景都有专属用例;
  • components/:133 个组件测试,配合 Testing Library 断言交互行为;
  • hooks/__tests__/:22 个 Hook 测试,如键盘快捷键、侧边栏应用解析。

贡献者在 CONTRIBUTING.md 中有一行硬要求:提交 PR 前先跑

npm run typecheck && npm run lint && npx vitest run

类型、风格、单测三关全过,才有资格进入评审。

第二层:Playwright + Stalwart 真机集成测试

这是整套矩阵里最有含金量的部分,独立成 integration/ 目录,README 就在 integration/README.md。

一键拉起"真机"环境

run-tests.sh 是推荐入口:

integration/run-tests.sh # 全量跑 integration/run-tests.sh 01-login # 只跑登录场景

脚本先docker compose up起两个容器(见 docker-compose.yml):

  • stalwart:JMAP + 管理端口8025、SMTP 提交1025、IMAP1143,并用声明式 NDJSON 引导出alice/bob/carol三个测试邮箱;
  • webmail:被测应用本身,跑在:3000。

Playwright 则跑在官方浏览器镜像里,绕开浏览器下载失败的老问题;globalSetup会等 Stalwart JMAP 和 webmail 健康检查双双就绪才开始跑(见 integration/tests/global-setup.ts)。

测试思路:改服务器,看浏览器

这是它和普通 E2E 的最大区别——变更走旁路,断言看界面:

  1. 用零依赖的 SMTP 客户端 helpers/smtp.ts 往邮箱"注入"一封真邮件(支持附件、内联图片);
  2. 用 JMAP 客户端 helpers/jmap.ts 在服务端执行读、移、删、建文件夹;
  3. 断言全部落在渲染出来的 UI上——读的是[data-testid="folder-counts"]里的data-unread/data-total,与语言环境无关。

也就是说,测试回答的问题永远是:服务器变了,webmail 同步到了没有?

以 02-mail-sync.spec.ts 为例:SMTP 收进一封新邮件 → 断言收件箱未读数从 0 变 1;再点开标已读 → 断言服务端状态回落、计数清零。多账号隔离、跨账号移动、委托文件夹、跨账号附件下载等 55 个场景,全部按这套方法覆盖。

失败时"现场全留"

playwright.integration.config.ts 里几个细节很讲究:

  • screenshot: 'only-on-failure'+trace: 'retain-on-failure':失败才存截图和 trace;
  • 视频默认retain-on-failure,想全程录像就IT_VIDEO=on integration/run-tests.sh,产物落在integration/test-results/<test>/video.webm;
  • CI 环境自动重试 1 次,HTML 报告输出到integration/playwright-report。

这套"真机测试"到底抓出了什么

最有说服力的,是 integration/README.md 里"Findings"一节——测试矩阵实打实钉住并修复了若干同步缺陷:

  • 共享账号计数:Stalwart SSE 只推主账号变更,后台账号变更客户端现在会在可见性对账时轮询补上;
  • 跨账号移动:自己账号与共享文件夹之间、跨属主之间的移动,送达、读状态、源删除全部验证通过;
  • 跨账号附件:附件 blob 是账号作用域的,All Mail 里下载他人账号邮件的附件曾 404,现在按消息归属的accountId路由;
  • 草稿重开:重新打开草稿会还原所选发件人,不再被重置回默认身份(对应草稿场景测试)。

这些 Bug 有一个共同点:只测 UI 状态测不出来,必须让真服务器变一下再看浏览器——这正是整套真机矩阵存在的意义。

第三层:Lite 静态版冒烟测试

Bulwark Lite 是不依赖 Node 服务器的纯静态构建。它的冒烟套件在 scripts/lite/smoke/:

  • lite-demo.spec.ts:静态导出页在 SPA 回退和"裸 404 主机"两种托管方式下都能正确启动;
  • lite-stalwart.spec.ts:用 Stalwart 模拟器验证部署前缀重定向、OAuth 客户端 id、深度链接、无越界请求。

对应命令npm run test:lite-smoke与npm run test:lite-smoke:stalwart。

CI 里怎么跑的

  • 单元测试套件在每次 push 和 pull request都会跑;
  • 集成测试工作流在main 分支每晚、带integration标签的 PR、以及手动触发时运行;
  • 失败时自动上传 Playwright 报告、trace 和失败视频作为 artifact,并打印容器日志——排查问题不用本地复现。

小结:三层矩阵给普通用户带来了什么

你感知的功能守护它的测试
未读角标、文件夹计数准确Vitest 计数逻辑 + 02-mail-sync / 09-live-counters
多账号统一收件箱03-multi-account / 04-all-mail
草稿、委托文件夹、附件下载07-drafts / 06-shared-folders / 10-attachments
换设备打开都正常组件/Hook 单测 + 响应式断言

一句话总结:单元测试管"写得对不对",Playwright 管"交互顺不顺",Stalwart 真机管"同步真不真"。想自己动手跑一遍?git clone https://gitcode.com/gh_mirrors/webm/webmail之后,npx vitest run看秒级反馈,integration/run-tests.sh体验真机全量回归——这就是 Bulwark Webmail 放心发布的全部底气。

【免费下载链接】webmail

Self-hosted JMAP webmail for Stalwart Mail Server. Mail, calendar, contacts, and files in one client.

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 15:59:16

WPS PIN算法缺陷与两小时破解实战指南

简介&#xff1a;本资源是一份面向网络安全初学者与渗透测试爱好者的实战技术文档&#xff0c;聚焦WPS协议安全缺陷与无线路由器PIN码算法破译原理及防御实践。内容涵盖MAC地址解析、十六进制转十进制计算PIN前6位、最后一位数字的穷举逻辑、WPS功能漏洞成因分析&#xff0c;并…

作者头像 李华
网站建设 2026/10/14 15:58:51

TfidfVectorizer参数详解:从TF-IDF原理到文本分类调参实战

很多人第一次接触文本挖掘&#xff0c;就是把一堆新闻标题丢给模型的fit_transform&#xff0c;然后拿到一个稀疏矩阵直接开训。等到矩阵大到内存报警&#xff0c;或者模型线上效果和线下验证对不上时&#xff0c;才回头研究TfidfVectorizer里那一二十个参数到底动了什么。这篇…

作者头像 李华
网站建设 2026/10/14 15:58:36

视频生成时间一致性难题:从逐帧生成到时空建模与DiT架构演进

视频生成领域这两年最热闹的讨论&#xff0c;几乎都绕不开一个词——时间一致性。你肯定见过那种demo&#xff1a;单帧画面精致得像壁纸&#xff0c;人物皮肤纹理、光影层次都挑不出毛病&#xff0c;可一旦播放起来&#xff0c;人物的脸在几秒内换了三张&#xff0c;衣服颜色忽…

作者头像 李华
网站建设 2026/10/14 15:58:34

NLP入门文本预处理实战:分词、停用词与词频统计全解析

简介&#xff1a;南邮自然语言处理课程实验一&#xff08;词典分词与二元语法分词&#xff09;配套参考文档已整理为doc格式&#xff0c;面向正在学习自然语言处理基础、需要通过HanLP完成分词与句法分析实验的本科生。文档对应2023/2024学年第二学期实验报告&#xff0c;系统梳…

作者头像 李华
网站建设 2026/10/14 15:58:30

无人机如何检测路面病害:从像素级分割到毫米级定位的技术路径

一、路面病害的视觉特征与检测难点 1.1 病害类型与视觉表现 公路沥青路面病害按《公路技术状况评定标准》分为龟裂、块状裂缝、纵向裂缝、横向裂缝、坑槽、松散、沉陷、车辙、翻浆、波浪拥包、泛油等十余类。水泥混凝土路面则包括破碎板、板角断裂、错台、唧泥、坑洞等。 从计算…

作者头像 李华
网站建设 2026/10/14 15:57:34

数组逆序对计数:从暴力遍历到归并排序与树状数组优化

1. 问题定义与第一反应1.1 什么是数组中的逆序对面试算法题里&#xff0c;“数组中的逆序对”属于那种一眼看上去很简单、真正写起来到处是坑的典型题目。题面本身不复杂&#xff1a;给定一个整数数组&#xff0c;如果存在两个下标 i 和 j&#xff0c;满足 i < j 且 nums[i]…

作者头像 李华