Files
gochat/docs/qa/2026-07-09-test-plan-round5.md
T
2026-07-09 18:14:45 +08:00

19 KiB
Raw Blame History

Test Plan — CDP 自动化全链路测试 (Round 5)

日期: 2026-07-09 环境: backend (:3000) + frontend Vite (:3036) + FakeMessagePlatform (:9100) + CDP browser (:9222) 登录: admin@gochat.local / changeme 前置条件: FakeMessagePlatform 已实现(Plan 文档 Task 1-13 全部完成),Round 4 的 28 页功能测试已通过,WebSocket 认证修复已验证。


背景

Round 4 验证了 28 页功能页面 + WebSocket 认证修复 + 实时消息推送。但以下场景因未对接消息收发平台而未被实际验证:

  • 外部渠道 → GoChat:客户通过外部平台发消息,webhook 接收并创建会话
  • GoChat → 外部渠道:客服回复后消息通过 provider 发回外部平台
  • 多客服同时在线的消息分配
  • 客服上下线状态切换对消息路由的影响
  • 聊天窗口关闭/重开的对话连续性
  • 打字状态指示跨渠道传递

本轮引入 FakeMessagePlatform 作为可编程的假消息平台,覆盖上述全部场景。同时保留 Round 4 的 28 页回归测试。


测试规则(继承 Round 4,无放松)

Rule 1: Console warnings ARE errors

  • console.warn / Vue warnings / i18n fallback / deprecation notices 全部记录为 finding
  • 允许的 pre-existing warnings(不变):onClose deprecated、WootInput deprecated、Lit dev mode、Vue Router "Discarded invalid param(s)"、SW registration SecurityError
  • 任何不在 allowlist 中的新 warning IS a bug

Rule 2: Network infinite request loop detection

  • 每页加载并 settle 后,监控网络 10 秒
  • 标记任何在无用户交互下被调用超过 3 次的端点
  • 特别关注 /cable 重连循环、轮询模式、4xx/5xx 端点重试
  • cache_keys 端点多次调用是 false-positive(各组件独立获取,settle 后停止)

Rule 3: Click-only navigation — NO URL input

  • 所有页面切换通过 UI 点击(sidebar links、sub-menus、tabs、buttons)
  • 唯一例外:初始登录页 /app/login
  • 折叠的 Settings sub-links 用 JS .click() on <a> 元素(算 UI click)
  • window.location.href = '...' 禁止用于页面导航

Rule 4: Transition error capture

  • 离开页面前 capture console buffer,到达下一页后 capture
  • 过渡期间出现的 error/warning 是 transition-error finding

Rule 5: CRUD interaction where applicable

  • 不只是"页面加载"——在支持 CRUD 的页面至少执行一次 create/edit 操作
  • 验证操作成功 + 无新 console errors + 无 infinite refetch loop

Pre-Test Setup

Step 0a: 启动全部服务

# Terminal 1: GoChat 后端 (:3000)
cd /home/yanghao05/Projects/gochat && pnpm dev:backend

# Terminal 2: Frontend Vite (:3036)
cd /home/yanghao05/Projects/gochat && pnpm dev:frontend

# Terminal 3: FakeMessagePlatform (:9100)
cd /home/yanghao05/Projects/gochat && pnpm fake:start
  • curl http://127.0.0.1:3000/health → 200
  • curl http://127.0.0.1:3036/ → 200
  • curl http://127.0.0.1:9100/health → {"status":"ok","service":"fake-message-platform"}

Step 0b: DB schema integrity check(Round 2 BUG-7 教训)

for ep in conversations/unread_counts notifications custom_attribute_definitions/ agent_bots "custom_filters/?filter_type=conversation" "custom_filters/?filter_type=contact"; do
  code=$(curl -s -o /dev/null -w '%{http_code}' -H 'X-Account-Id: 1' "http://127.0.0.1:3000/api/v1/accounts/1/$ep")
  echo "$ep → $code"
done

全部返回 200(或 401 未认证),不可 500。任何 500 = 停下修 schema。

