visuddhinanda 6c13e25c5c test(dashboard-test): 讨论页路径改为 /workspace/discussion/* 4 天之前
..
documents f8c7a356fc test(dashboard-test): 新增讨论话题页 spec;配置改为 .env;testlog 移出版本库 4 天之前
src 6c13e25c5c test(dashboard-test): 讨论页路径改为 /workspace/discussion/* 4 天之前
.env.example 674b176031 test: api-test 与 dashboard-test 覆盖讨论批量角标与补回的讨论入口 4 天之前
.gitignore f8c7a356fc test(dashboard-test): 新增讨论话题页 spec;配置改为 .env;testlog 移出版本库 4 天之前
README.md 6c13e25c5c test(dashboard-test): 讨论页路径改为 /workspace/discussion/* 4 天之前
package.json f8c7a356fc test(dashboard-test): 新增讨论话题页 spec;配置改为 .env;testlog 移出版本库 4 天之前
playwright.config.ts f8c7a356fc test(dashboard-test): 新增讨论话题页 spec;配置改为 .env;testlog 移出版本库 4 天之前
tsconfig.json d281b449d3 create 1 月之前

README.md

dashboard-test

dashboard-v6 的 Playwright 端到端测试。本目录仅用于 dashboard 测试, 不含任何应用代码,也不参与 dashboard-v6 的构建。

它替代的是「人工点页面 + 肉眼盯 console」的手工测试:脚本驱动真实浏览器操作页面, 自动采集 console 报错、未捕获异常、请求失败和 HTTP 4xx/5xx,并逐步截图。

设计取舍见 documents/development/testing-strategy.md。


安装

cd dashboard-test
npm install
npx playwright install chromium
cp .env.example .env        # 生成本机配置,填上测试账号的密码(.env 已 gitignore)

依赖只有两个,且都在 devDependencies:

包 用途
@playwright/test 测试运行器 + 浏览器驱动
@types/node TypeScript 类型

前置:启动 dev server

测试直连本地 dev server,需先在另外的终端起好:

cd ../api-v13      && php artisan serve      # http://127.0.0.1:8000
cd ../dashboard-v6 && npm run dev            # http://127.0.0.1:4000/pcd-v2026/

运行

npm test                    # 跑全部
npm run test:channel        # 只跑 channel 路由
npm run test:users          # 只跑匿名账号页面(登录 / 注册 / 找回密码 / 重置密码)
npm run test:discussion     # 只跑讨论:话题页、对象的全部讨论页(/workspace/discussion/*)、文章底部问答区、讨论角标
npm run test:ui             # UI Mode,可视化单步调试
npm run test:headed         # 显示浏览器窗口
npm run report              # 打开上次的 HTML 报告
npm run codegen             # 录制操作生成选择器

正式记录一次测试时,把截图输出到带时间戳的目录:

E2E_SHOT=testlog/assets/channel_20260907_034904 npm run test:channel

配置

写在 .env(模板 .env.example),由 playwright.config.ts 用 Node 自带的 process.loadEnvFile 加载;shell 里已设置的同名环境变量优先。spec 里一律从 src/lib/env.ts 取值,不直接读 process.env,也不写死账号密码——缺 E2E_USER / E2E_PASS 会直接报错提示。

变量 默认值 说明
E2E_BASE http://127.0.0.1:4000/pcd-v2026/ 被测站点根地址
E2E_USER (必填) 测试账号
E2E_PASS (必填) 密码
E2E_SHOT testlog/assets/<路由>_latest 截图输出目录
E2E_DESTRUCTIVE 未设置(执行) 设为 0 跳过增删改用例
E2E_DISCUSSION_SENTENCE ee5259be-…(本地开发库) 讨论用例挂的句子:须在测试账号自己的 channel 里
E2E_ARTICLE f24cfd88-…(本地开发库) 测试账号自己的文章:文章底部问答区、讨论角标请求

目录结构

目录布局参照 dashboard-v6:代码在 src/,文档在 documents/。

dashboard-test/
├── playwright.config.ts       配置:baseURL、串行执行、trace/video、setup 依赖
├── .env.example               本机配置模板 → 复制成 .env(gitignore)
├── src/
│   ├── tests/
│   │   ├── auth.setup.ts      登录一次,存 storageState
│   │   ├── channel.spec.ts    /workspace/channel 及子路由
│   │   ├── discussion.spec.ts 讨论话题页、/discussion/show、文章底部问答区、讨论角标(数据经 v3 API 建删)
│   │   └── users.spec.ts      /anonymous 下的登录、注册、邀请注册、找回密码、重置密码
│   └── lib/
│       ├── collect.ts         console / pageerror / HTTP 错误采集与噪音过滤
│       └── env.ts             配置的唯一出口(账号、地址、种子数据)
├── documents/
│   └── development/
│       └── testing-strategy.md   方案取舍与约定
├── testlog/                   测试日志与截图(gitignore,只在本机)
│   ├── <路由>_<时间戳>.md      每次测试的结论与待办
│   └── assets/<路由>_<时间戳>/ 该次测试的截图
├── playwright/.auth/          登录态缓存(gitignore)
├── playwright-report/         HTML 报告(gitignore)
└── test-results/              失败用例的 trace / video(gitignore)

登录

按 官方推荐的 setup project 模式: src/tests/auth.setup.ts 作为 setup 项目先跑一次登录,把会话存到 playwright/.auth/user.json;chromium 项目通过 dependencies: ['setup'] 和 storageState 复用,所有用例都以已登录状态开始。


约定

一个路由一个 spec

src/tests/<路由名>.spec.ts,用 test.describe 按子路由分组, test.step 对应测试日志里的编号步骤。

各 describe 相互独立(不用 mode: 'serial'),一个失败不阻断其余用例; 执行顺序由 workers: 1 保证。

已知缺陷写成断言

发现的 bug 直接写进断言,注释标明对应的 BUG 编号,修复前保持红灯。 当前 src/tests/channel.spec.ts 有两条这样的断言:

  • BUG-1 Webhooks 页签不应跳到已废弃的 /studio/...
  • BUG-4 不存在的频道不应出现 Unexpected Application Error

所以 npm test 现在是 22 通过 / 2 失败(含 setup;channel 3/2、users 7/0、discussion 11/0), 两个失败即上述待修项。

修复后的缺陷断言保留作回归保护:src/tests/users.spec.ts 的「回归」组里有 BUG-5(中文界面下 v3 错误文案应为中文,2026-10-08 修复)。

限流

登录(同账号 + IP 每分钟 5 次)、找回密码 / 注册验证码(同 IP 每分钟 10 次)有限流。 setup 与 users.spec.ts 都用 E2E_USER 登录,api-test 也用同一个账号;一分钟内连跑 两三遍就会撞 429(页面上出现「Too Many Attempts.」),隔一分钟再跑。

破坏性操作

在开发机上实际执行(新建、保存、删除),但:

  • 只操作脚本自建的临时数据,命名 e2e-tmp-<timestamp>
  • 测试结束必须清理干净,日志中声明无残留
  • 涉及第三方的操作(转让、分享授权)只验证弹窗渲染,不提交
  • E2E_DESTRUCTIVE=0 可整体跳过

会发邮件、或建出删不掉的数据的请求,不打真实后端,用 page.route 拦截。 开发机的邮件是真实 SMTP;注册建出的账号没有删除接口。拦截后验证前端流程、错误展示 和前端实际发出的请求体(route.request().postDataJSON()),后端行为交给 api-v13 的 Pest 测试。没有副作用的请求(无效邀请、错误验证码、未注册邮箱申请重置)照常走真实后端。 users.spec.ts 是范例。

测试日志

每次正式测试在 testlog/(已 gitignore,不进版本库)下写一个 <路由名>_<YYYYMMDD_HHMMSS>.md,截图放同名 assets 目录并在 md 中内嵌引用。

固定结构:概览表 → 结论 → 一、通过的功能(含截图)→ 二、待修复 (每条一个 - [ ] 代办,含日志片段、截图、定位到文件行号的原因、修复方向)→ 三、未覆盖 / 待确认。

本机已有记录: