Files
gochat/docs/qa/2026-07-18-cdp-click-only-full-test-plan.md
T
2026-07-27 15:50:18 +08:00

886 lines
44 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-07-18 GoChat CDP 点击式全量功能测试计划
> 创建日期:2026-07-18
> 最后更新:2026-07-20
> 适用范围:`/home/rogee/Projects/gochat`
> 执行方式:连接已手动启动的本地 GoChat 服务,通过 Chrome DevTools Protocol 做真实点击路径测试
> 关联文档:
> - [docs/qa/2026-07-15-cdp-user-function-test-plan.md](/home/rogee/Projects/gochat/docs/qa/2026-07-15-cdp-user-function-test-plan.md)
> - [docs/qa/2026-07-17-cdp-full-user-function-test-plan.md](/home/rogee/Projects/gochat/docs/qa/2026-07-17-cdp-full-user-function-test-plan.md)
> - [docs/qa/reports/2026-07-15-cdp-user-function-report.md](/home/rogee/Projects/gochat/docs/qa/reports/2026-07-15-cdp-user-function-report.md)
这份文档截至 2026-07-20 仍作为当前这轮 CDP 点击式全量测试的主执行基线;`2026-07-15``2026-07-17` 两份文档保留为补充参考,不再作为当前主执行稿。
## 1. 目标
这轮不是再写一个泛泛的 QA 说明,而是把后续 CDP 执行真正需要的三件事一次定清楚:
1. 用点击式路径把 GoChat 当前可见的用户页面全部纳入测试范围。
2. 把每类页面必须验证的功能点拆细,避免只看“能打开”。
3. 明确哪些测试数据和哪些假能力没有补齐前,不能宣称“全量实际功能测试完成”。
## 2. 当前执行前提
用户已手动启动以下 3 个服务:
```bash
pnpm dev:backend
pnpm dev:frontend
GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=true pnpm fake:start
```
本计划默认基于以下地址:
| 服务 | 地址 | 说明 |
|---|---|---|
| frontend | `http://127.0.0.1:3036` | Dashboard / Widget / Public surface |
| backend | `http://127.0.0.1:3000` | API / webhook / SSE / websocket |
| fake channel | `http://127.0.0.1:9100` | 外部客户消息、出站消息回收、自动回流 |
| Chrome CDP | `http://127.0.0.1:9222` | 优先复用现有浏览器会话 |
### 2.1 本轮直接产出
| 产出 | 位置 | 用途 |
|---|---|---|
| CDP 点击式全量测试主计划 | 当前文档 | 作为 Saturday, July 18, 2026 这一轮的唯一执行基线 |
| 持续追加的执行报告 | `docs/qa/reports/2026-07-15-cdp-user-function-report.md` | 沉淀后续每个页面族的 pass/fail/blocked 证据 |
| 全量测试数据缺口清单 | 第 8 节、第 9 节 | 明确哪些对象不补齐前不能宣称“全量实际功能测试完成” |
| AI 测试支撑方案 | 第 10 节到第 12 节 | 约束 `fake:ai` 的最小接口、场景模式、接入方式 |
### 2.2 当前最高优先级 blocker 摘要
| 优先级 | blocker | 最低要求 | 不补会卡住什么 |
|---|---|---|---|
| P0 | `fake_01` inbox 在 GoChat 内完成建档 | 1 个 | fake 入站、客服回复、auto reply 主链路 |
| P0 | 第二个可登录 agent | 1 个 | 分配、协作、mentions、在线状态、团队联动 |
| P0 | 多状态会话池 | 至少 6 条 | 会话列表、筛选、报表、回归重走 |
| P0 | CRM 非空数据 | contacts 8+、companies 3+ | 联系人/公司列表、搜索、分页、联动 |
| P0 | 标签与团队数据 | labels 5+、teams 2+ | team 视图、标签过滤、自动化条件、报表 |
| P0 | 本地 `fake:ai` | 1 套可保存并可观测的 `openai_compatible` 假服务 | Captain / Copilot 只能停留在 render-only |
### 2.3 截至 2026-07-20 的当前测试边界
基于现在已经手工启动的 `backend + frontend + fake channel`,本轮测试边界先明确为两层:
1. 可以立刻开始做 click-only CDP 实测的范围:
- 登录与 dashboard 主壳
- 会话主链路与 fake channel E2E
- 联系人、公司、搜索、通知、报表
- settings、widget、public、help center
2. 仍不能记为“全量实际功能通过”的范围:
- Captain / Copilot 的真实生成链路
- embedding、FAQ/document 索引、playground 生成、rewrite/summarize 等 AI 功能
原因不是页面没法打开,而是当前仓库还没有 `fake:ai`,因此 AI 相关页面在没有本地 OpenAI-compatible 假服务前,只能验证:
- 路由
- 页面渲染
- 表单保存
- provider disabled / provider error 降级提示
不能验证:
- 真实 chat completion
- 流式输出
- embedding 维度兼容
- AI 任务成功后的前后状态变化
## 3. 强约束
### 3.1 导航约束
- 登录页、public 页面、widget 根入口允许直接打开。
- 登录后的 GoChat 内部页面一律通过真实 UI 点击进入。
- 不允许把 `/app/accounts/:id/...` 深链当成页面通过证据。
- 如果只能靠手输 URL 才能进入,记为入口或路由组织问题,不算页面通过。
### 3.2 判定约束
每个页面至少同时满足以下 6 项,才可判为 `pass`
1. 可达:从现有 UI 路径真实点击进入。
2. 可见:主区域不是空白壳,不是只变 URL。
3. 可载:关键 API 返回正常,首屏数据完成加载。
4. 可用:至少 1~3 个核心功能点能实际执行。
5. 可回:返回列表、刷新、再次进入时状态一致。
6. 可观测:console、network、runtime exception 均已记录。
以下情况直接记 `fail``partial pass`,不能算通过:
- URL 改了,但 `main` 区域没切换。
- 只看到 `离线的`、空白主区、`Unhandled error during execution of component update``Uncaught (in promise)`
- API 422/500 明确落在当前页面主链路上。
## 4. 执行前检查
| 检查项 | 动作 | 通过标准 |
|---|---|---|
| backend health | `GET /health` | 200 |
| frontend login | 打开 `/app/login` | 登录页正常渲染 |
| fake health | `GET http://127.0.0.1:9100/health` | `status=ok` |
| smoke seed 基线 | 确认 `admin@gochat.local / changeme``Test Website Inbox``Smoke Company``Smoke Help Center` 等已存在;若缺失则执行 `cd backend && go run ./cmd/gochat seed` | 至少能登录并看到 smoke 基础对象 |
| fake inbox 绑定 | 确认 GoChat 内已存在 `fake_01` 对应的 fake inbox,且其 identifier 与 `GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01` 一致 | fake 平台发消息后能在 GoChat 建会话,而不只是 fake 服务自己健康 |
| CDP attach | `GET http://127.0.0.1:9222/json/version` | 能拿到 `webSocketDebuggerUrl` |
| Node tooling | `command -v npx` | `npx` 可用 |
| fake 配置 | `POST /api/config` 或读 fake 状态 | `fake_01` webhook 指向 GoChat,本轮 auto reply 已开启 |
| 登录态 | 通过 UI 登录 | 能进入主 dashboard |
| websocket/sse | 登录后观察 `/cable` / SSE 请求 | 无持续 401/403 重连风暴 |
| 报告落点 | 确认既有 report | 本轮证据继续追加同一份 report |
## 5. CDP 统一取证格式
每个页面或子页至少记录这些内容:
- 页面入口点击链路
- `page.url`
- 页面主标题或主区域关键文本
- 关键按钮/表单/列表是否出现
- 当前页面触发的关键 API 路径与状态码
- console warning / error
- runtime exception
- 操作前后截图或 snapshot 摘要
- 最终判定:`pass` / `partial pass` / `fail` / `blocked`
推荐统一证据模板:
| 字段 | 说明 |
|---|---|
| page group | 模块或页面组名称 |
| click path | 从哪个菜单、哪个列表项点进来 |
| url | 最终路由 |
| expected | 本页应验证的能力 |
| observed | 实际看到的文案、列表、表单、图表、交互 |
| api | 关键请求及状态码 |
| console | warning/error 摘要 |
| verdict | pass / partial pass / fail / blocked |
### 5.1 每个页面都要过的统一检查维度
为了避免后续执行变成“页面能打开就算过”,这里再固定一层页面级验收维度。第 6 节所有页面组,都至少要按下面这些切面挑选对应项去验证:
| 维度 | 要检查什么 | 典型证据 |
|---|---|---|
| 入口可达 | 是否能从当前 UI 真实点到 | click path、snapshot、最终 URL |
| 首屏挂载 | 主区是否真的切换,不是只变 URL | 主标题、列表/表单/图表出现 |
| 数据加载 | 首屏关键 API 是否成功返回 | `/api``/platform``/public` 请求状态码 |
| 空态/非空态 | 空页面文案与非空列表是否都合理 | 空态文案、首条数据、计数器 |
| 列表能力 | 搜索、筛选、排序、分页、计数是否正常 | 查询前后列表变化、页码变化 |
| 详情能力 | 列表进入详情、详情返回列表是否稳定 | 详情标题、侧栏信息、返回后状态 |
| CRUD/主操作 | 创建、编辑、删除、保存、执行是否真实生效 | toast、回显、刷新后仍存在 |
| 模块联动 | 会话 ↔ 联系人 ↔ 公司,设置 ↔ 业务页是否串得起来 | 从 A 点进 B 后再返回 A 的状态 |
| 权限与可见性 | 管理员、agent、custom role 是否看到正确入口和禁用态 | 菜单裁剪、按钮禁用、403/422 提示 |
| 异常与降级 | 后端 4xx/5xx、空结果、feature gate、第三方缺失是否有明确反馈 | alert、inline error、空壳/离线态 |
| 刷新与返回 | browser back、页面刷新、重复进入是否一致 | URL、主区文本、筛选状态回显 |
| 可观测性 | console / runtime / websocket / SSE 是否稳定 | console message、runtime exception、`/cable`、SSE 请求 |
额外强调两条:
- 对列表页,至少要覆盖“空态”和“有数据态”其中之一;如果当前数据不够,要在报告里明确记成数据阻塞,不要把空态误记成通过。
- 对配置页,至少要覆盖“一次真实保存 + 一次刷新回显”;只看到表单渲染不算通过。
## 6. 页面覆盖矩阵
下面是后续 CDP 执行的主清单。不是所有页面都要一次测完,但最终报告需要按这个范围闭环。
### 6.1 登录与主壳
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| 登录页 | `/app/login` | 邮箱/密码输入、回车提交、错误密码提示、loading、登录成功跳转 |
| 主 dashboard 壳 | 登录后默认页 | 左侧菜单、顶部栏、账号上下文、全局状态、页面切换时主区真的更新 |
| 刷新恢复 | 任意已进入页刷新 | session 保持、当前页恢复、不会回到空壳 |
### 6.2 会话工作台
来源:`conversation.routes.js``M03`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| 会话总览 | 左侧“会话” | open/pending/resolved/snoozed 列表、计数、分页、切换 |
| Inbox 维度会话 | 会话侧栏 inbox 分组 | inbox 过滤、列表切换、详情联动 |
| Label 维度会话 | 会话侧栏 label 分组 | 标签过滤、列表计数、详情打开 |
| Team 维度会话 | 会话侧栏 team 分组 | 团队过滤、分配联动 |
| Mentions / Unattended / Participating | 会话侧栏对应入口 | 各维度列表是否正确、计数是否变化 |
| 单会话详情 | 从列表点进会话 | 时间线、状态、优先级、标签、assignee、team、侧栏联系人/公司信息 |
| 回复能力 | 会话编辑区 | 发送文本、private note、切换状态、加标签、分配 agent/team |
| 附件与富交互 | 会话编辑区 | 上传附件、粘贴、多消息类型渲染 |
| 实时链路 | fake channel + 会话列表/详情 | fake 入站、客服回复、fake 收到出站、auto reply 回流、UI 无刷新更新 |
### 6.3 Inbox View
来源:`dashboard/inbox/routes.js`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Inbox View 空页 | 左侧或相关入口进入 Inbox View | 空态渲染、说明文案、选择项 |
| Inbox View 详情 | 在 Inbox View 中点具体对象 | 列表与详情同步、筛选切换、返回路径稳定 |
### 6.4 联系人与公司
来源:`contacts/routes.js``companies/routes.js``M04`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| 联系人列表 | 左侧“联系人” | 列表加载、分页、搜索、active/segment/label 过滤 |
| 联系人详情 | 联系人列表点进详情 | 基本资料、自定义属性、标签、最近活动、可用操作 |
| 联系人操作 | 联系人页按钮/弹窗 | 新建、编辑、删除、合并、加标签 |
| 联系人与会话联动 | 从会话侧栏进入联系人,再返回 | 联动跳转正确、状态不丢 |
| 公司列表 | 左侧“公司” | 列表、分页、搜索、计数 |
| 公司详情 | 公司列表点进详情 | 基本信息、关联联系人、历史记录、备注、自定义属性 |
| 公司与联系人联动 | 公司详情子 tab | 添加联系人、关联联系人详情跳转 |
### 6.5 全局搜索
来源:`modules/search/search.routes.js`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| 搜索总页 | 顶部搜索入口 | 默认页渲染、recent searches、空态 |
| 搜索结果 | 输入关键词后回车或选择结果 | conversations/messages/contacts/articles tab 切换、高亮、跳转 |
| 错误态 | 搜索接口异常时 | UI 错误提示、非静默失败、不会误显示空结果 |
### 6.6 通知中心
来源:`notifications/routes.js``M08`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| 通知列表 | 右上或设置包装后的通知入口 | 列表加载、已读/未读、分页或增量加载 |
| 通知动作 | 列表项按钮 | 标为已读、全部已读、删除、跳转回目标页面 |
| snooze/恢复 | 有对应入口时 | snooze 后状态变化、恢复后计数变化 |
### 6.7 报表
来源:`settings/reports/reports.routes.js``M07`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| 总览报表 | 左侧“报告”默认页 | 实时指标、筛选、时间范围 |
| 会话报表 | 报告 → 会话 | 指标卡、图表、筛选条件 |
| 客服概览/详情 | 报告 → 客服 | overview 列表、agent drilldown、时间范围、图表 |
| 收件箱概览/详情 | 报告 → 收件箱 | overview、detail、图表、计数 |
| 标签概览/详情 | 报告 → 标签 | overview、detail、summary、图表、错误态 |
| 团队概览/详情 | 报告 → 团队 | overview、detail、summary、图表 |
| SLA 报表 | 报告 → SLA | 筛选、列表、跳会话 |
| CSAT 报表 | 报告 → CSAT | 指标、分布、评论、筛选 |
| Bot 报表 | 报告 → Bot | 指标卡、图表、空态或 feature gate |
### 6.8 Settings:账户与个人设置
来源:`settings.routes.js` 下 account/profile/security。
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| General / Account | 设置 → General | 账户名称、语言、时区、支持邮箱、保存回显 |
| Profile | 设置 → Profile | 昵称、签名、头像、语言偏好 |
| Security | 设置 → Security | 安全配置、受限项可见性、降级提示 |
| MFA | Profile/Security 子页 | 开关、二维码/验证码流程、错误态 |
### 6.9 Settings:人员、角色、组织
来源:`agents``teams``customRoles``assignmentPolicy``agentBots`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Agents | 设置 → Agents | 列表、新建/邀请、编辑、状态、重置密码 |
| Teams | 设置 → Teams | 列表、新建、编辑、成员管理 |
| Custom Roles | 设置 → Custom Roles | 角色列表、权限矩阵、创建/编辑、绑定用户 |
| Assignment Policy | 设置 → Assignment Policy | 规则列表、创建、编辑、Inbox 绑定 |
| Agent Bots | 设置 → Agent Bots | 列表、创建、编辑、绑定 inbox、token/配置可见性 |
### 6.10 SettingsInbox 与渠道
来源:`settings/inbox` 及其 channels 页面。
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Inbox 列表 | 设置 → Inboxes | 列表、搜索/筛选、进入详情 |
| 新建 Inbox 向导 | Add Inbox | 类型选择、步骤推进、校验、完成页 |
| Inbox 通用配置 | Inbox 详情 → Configuration | 名称、欢迎语、营业时间、sender name、锁单会话、保存 |
| Collaborators | Inbox 详情 → Collaborators | agent 绑定、移除、分配策略联动 |
| Customer Satisfaction | Inbox 详情 → CSAT | 开关、模板、survey rules、保存 |
| Voice Configuration | Voice inbox 子页 | voice 配置项、降级态 |
| Pre-chat Form | Website inbox 子页 | 字段增删改、必填、排序、预览 |
| Fake 渠道页 | Add Inbox / Inbox detail | Fake inbox 创建、配置、消息链路联调 |
| Website 渠道页 | Add Inbox / Inbox detail | website token、域名、widget 外观、预聊天 |
| API 渠道页 | Add Inbox / Inbox detail | API inbox 创建、可用 token/endpoint 文案 |
| Email 渠道页 | Add Inbox / Inbox detail | IMAP/SMTP 表单、校验、保存、错误提示 |
| SMS/Twilio/WhatsApp/Telegram/Facebook/Instagram/Line/Twitter/TikTok/Voice | 各渠道入口 | 页面挂载、核心表单、OAuth 或外部依赖降级态、保存校验 |
### 6.11 Settings:标签、属性、模板、自动化
来源:`labels``attributes``canned``macros``automation``conversationWorkflow``sla`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Labels | 设置 → Labels | 列表、新建、编辑、删除 |
| Custom Attributes | 设置 → Attributes | contact/conversation/company 三类定义 CRUD |
| Canned Responses | 设置 → Canned Responses | 列表、新建、搜索、插入回复框 |
| Macros | 设置 → Macros | 列表、新建、编辑、执行 |
| Automation | 设置 → Automation | 列表、新建、编辑、clone、删除、条件动作校验 |
| Conversation Workflow | 设置 → Workflow | 工作流配置、保存、回显 |
| SLA | 设置 → SLA | 策略列表、创建、编辑、适用范围 |
### 6.12 Settings:集成、审计、账单、Copilot 设置
来源:`integrations``auditlogs``billing``settings/copilot`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Integrations | 设置 → Integrations | webhook/integration 列表、创建、编辑、删除 |
| Audit Logs | 设置 → Audit Logs | 列表、时间排序、筛选、详情 |
| Billing | 设置 → Billing | 页面渲染、受限计划文案、外链或升级入口 |
| Copilot Settings | 设置 → Copilot | provider 配置、chat model、embedding model、base URL、保存与验证 |
### 6.13 Campaigns
来源:`campaigns.routes.js``M07`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Live Chat Campaigns | 左侧/菜单进入 Campaigns | ongoing 列表、创建、编辑、启停 |
| SMS Campaigns | Campaigns 子页 | one-off 列表、创建、schedule、受众 |
| WhatsApp Campaigns | Campaigns 子页 | feature flag、列表、创建、错误态/空态 |
### 6.14 Help Center
来源:`helpcenter.routes.js``M09`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Portal 列表 | 左侧“帮助中心” | portal 列表、切换、空态 |
| 新建 Portal | 帮助中心 → 新建 | 基本信息、保存、返回 |
| Articles 列表 | portal 内文章页 | 列表、tab、过滤、进入编辑 |
| New/Edit Article | portal 文章页按钮 | 新建、编辑、保存、预览 |
| Categories | portal 分类页 | 列表、新建、编辑、跳文章列表 |
| Locales | portal locales 页 | locale 列表、切换、多语言入口 |
| Portal Settings | portal settings 页 | 设置项加载、保存、异常态 |
| Public Preview | article preview | 公共预览页渲染、内容一致 |
### 6.15 Widget / Public Surface
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Website widget | website inbox 生成的入口 | 打开 widget、预聊天表单、建会话、收发消息 |
| Public CSAT | CSAT public 页 | 页面渲染、评分、提交、回显 |
| Public help center | public portal 链接 | portal 首页、分类、文章、搜索 |
### 6.16 Captain / Copilot / AI
来源:`dashboard/captain/captain.routes.js``settings/copilot``M10`
| 页面组 | 真实入口 | 需验证的特性功能点 |
|---|---|---|
| Assistants 列表/空态 | 左侧 Captain | 列表、默认重定向、创建入口 |
| Assistant Settings | Captain → assistant → settings | 基本信息、system prompt、控制项、删除/切换 |
| Assistant FAQs / Responses | Captain → FAQs | 列表、搜索、创建、编辑、pending 切换 |
| Documents | Captain → documents | 列表、上传、状态、重试、删除 |
| Inboxes | Captain → inboxes | 关联 inbox、解除关联 |
| Playground | Captain → playground | 输入问题、获得回答、错误态、loading |
| Guardrails / Guidelines / Scenarios | Captain 子页 | 列表、新增、编辑、删除、保存 |
| Custom Tools | Captain → tools | 列表、新建、编辑、调用配置 |
| Copilot in message composer | 会话回复框 | rewrite、reply suggestions、生成失败提示 |
## 7. 推荐执行顺序
避免一开始就被局部页面问题拖住,建议按这个顺序跑:
1. 登录页 → dashboard 主壳
2. 会话列表 → 单会话 → fake 收发闭环
3. 联系人 / 公司 / 搜索
4. 报表
5. Settings 主链(General、Agents、Teams、Inboxes、Labels、Automation
6. Help Center / Campaigns / Public / Widget
7. Captain / Copilot / AI
8. 权限边界、刷新恢复、异常态回归
## 8. 影响“全量实际功能测试”的数据缺口
下面这些对象如果不补齐,很多页面只能测到“能渲染”或“空态”,不能测到真实功能。
### 8.1 第一层:主链路必须先有
| 数据对象 | 最低要求 | 影响页面/功能 |
|---|---:|---|
| 管理员账号 | 1 个 | 登录、所有 Settings、报表、Captain |
| 普通 agent | 2 个 | 分配、协作、team、mentions、参与者、在线状态 |
| custom role 用户 | 1 个 | 权限边界、菜单裁剪、受限页 |
| Fake inbox `fake_01` | 1 个 | fake 消息主链路、会话实时测试 |
| Website inbox | 1 个 | widget、pre-chat form、campaign、portal 关联 |
| 基础会话池 | 6~12 条 | 会话列表、过滤、报表、搜索 |
| 基础消息池 | 每会话至少 3 条 | 时间线、报表、搜索、状态流转 |
### 8.2 第二层:CRM 与过滤能力必须有
| 数据对象 | 最低要求 | 影响页面/功能 |
|---|---:|---|
| Contacts | 8+ | 联系人列表、分页、搜索、合并、标签 |
| Companies | 3+ | 公司列表、详情、关联联系人 |
| Labels | 5+ | 会话/联系人标签、报表、自动化条件 |
| Teams | 2+ | 分配、team 视图、报表 |
| Contact custom attributes | 2+ | 联系人详情、自定义筛选 |
| Conversation custom attributes | 2+ | 自动化条件、详情、自定义筛选 |
| Company custom attributes | 2+ | 公司详情、属性设置页 |
### 8.3 第三层:设置与提效页面必须有
| 数据对象 | 最低要求 | 影响页面/功能 |
|---|---:|---|
| Canned responses | 3+ | 设置页 CRUD、回复框插入 |
| Macros | 3+ | 宏列表、编辑、执行 |
| Automation rules | 3+ | 列表、编辑、clone、条件动作验证 |
| Assignment policies | 2+ | 策略列表、Inbox 绑定 |
| SLA policies | 2+ | SLA 设置页、SLA 报表 |
| Notifications | 5+ | 通知中心、已读/未读、跳转 |
| Audit logs | 5+ | 审计日志页 |
### 8.4 第四层:报表与公共能力必须有
| 数据对象 | 最低要求 | 影响页面/功能 |
|---|---:|---|
| CSAT responses | 5+ | CSAT 报表、公共 CSAT 页面 |
| Reporting rollups / events | 连续 7 天内有数据 | 总览、客服/标签/团队/收件箱 drilldown |
| Help center portal | 1 套 | portal 列表、settings、public page |
| Categories | 2+ | 帮助中心分类页 |
| Articles | 5+ | 文章列表、预览、编辑、搜索 |
| Locales | 2+ | 多语言切换、locale 页面 |
| Campaigns | live chat / sms / whatsapp 各至少 1 | Campaigns 页面和调度状态 |
### 8.5 第五层:AI 页面必须有
| 数据对象 | 最低要求 | 影响页面/功能 |
|---|---:|---|
| Copilot 配置 | 1 套可保存配置 | Copilot 设置页、回复框 AI 功能 |
| Assistant | 1 个 | Captain 主入口、详情子页 |
| Assistant responses / FAQs | 5+ | FAQ 列表、pending、搜索 |
| Assistant documents | 3+ | 文档列表、状态、重试 |
| Assistant scenarios | 2+ | scenario 页 |
| Assistant guidelines / guardrails | 各 2+ | 子页编辑和展示 |
| Custom tools | 1+ | tools 页面 |
### 8.6 基于当前三服务 + smoke seed 的“已覆盖 / 仍缺”结论
这一节是把“仓库当前已有 smoke seed 能力”和“做全量真实功能测试仍然欠缺的数据”分开说,避免后续误判。
当前 `cd backend && go run ./cmd/gochat seed` 已能稳定准备出这些对象:
| 当前 smoke seed 已覆盖 | 当前状态 | 说明 |
|---|---|---|
| 管理员账号 | 已覆盖 | 默认可登录 `admin@gochat.local / changeme` |
| 1 个 website inbox | 已覆盖 | `Test Website Inbox`,含 `website_token` |
| 1 个 voice inbox | 已覆盖 | `Smoke Voice Inbox` |
| 1 个 company + 1 个 contact | 已覆盖 | `Smoke Company` / `Smoke Customer` |
| 1 条 open 会话 + 3 条消息 | 已覆盖 | 仅够做最小烟测,不够覆盖列表/过滤/报表 |
| 1 套 help center portal/category/article | 已覆盖 | 仅 1 portal、1 category、1 article |
| 1 条 SLA policy | 已覆盖 | 仅最小样本 |
| 1 个 custom role / 1 个 capacity policy | 已覆盖 | 仅可验证页面首屏和单对象详情 |
| 1 个 Captain assistant / 1 条 Captain message / 1 个 agent bot | 已覆盖 | 只够做 AI 页面初始挂载,不够测多对象和主链路 |
但基于你当前已经手动启动的三项服务,下面这些仍然是会影响“全量实际功能测试”结论的缺口:
| 当前仍缺 | 最低补齐要求 | 为什么仍然卡全量测试 |
|---|---:|---|
| fake inbox `fake_01` 在 GoChat 内完成建档与关联 | 1 个 | `pnpm fake:start` 只启动 fake 平台,不会自动在 GoChat 里创建 fake inbox |
| 第二个可登录 agent | 1 个 | 目前 smoke seed 只有管理员,没有第二坐席,无法测分配/协作/在线状态/mentions |
| custom role 绑定到真实用户 | 1 个用户 | 仅有 role 定义不足以验证菜单裁剪和权限边界 |
| 多状态会话池 | 6~12 条 | 当前只有 1 条 open 会话,缺 pending/resolved/snoozed/unassigned 等 |
| 更丰富消息类型 | 每会话再补 2~3 条 | 当前主要是 text + 1 条 CSAT 模板,不够覆盖 private note/附件/状态流转 |
| CRM 列表数据 | contacts 8+、companies 3+ | 当前 1 个联系人、1 个公司不足以测分页、搜索、合并、联动 |
| labels / teams | labels 5+、teams 2+ | 影响过滤、报表、自动化条件、team 视图 |
| canned responses / macros / automation rules | 各 3+ | 设置页能打开,但无法验证真实 CRUD 与执行 |
| notifications / audit logs | 各 5+ | 否则只能测空态,不能测跳转、已读、筛选 |
| help center 丰富数据 | categories 2+、articles 5+、locales 2+ | 当前 smoke help center 只有单文章样本 |
| campaigns 丰富样本 | live chat / sms / whatsapp 各 1 | 当前很难证明列表、状态和调度是真实可用 |
| AI fixtures | FAQ 5+、documents 3+、scenarios 2+、guardrails/guidelines 各 2+、tool 1+ | 当前 Captain 页面大多只能停留在 render-only 或单对象样本 |
### 8.7 模块与数据依赖映射
这一节是给后续执行时快速判断“为什么这个页面现在只能测到一半”。
| 模块 | 没有这些数据时会退化成什么 | 需要补的最低数据 |
|---|---|---|
| 会话列表 / 详情 | 只能验证空态或单条样本,无法验证状态切换、分配、报表回流 | `fake_01` inbox、6~12 条多状态会话、每会话 3+ 消息、2 个 agent、2 个 team、5 个 labels |
| Inbox View / Mentions / Participating / Unattended | 只能验证入口和空态,无法验证计数、协作、提醒链路 | 第二个 agent、至少 1 条 mention、1 条 participating、1 条 unattended 会话 |
| 联系人 / 公司 | 只能验证首屏挂载,无法验证搜索、分页、合并、交叉跳转 | contacts 8+、companies 3+、带标签联系人 3+、带公司联系人 3+ |
| 全局搜索 | 容易出现“空结果”和“真没索引”混淆 | 会话、联系人、文章、消息各自至少 3 条可命中样本 |
| 报表 | 只能看图表壳和空图,无法验证趋势与 drilldown | 连续 7 天事件、不同 inbox/team/label/agent 维度数据、CSAT 5+、SLA 命中样本 3+ |
| Agents / Teams / Roles / Assignment | 只能看列表壳,无法验证权限、分配、成员管理 | 2 个普通 agent、1 个 custom-role user、2 个 teams、2 个 assignment policies |
| Inboxes / Channels | 只能验证 website/voice/fake 的部分页面,很多渠道只能测降级态 | `fake_01`、website inbox、voice inbox、至少 1 个配置过 webhook/OAuth 的可回显样本 |
| Labels / Attributes / Macros / Automation | 只能验证空态或新建入口,无法验证编辑与实际执行 | labels 5+、三类 custom attributes 各 2+、canned responses 3+、macros 3+、automation 3+ |
| Notifications / Audit Logs | 只能看空态,无法验证跳转、筛选、时间排序 | notifications 5+、audit logs 5+ |
| Help Center / Public | 只能看单 portal、单文章,无法验证多语言和分类切换 | portal 1+、categories 2+、articles 5+、locales 2+ |
| Campaigns | 只能看页面框架,无法验证状态流转和调度 | live chat / sms / whatsapp campaigns 各 1+ |
| Captain / Copilot / AI | 只能验证静态渲染或 provider disabled 提示,不能验证真实生成链路 | copilot config 1 套、assistant 1+、FAQ 5+、documents 3+、scenarios 2+、guidelines/guardrails 各 2+、custom tools 1+、`fake:ai` |
## 9. 数据补齐建议
按投入产出比,建议这样补:
### 9.1 执行前一次性准备
- 管理员 1 个
- agent 2 个
- custom role 用户 1 个
- `fake_01` inbox
- website inbox
- 至少 6 条不同状态会话
- 至少 8 个联系人、3 个公司、5 个标签、2 个团队
### 9.2 执行过程中顺手创建
- canned responses
- macros
- automation rules
- custom attributes
- help center portal / categories / articles
### 9.3 执行前最好补成假数据或脚本造数
- 报表连续日期数据
- CSAT responses
- SLA 命中/超时样本
- notifications / audit logs
- AI 相关对象
### 9.4 建议的数据补齐顺序
为了尽快进入“可持续追加证据”的阶段,建议按下面顺序准备:
1. 先确认 smoke seed 基线可登录、可见。
2. 在 GoChat 内补出 `fake_01` inbox,并和当前 fake 平台 webhook 对齐。
3. 再补第二个 agent、teams、labels、6~12 条多状态会话。
4. 接着补 CRM 列表数据、canned responses、macros、automation rules。
5. 最后补报表连续数据、notifications / audit logs、以及 `fake:ai` 相关 AI fixtures。
### 9.5 建议的数据来源与造数方式
为了避免后续执行时一边测一边猜“这条数据该怎么补”,这里把推荐来源固定下来:
| 数据 / 对象 | 优先来源 | 推荐方式 | 备注 |
|---|---|---|---|
| 管理员、website inbox、基础 smoke company/contact/conversation、help center 初始对象 | `cmd/gochat seed` | `cd backend && go run ./cmd/gochat seed` | 作为最小可登录与可见基线 |
| `fake_01` inbox 建档 | GoChat 后台 UI | Settings → Inboxes → Add Inbox → Fake | `pnpm fake:start` 只启动外部 fake 平台,不会自动在 GoChat 内建 inbox |
| fake 会话 / 客户消息 / 回复回流 | `channels/fake` | `POST /api/send``POST /api/reply``POST /api/close``POST /api/typing` | 适合造 open/pending/resolved/snoozed 前的消息样本 |
| agent 在线/离线观测样本 | `channels/fake` | `POST /api/agent/online``POST /api/agent/offline` | 主要用于 presence/UI 观测,不替代真实坐席登录 |
| 第二个 agent、custom-role user | GoChat 后台 UI 或 seed 扩容 | Settings → Agents / Roles | 若要稳定回归,后续更适合补进 seed |
| teams、labels、custom attributes、canned responses、macros、automation | GoChat 后台 UI | 直接通过设置页创建 | 这样既补数据,也顺手覆盖 CRUD |
| contacts、companies 丰富样本 | 优先 UI,必要时 seed 扩容 | CRM 页面新增;批量时可走 seed | 少量样本适合 UI,批量搜索/分页样本适合 seed |
| 多状态会话池 | fake 平台 + GoChat UI 操作 | 先 fake 造会话,再通过 UI 做 assign/resolve/snooze/label/team | 最贴近真实用户行为,也最利于回放 |
| notifications、audit logs、连续报表事件 | 定向脚本 / seed 扩容 / 真实操作回灌 | 不建议纯手工补齐 | 这些数据量大、时间维度强,最好脚本化 |
| FAQ、documents、scenarios、guardrails、custom tools | Captain UI + `fake:ai` | 先配 Copilot,再在 Captain 内创建 | 没有 `fake:ai` 时只能测渲染或 disabled fallback |
| Copilot provider 配置 | Settings → Copilot | 指向本地 `fake:ai` | 建议 chat / embedding 都走 `openai_compatible` |
补充建议:
- fake 平台现成可用的观测接口包括 `GET /api/messages``GET /api/status``POST /api/reset`,适合在 CDP 操作前后核对消息链路是否闭环。
- 如果某一类数据预计需要长期复用,优先考虑补进 `seed` 或专用 bootstrap,而不是依赖人工临时点出来。
- 若某页面的验证目标本身就是“创建对象”,那一类对象不需要在执行前全量准备,只需要留一个最小可进入基线即可。
## 10. `fake:ai` 支撑方案
AI 相关页面如果继续依赖真实外部模型,会让本地 CDP 测试变成“不稳定、不可重复、不可回放”。这里建议直接仿照 `channels/fake` 新增一个本地 `fake:ai`
### 10.1 设计目标
`fake:ai` 的目标不是伪装“聪明模型”,而是提供一个:
- 本地可启动
- 响应确定
- 可人为切换成功/失败/限流/慢响应
- 能记录最近请求
- 能兼容 GoChat 当前 `openai_compatible` provider 的最小实现
### 10.2 现有代码约束
当前仓库里:
-`package.json` 已有 `fake:start`,但还没有 `fake:ai`
- `pnpm-workspace.yaml` 当前只包含 `frontend``channels/fake`
- `backend/internal/llm/openai_provider.go` 会向 `baseURL + /chat/completions``baseURL + /embeddings` 发请求
- `provider_manager.go` 已支持 `openai_compatible`
- `backend/internal/llm/openai_provider.go` 已实现 `ChatCompletionStream`
这意味着:
- 不需要先改 GoChat 的 provider 抽象
- 只需要补一个本地 OpenAI-compatible 假服务
-`fake:ai` 监听 `9110`GoChat 里的 `base_url` 应配置成 `http://127.0.0.1:9110/v1`
- 如果 `Captain Playground` 或会话回复框的 AI 路径走流式输出,`fake:ai` 不能只实现非流式 JSON 返回
### 10.3 最小接口面
首批必须有:
| 方法 | 路径 | 用途 |
|---|---|---|
| `GET` | `/health` | 健康检查 |
| `POST` | `/v1/chat/completions` | Captain/Copilot 文本生成 |
| `POST` | `/v1/embeddings` | 文档索引、检索、语义功能 |
| `POST` | `/api/scenario` | 切换响应模式 |
| `GET` | `/api/requests` | 查看最近请求,便于断言 |
| `POST` | `/api/reset` | 清空内存状态 |
建议首批也支持:
| 方法 | 路径 | 用途 |
|---|---|---|
| `GET` | `/v1/models` | provider 测试或后续扩展 |
| `POST` | `/v1/chat/completions` with `stream=true` | 覆盖流式生成路径 |
建议补一个最小场景切换请求体,便于后续浏览器测试直接复用:
```json
{
"scenario": "ok",
"delay_ms": 0,
"response_text": "[fake:ai][scenario=ok] hello from fake ai"
}
```
### 10.3.1 建议直接固定的 OpenAI-compatible 契约
为了避免后续 `fake:ai` 做出来以后,还要反复因为字段不对去排查 GoChat provider,这里建议第一版就固定成下面这组最小契约。
`POST /v1/chat/completions` 最低接受:
```json
{
"model": "fake-gpt-4o-mini",
"messages": [
{ "role": "system", "content": "You are a QA fake." },
{ "role": "user", "content": "Say hello" }
],
"temperature": 0,
"stream": false
}
```
非流式成功响应建议至少返回:
```json
{
"id": "chatcmpl_fake_001",
"object": "chat.completion",
"created": 1784332800,
"model": "fake-gpt-4o-mini",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "[fake:ai][scenario=ok] hello from fake ai"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 8,
"total_tokens": 20
}
}
```
如果 `stream=true`,建议返回最小 SSE 片段序列:
```text
data: {"id":"chatcmpl_fake_002","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":"[fake:ai]"},"finish_reason":null}]}
data: {"id":"chatcmpl_fake_002","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" hello from fake ai"},"finish_reason":null}]}
data: {"id":"chatcmpl_fake_002","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]
```
`POST /v1/embeddings` 最低接受:
```json
{
"model": "fake-text-embedding-3-small",
"input": "hello from fake embedding"
}
```
成功响应建议至少返回:
```json
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [0.01, 0.02, 0.03, 0.04]
}
],
"model": "fake-text-embedding-3-small",
"usage": {
"prompt_tokens": 4,
"total_tokens": 4
}
}
```
注意点:
- 第一版 embedding 建议直接返回与 GoChat 配置一致的固定维度,默认优先按 `1536` 实现。原因有两个:一是当前 `CopilotConfigService.Test()` 会校验返回向量长度是否等于配置里的 `dimensions`;二是 `captain_assistant_responses.embedding` 仍是 `vector(1536)`。虽然 `article_embeddings.vector_embedding` 已改成动态维度,但如果 `fake:ai` 先返回 4 维之类的短向量,本地 Copilot 健康检查和部分 Captain 索引路径会先失败。
- 如果后续明确把 Copilot 配置里的 `dimensions` 改成其他值,再同步让 `fake:ai` 返回同维度向量;不要把“接口能通”和“维度真实兼容”混为一谈。
- 所有响应里的 `model` 建议回显请求中的模型名,便于在 QA 证据里确认当前页面到底打到了哪条配置。
- `created``id``usage` 不要求真实,但建议稳定、可预测,避免前端因为缺字段误判为 provider 异常。
### 10.4 `fake:ai` 与页面功能点映射
`fake:ai` 不是单纯给 Captain playground 用的,它至少要覆盖下面这些实际测试点:
| 页面/功能 | 依赖能力 | 没有 `fake:ai` 会发生什么 |
|---|---|---|
| 设置 → Copilot 配置 → 测试/保存 | `POST /v1/chat/completions``POST /v1/embeddings` | 只能停留在表单渲染,无法验证 provider 配置真可用 |
| Captain Playground | chat completions,最好支持 stream | 只能测输入框和 loading,不能测回答内容与失败提示 |
| Captain FAQ / response 生成 | chat completions | 无法验证生成 FAQ、approve/reject 前后的主链路 |
| Captain Documents 同步 / 处理 | embeddings | 无法验证文档处理、索引、状态从 syncing 到 synced |
| Copilot rewrite / suggest replies / summarize / translate | chat completions,部分路径建议 stream | 只能验证按钮存在,无法验证生成文本回填 |
| 会话里的 label suggestion / follow-up / participant insights | chat completions | 只能验证入口或 provider disabled fallback |
| AI 错误回归 | `error` / `rate_limit` / `slow` scenario | 无法稳定复现错误提示、重试、超时 UI |
补充约束:
- `fake:ai` 必须接受 `Authorization: Bearer ...` 头,即使服务端不真的校验,也要保证请求不会因为缺少解析而失败。
- `/api/requests` 返回的观测数据必须脱敏 `Authorization``api_key``base_url` 之外的秘密字段,避免把本地测试密钥直接写进 QA 证据。
- chat completion 成功响应建议固定带 `[fake:ai][scenario=...]` 前缀,这样 CDP 报告里能一眼看出当前结果来自本地假服务,而不是误连到了外部模型。
## 11. `fake:ai` 场景模式
至少支持下面几类 scenario
| scenario | 行为 | 主要用途 |
|---|---|---|
| `ok` | 固定成功返回 | 基础页面通过 |
| `slow` | 延迟 2~5 秒后成功 | loading、取消、超时 UI |
| `error` | 500 错误体 | 错误提示、重试 |
| `rate_limit` | 429 错误体 | 限流提示 |
| `empty` | 成功但内容为空 | 空建议、空生成态 |
| `tool_call_stub` | 返回可预测 tool call 结构 | 未来 custom tools 联调 |
### 11.1 返回内容约束
为了让断言稳定,建议所有成功响应都带可识别前缀,例如:
- chat completion 返回:`[fake:ai][scenario=ok] ...`
- embedding 返回固定长度向量,例如 1536 维
这样可以在:
- Copilot 设置页的验证请求
- Captain playground
- 会话回复框 rewrite/suggestion
- 文档 embedding 索引
里快速判断链路是否走到了本地 `fake:ai`
### 11.2 流式返回建议
由于 GoChat 当前 provider 代码已经实现 `ChatCompletionStream``fake:ai` 最好首批就支持 SSE chunk 流式返回,避免后续 Playground 或 Copilot 某些路径只能测非流式。
推荐最小流式行为:
- `Content-Type: text/event-stream`
- 至少返回 2~3 个 `data:` chunk
- 末尾返回 `[DONE]`
## 12. `fake:ai` 的仓库落地建议
建议直接对齐 `channels/fake` 的组织方式:
| 项 | 建议 |
|---|---|
| 目录 | `channels/fake-ai` |
| 启动脚本 | 根 `package.json` 增加 `fake:ai` / `fake:ai:dev` / `fake:ai:test` |
| workspace | `pnpm-workspace.yaml` 增加 `channels/fake-ai` |
| 默认端口 | `9110` |
| 默认模型名 | `fake-gpt-4o-mini``fake-text-embedding-3-small` |
| 观测接口 | `/api/requests``/api/reset``/api/scenario` |
### 12.1 目录与脚本骨架建议
建议 `fake:ai` 第一版直接复用 `channels/fake` 的组织习惯,这样后续维护和理解成本最低:
```text
channels/fake-ai/
├── package.json
├── tsconfig.json
├── README.md
├── src/
│ ├── index.ts
│ ├── server.ts
│ ├── types.ts
│ ├── scenarios.ts
│ └── store/
│ └── memory-store.ts
└── tests/
└── integration.test.ts
```
根目录建议补这些脚本:
```json
{
"scripts": {
"fake:ai": "cd channels/fake-ai && tsx src/index.ts",
"fake:ai:dev": "cd channels/fake-ai && tsx watch src/index.ts",
"fake:ai:test": "pnpm --dir channels/fake-ai test"
}
}
```
`pnpm-workspace.yaml` 也建议同步补:
```yaml
packages:
- frontend
- channels/fake
- channels/fake-ai
```
这样做的好处很直接:
- `fake:start``fake:ai` 的心智模型一致,后续谁来接手都容易理解。
- message fake 和 AI fake 都可以保留自己的 `/health``/api/reset``/api/requests`,不会互相污染。
- 后续如果要把 `dev:all` 扩成包含 AI 的本地联调模式,也只是在根脚本上追加一个并发进程,不需要重构现有 fake channel。
建议默认启动命令:
```bash
FAKE_AI_PORT=9110 pnpm fake:ai
```
在 GoChat Copilot 配置里建议填:
| 配置项 | 建议值 |
|---|---|
| chat provider | `openai_compatible` |
| chat base_url | `http://127.0.0.1:9110/v1` |
| chat model | `fake-gpt-4o-mini` |
| embedding provider | `openai_compatible` |
| embedding base_url | `http://127.0.0.1:9110/v1` |
| embedding model | `fake-text-embedding-3-small` |
## 13. 完成定义
后续要对外说“CDP 全量功能测试完成”,至少要满足下面条件:
1. 第 6 节所有页面组都已有一条最终结论。
2. 每个页面组都留下点击链路和关键 API 证据。
3. 第 8 节的数据缺口已补齐,或在报告里明确标注哪些仍是 `blocked`
4. fake 会话主链路已完成真实闭环。
5. AI 页面不再依赖真实外部 Key,而是通过 `fake:ai` 完成稳定回归。
6. 结果统一沉淀在既有 QA report 中,而不是散落在聊天记录里。
## 14. 本轮建议的直接下一步
建议按下面顺序推进:
1. 先补齐 `fake:ai` 的文档与实现计划。
2. 先准备最小可用测试数据:管理员、2 个 agent、`fake_01`、website inbox、6~12 条会话、8 个联系人、3 个公司。
3. 再继续按本计划做 click-only CDP 覆盖,并把证据追加到既有 report。