Step 0c: CDP browser + console hooks

  • Chrome :9222 alive — curl http://127.0.0.1:9222/json/version
  • 打开 http://127.0.0.1:3036/app/login
  • 注入 console hooks(window.__consoleErrors / __consoleWarnings / __resetConsole)
  • 验证返回 'ok'

Step 0d: Login

  • 填写 admin@gochat.local / changeme,点击登录
  • 验证重定向到 dashboard
  • Capture console — post-login 干净
  • 验证 cookie cw_d_session_info 包含 access-token

Step 0e: 创建 Fake 渠道 Inbox

通过前端 UI 创建(验证 Task 7-9 的前端兼容性):

  • Sidebar → 设置 → 收件箱 → 点击"创建新收件箱"
  • 渠道选择列表中找到"Fake 测试平台"卡片,点击
  • 填写表单:
    • 频道名称:Fake Test Inbox
    • Identifier:fake_test_1
    • Webhook URL:http://127.0.0.1:9100/receive
    • Token:fake_test_token
  • 点击"创建 Fake 频道"
  • 验证跳转到 agent 分配页面
  • 添加 admin 到此 inbox
  • 验证 inbox 出现在收件箱列表中

通过 API 验证:

curl -s -H "X-Account-Id: 1" -H "Authorization: Bearer <JWT>" \
  http://127.0.0.1:3000/api/v1/accounts/1/inboxes | jq '.[] | select(.channel_type=="fake")'

Step 0f: 验证 FakeMessagePlatform ↔ GoChat 连通性

# 从 FakeMessagePlatform 发一条测试消息到 GoChat
curl -X POST http://127.0.0.1:9100/api/send \
  -H 'Content-Type: application/json' \
  -d '{"inbox_identifier":"fake_test_1","sender_id":"smoke_test","sender_name":"连通性测试","content":"ping"}'

# 预期:GoChat 收到 webhook,创建 contact + conversation + message
# 验证 GoChat 日志中出现 "Fake webhook received" + "message persisted"

# 验证 FakeMessagePlatform 状态
curl http://127.0.0.1:9100/api/status
# 预期:sent >= 1

如果连通性测试失败,停下排查——后续所有测试依赖这条链路。


Phase 1: WebSocket /cable 验证(回归 Round 4)

  • 登录后等 5s,检查后端日志 ws: connection established
  • 后端日志无 ws: authentication failed
  • 浏览器 console 无 WebSocket errors、无 /cable 401
  • 网络 15s:/cable 连接一次并保持,不重复重连
  • Presence indicator 显示状态(online/busy/offline)
  • 直接 WS 测试:连 ws://127.0.0.1:3036/cable?access-token=<JWT>,收到 {"type":"welcome"} + 5s ping

Phase 2: 28 页功能回归测试(click navigation)

继承 Round 4 的 28 页矩阵。本轮重点验证回归——Round 4 发现的 bug 是否修复、是否回退。每页执行完整 per-page checklist(reset buffer → click → settle → console → network 10s → CRUD → backend logs → transition capture)。

# 页面 点击路径 CRUD 测试 回归关注
1 Dashboard (post-login) 验证会话列表 + 在线状态 —
2 会话详情 点击会话 发消息,验证即时送达 —
3 联系人 Sidebar: 联系人 编辑联系人,保存 —
4 报告 Overview Sidebar: 报告 → Overview 日期选择器变化 —
5 报告 会话 报告 sub-tab: 会话 筛选变化 —
6 报告 客服 报告 sub-tab: 客服 验证表格 —
7 报告 标签 报告 sub-tab: 标签 验证加载 —
8 报告 收件箱 报告 sub-tab: 收件箱 验证加载 —
9 报告 团队 报告 sub-tab: 团队 验证加载 —
10 报告 CSAT 报告 sub-tab: 客户满意度 验证加载 —
11 报告 SLA 报告 sub-tab: SLA 验证 SLA 指标 —
12 报告 机器人 报告 sub-tab: 机器人 验证加载 BUG-A 回归:从 Reports 页面内点"机器人" sidebar link 是否跳转
13 活动 Sidebar: 活动 验证页面加载 BUG-1 回归:路由是否正常
14 帮助中心 Sidebar: 帮助中心 点击 portal,验证文章 —
15 设置 账户设置 Settings → 账户设置 更新字段,保存 —
16 设置 客服代理 Settings sub: 客服代理 验证列表 + 搜索 —
17 设置 团队 Settings sub: 团队 打开创建团队向导 —
18 设置 收件箱 Settings sub: 收件箱 点击 inbox config,加载全部 tab BUG-C 回归:预聊天表单 tab
19 设置 标签 Settings sub: 标签 创建标签 BUG-3 回归:intlify empty key warning
20 设置 自定义属性 Settings sub: 自定义属性 切换 tab —
21 设置 自动化 Settings sub: 自动化 验证列表 —
22 设置 机器人 Settings sub: 机器人 验证列表 BUG-2 回归:sidebar click nav
23 设置 宏 Settings sub: 宏 验证列表 —
24 设置 预设回复 Settings sub: 预设回复 创建预设回复 —
25 设置 集成方式 Settings sub: 集成方式 点击配置一个 —
26 设置 会话工作流 Settings sub: 会话工作流 Toggle switch —
27 设置 客服分配 Settings sub: 客服分配 验证表单 —
28 个人资料 Avatar dropdown → profile 更新资料,保存 —

回归判定标准

Bug Round 4 状态 Round 5 判定
BUG-1 (P2) Activity 路由缺失 FIXED 点击"活动" → campaigns 页面加载 → FIXED
BUG-2 (P3) Bots sidebar 导航 FIXED Settings → 机器人 → 导航到 agent-bots → FIXED
BUG-3 (P4) intlify empty key PERSISTING 创建标签时无 [intlify] Not found '' → FIXED;仍有 → PERSISTING
BUG-A (P3) Bot Reports 侧栏导航 NEW 从 Reports 页面点"机器人" → 跳转到 /reports/bot → FIXED;不跳转 → PERSISTING
BUG-C (P2) 预聊天表单 null FIXED inbox settings → 预聊天表单 tab → 无 Vue warn → FIXED

Phase 3: FakeMessagePlatform 全链路消息测试(本轮新增核心)

这是 Round 5 的核心差异——通过 FakeMessagePlatform 驱动真实的外部渠道消息流。

3.1 客户发消息 → GoChat 创建会话

  • 通过 FakeMessagePlatform 发送消息:
    curl -X POST http://127.0.0.1:9100/api/send \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","sender_id":"customer_001","sender_name":"测试客户A","content":"你好,我需要帮助"}'
    
  • 前端 Dashboard 看到新会话出现(Fake Test Inbox 渠道)
  • 会话列表显示客户名"测试客户A"和消息预览"你好,我需要帮助"
  • 点击会话,消息出现在聊天窗口
  • 后端日志:Fake webhook received + message persisted
  • Console 无新错误

3.2 客服回复 → FakeMessagePlatform 收到出站消息

  • 在前端会话详情页,客服输入回复"您好,有什么可以帮您?",Ctrl+Enter 发送
  • 消息即时出现在聊天窗口(WS 实时推送)
  • FakeMessagePlatform 收到出站消息:
    curl http://127.0.0.1:9100/api/messages?inbox_identifier=fake_test_1
    
    预期:返回包含 "content":"您好,有什么可以帮您?" 的消息
  • 消息 sender.type 为 "agent"
  • Console 无新错误

3.3 客户回复 → 消息追加到同一会话

  • 通过 FakeMessagePlatform 回复:
    curl -X POST http://127.0.0.1:9100/api/reply \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","sender_id":"customer_001","content":"我的订单有问题","reply_to_id":"<agent_msg_source_id>"}'
    
  • 前端会话详情页:新消息追加到聊天窗口底部(不创建新会话)
  • 消息 sender 为客户"测试客户A"
  • Console 无新错误

3.4 多客户并发会话

  • 同时发送两个不同客户的消息:
    curl -X POST http://127.0.0.1:9100/api/send \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","sender_id":"customer_002","sender_name":"测试客户B","content":"退款咨询"}' &
    
    curl -X POST http://127.0.0.1:9100/api/send \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","sender_id":"customer_003","sender_name":"测试客户C","content":"技术支持"}' &
    
  • 前端会话列表出现 3 个独立会话(A/B/C)
  • 每个会话的消息内容正确对应
  • Console 无新错误

3.5 打字状态指示

  • 触发客户打字状态:
    curl -X POST http://127.0.0.1:9100/api/typing \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","sender_id":"customer_001","typing":true}'
    
  • 前端会话详情页显示"正在输入..."指示器(如果 UI 支持)
  • 停止打字:
    curl -X POST http://127.0.0.1:9100/api/typing \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","sender_id":"customer_001","typing":false}'
    
  • 指示器消失
  • Console 无新错误

3.6 聊天窗口关闭(session end)

  • 关闭客户会话:
    curl -X POST http://127.0.0.1:9100/api/close \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","conversation_id":"<external_conv_id>","sender_id":"customer_001"}'
    
  • GoChat 收到 session.end 事件,创建 "[session ended]" 消息
  • 前端会话显示系统消息或状态变化
  • Console 无新错误
  • 同一客户再次发消息 → 创建新会话(如果 inbox 配置 lock_to_single_conversation=false)

3.7 消息附件

  • 发送带附件的消息:
    curl -X POST http://127.0.0.1:9100/api/send \
      -H 'Content-Type: application/json' \
      -d '{"inbox_identifier":"fake_test_1","sender_id":"customer_001","sender_name":"测试客户A","content":"请看这张截图","content_type":"image","attachments":[{"url":"http://example.com/screenshot.png","content_type":"image/png","filename":"screenshot.png","file_size":102400}]}'
    
  • 前端会话详情页显示附件预览(图片缩略图或文件链接)
  • Console 无新错误

Phase 4: 多客服消息分配测试(本轮新增)

4.1 单客服在线 — 所有消息分配给该客服

  • 确保 Fake Test Inbox 启用 auto_assignment
  • 确保只有一个客服(admin)在线
  • FakeMessagePlatform 模拟客服上线:
    curl -X POST http://127.0.0.1:9100/api/agent/online \
      -H 'Content-Type: application/json' \
      -d '{"agent_id":"1","agent_name":"Admin"}'
    
  • 发送新客户消息 → 验证会话自动分配给 admin
  • 前端会话列表中该会话 assignee 为 admin

4.2 多客服在线 — 轮询分配

  • 创建第二个客服用户(通过 Settings → 客服代理)
  • 将第二个客服添加到 Fake Test Inbox
  • 两个客服同时在线
  • 连续发送 3 条不同客户的消息
  • 验证会话按 round-robin 或 least_busy 策略分配给不同客服
  • 前端各客服的会话列表显示分配给自己的会话

4.3 客服下线 — 消息不分配给离线客服

  • 第二个客服下线:
    curl -X POST http://127.0.0.1:9100/api/agent/offline \
      -H 'Content-Type: application/json' \
      -d '{"agent_id":"2"}'
    
  • 发送新客户消息 → 验证会话只分配给在线的 admin
  • 不分配给已下线的客服

4.4 全部客服下线 — 消息进入未分配队列

  • admin 也下线
  • 发送新客户消息 → 验证会话创建但 assignee 为空(未分配)
  • 客服上线后 → 验证是否自动补分配(取决于 assignment policy 配置)

Phase 5: 实时 WebSocket 功能验证(含跨渠道)

5.1 基础实时推送(回归 Round 4)

  • 打开会话,发消息 → 即时出现
  • 后端日志:message.created event dispatched
  • Presence indicator 显示正确状态
  • 网络 30s:/cable 稳定,无 401,无重连风暴
  • 直接 WS 测试:welcome + 5s ping

5.2 跨标签页实时推送(回归 Round 4)

  • Tab 2 同账号登录,reload dashboard
  • Tab 1 发消息 → Tab 2 会话列表预览更新 + 会话详情消息出现
  • 无需手动刷新

5.3 FakeMessagePlatform 触发的实时推送(新增)

  • Tab 1 打开 customer_001 的会话
  • 通过 FakeMessagePlatform 发送 customer_001 的新消息
  • Tab 1 聊天窗口即时显示新消息(WS 推送,非轮询)
  • Tab 2 如果也打开同一会话 → 同样即时显示
  • 后端日志:Fake webhook received → message persisted → ws: message command(WS 推送)

Phase 6: 收集与报告

Issue severity(继承 Round 4)

Sev 定义
P0 功能损坏,阻断核心工作流,或无限循环导致资源耗尽
P1 核心功能损坏但有 workaround;或重复 console errors 降低 UX
P2 非核心功能损坏,或 warnings 指向真实代码问题
P3 轻微 cosmetic/edge-case,无功能影响
P4 纯噪声(dev-mode warnings、deprecation 无用户影响)

报告文件

写入 docs/qa/2026-07-09-qa-report-round5.md。

必须包含的章节:

  1. Summary — 总页数/通过/失败数 + FakeMessagePlatform 集成测试结果概要
  2. 服务启动验证 — backend/frontend/fake-platform 三个服务的健康检查结果
  3. Fake Inbox 创建验证 — 前端 UI 创建 fake 渠道 inbox 的过程和结果
  4. WebSocket 验证 — /cable 状态、welcome/ping、无 401
  5. 28 页回归测试结果表 — 页面、点击路径、通过/失败、findings
  6. FakeMessagePlatform 全链路测试结果(Phase 3 每个子项)
  7. 多客服消息分配测试结果(Phase 4 每个子项)
  8. 实时 WebSocket 功能验证(Phase 5 每个子项)
  9. Findings — 每个 issue:severity、复现步骤(click path + curl command)、预期 vs 实际、console errors、screenshot path、根因方向、影响文件
  10. Known issues 回归验证 — BUG-1/2/3/A/C 的 Round 5 状态
  11. 后端错误观察 — 500s、panics、WS auth failures
  12. 测试备注 — 测试了什么、跳过了什么、blockers

截图

每个 finding 截图:

browser_vision(question="Capture the issue: <description>", annotate=false)

在 CLI 模式下陈述截图的绝对路径(不使用 MEDIA: tag)。

文档清理

按 known-bugs.md 的 cleanup policy:

  • 将 Round 4 的 docs/qa/2026-07-09-qa-report-round4.md 和 docs/qa/2026-07-09-test-plan-round4.md 删除
  • 将 Round 5 报告中的新发现合并到 references/known-bugs.md
  • 更新 known-bugs.md 的 "Consolidated from QA rounds 1–5" 行
  • 保留 Round 5 的报告和测试计划作为当前版本

验证 Checklist

  • 三个服务(backend :3000 + frontend :3036 + fake :9100)全部启动并健康
  • DB schema integrity check:6 个历史端点全部 200(非 500)
  • Console hooks 注入成功
  • Login 成功,cookie 包含 access-token
  • Fake 渠道 Inbox 通过前端 UI 成功创建
  • FakeMessagePlatform → GoChat 连通性测试通过
  • /cable WebSocket 连接稳定(welcome + ping + 无 401)
  • 28 页全部通过 click navigation 测试(或标注 exception)
  • 每页:reset buffer → navigate → settle → console → network 10s → CRUD → logs → transition
  • Phase 3 全链路消息测试:发消息/回复/多客户/打字/关窗口/附件 全部验证
  • Phase 4 多客服分配:单客服/多客服轮询/下线/全下线 全部验证
  • Phase 5 实时推送:基础/跨标签页/FakePlatform 触发 全部验证
  • 报告写入 docs/qa/2026-07-09-qa-report-round5.md
  • 每个 finding 有:severity、复现步骤(click path + curl)、console errors、screenshot path、根因
  • Known bugs 回归验证:BUG-1/2/3/A/C 状态更新
  • 旧轮报告清理(Round 4 report + test plan 删除)
  • known-bugs.md 更新(新发现 + 状态变更 + "rounds 1–5")