diff --git a/docs/qa/2026-07-15-cdp-user-function-test-plan.md b/docs/qa/2026-07-15-cdp-user-function-test-plan.md index 792dcd8a..553239d0 100644 --- a/docs/qa/2026-07-15-cdp-user-function-test-plan.md +++ b/docs/qa/2026-07-15-cdp-user-function-test-plan.md @@ -1,7 +1,7 @@ # CDP 用户功能全量测试计划 > 创建:2026-07-15 -> 最后更新:2026-07-22 +> 最后更新:2026-07-28 > 目标:连接已启动的 GoChat 本地服务,用 Chrome DevTools Protocol 按真实用户路径覆盖 dashboard / widget / settings / Captain / Copilot / public surfaces。 > 当前服务由人工启动,不由测试脚本托管。 @@ -19,7 +19,7 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t ### 0.1 当前推荐的 CDP 连接方式(Sunday, July 19, 2026) -这轮计划默认优先复用已经打开的 Chrome,会比重新拉起 headed 浏览器更稳,也更符合“接现有人工会话继续点测”的目标。 +这轮计划默认优先复用已经打开的 Chrome,会比重新拉起 headed 浏览器更稳,也更符合"接现有人工会话继续点测"的目标。 建议默认使用: @@ -45,7 +45,7 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t ### 0.2 测试环境异常时的重置策略(Wednesday, July 22, 2026) -这轮点测里已经确认过:测试环境一旦进入“持续重连 / `/cable` 抖动 / 页面大量 `429` / fake 平台残留旧消息”的脏状态,继续硬点只会把环境噪音和真实缺陷混在一起。因此后续执行时,把“允许重置并继续”写成正式策略,而不是临场救火。 +这轮点测里已经确认过:测试环境一旦进入"持续重连 / `/cable` 抖动 / 页面大量 `429` / fake 平台残留旧消息"的脏状态,继续硬点只会把环境噪音和真实缺陷混在一起。因此后续执行时,把"允许重置并继续"写成正式策略,而不是临场救火。 重置优先级: @@ -84,8 +84,8 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t 报告要求: -- 一旦发生重置,必须在 QA report 中记下“重置原因 / 重置动作 / 重置后恢复结果”。 -- 重置后恢复通过的页面,要和“真实功能缺陷”分开归类,避免把环境污染误记成产品 bug。 +- 一旦发生重置,必须在 QA report 中记下"重置原因 / 重置动作 / 重置后恢复结果"。 +- 重置后恢复通过的页面,要和"真实功能缺陷"分开归类,避免把环境污染误记成产品 bug。 测试入口: @@ -101,7 +101,7 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t 1. 用 CDP 模拟真实用户点击、输入、上传、保存、导航、退出登录。 2. 每个页面至少验证:可打开、核心数据加载、主要操作可执行、错误态可见、无异常 API/console、刷新后状态仍正确。 3. 消息链路必须验证:客户入站 → dashboard 实时出现 → 客服回复 → fake 收到出站 → auto reply 回流 → dashboard 无刷新更新。 -4. Chatwoot parity 相关页面以“前端实际请求成功 + UI 可用”为准,不只看路由存在。 +4. Chatwoot parity 相关页面以"前端实际请求成功 + UI 可用"为准,不只看路由存在。 5. AI/Copilot/Captain 测试不依赖真实 LLM Key;先补 `fake:ai`,让页面功能和后端调用链可自动断言。 6. 除登录页、widget/public 入口页外,dashboard 内部页面一律通过真实 UI 点击进入,不直接 `open` 深层内部 URL,避免把路由可达误判成用户可达。 @@ -122,14 +122,14 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t 导航约束: - 允许直接打开:`/app/login`、widget/public 根入口、必要的外部 fake/fake:ai 观察接口。 -- 不允许直接打开:`/app/accounts/:id/...` 下的深层功能页作为“通过”依据。 +- 不允许直接打开:`/app/accounts/:id/...` 下的深层功能页作为"通过"依据。 - dashboard 内导航必须由登录后侧边栏、列表项、按钮、tab、面包屑、弹窗入口逐步点击完成。 - 若页面只能通过手输 URL 才能访问,记录为信息架构或入口缺失问题,而不是直接算页面通过。 失败分级: | 等级 | 标准 | -|---|---| +|------|------| | P0 | 登录失败、dashboard 不可用、消息收发断、权限泄露、数据保存丢失 | | P1 | 页面主要 CRUD 不可用、关键 API 4xx/5xx、实时事件错误 | | P2 | 局部功能不可用、空态错误、表单校验不清晰 | @@ -148,7 +148,7 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t ## 3. 预检查 | 检查 | 命令/动作 | 通过标准 | -|---|---|---| +|------|----------|----------| | backend health | `GET /health` | 200 | | frontend mount | 打开 `http://127.0.0.1:3036/app/login` | login 页面可见 | | fake health | `GET http://127.0.0.1:9100/health` | `status=ok` | @@ -160,10 +160,10 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t ## 4. 基础测试数据缺口 -需要补齐这些数据,否则“全量实际功能测试”会退化成空态浏览: +需要补齐这些数据,否则"全量实际功能测试"会退化成空态浏览: | 数据 | 最低数量 | 用途 | -|---|---:|---| +|------|--------:|------| | Account | 1 | 主测试租户 | | Administrator | 1 | 设置、成员、平台配置 | | Agent | 2 | 分配、团队、在线状态、跨坐席实时 | @@ -197,12 +197,11 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t | Captain response/FAQ | 5 | responses、pending | | Captain scenario | 2 | scenario 页面 | | Captain custom tool | 1 | tools 页面 | -| Copilot config | 1 fake provider | AI 功能不打真实外网 | ### 4.1 首轮必须先补的数据(否则会大面积 blocked) | 优先级 | 数据 | 最低要求 | 影响范围 | -|---|---|---|---| +|--------|------|---------|---------| | P0 | Administrator | 1 个可登录管理员 | 所有 settings / Captain / reports | | P0 | Agent | 2 个可登录 agent | 分配、协作、在线状态、mentions | | P0 | Fake inbox `fake_01` | 已绑定 webhook 且可收发 | 会话主链路、实时消息 | @@ -227,10 +226,10 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t ### 4.2 数据准备方式建议 -把“缺数据”再分成三类,执行时更省时间: +把"缺数据"再分成三类,执行时更省时间: | 类别 | 数据 | 建议来源 | 是否需要执行前准备 | 备注 | -|---|---|---|---|---| +|------|------|---------|-------------------|------| | A | Administrator / Agent / Custom role 用户 | seed + 后台 Settings 手工补齐 | 是 | 登录、权限、分配依赖它们 | | A | Fake inbox `fake_01` | 当前 fake channel + inbox 配置 | 是 | 主消息链路阻断项 | | A | Website inbox | Settings 新建或 seed | 是 | widget / campaign / pre-chat 依赖 | @@ -239,7 +238,7 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t | B | Canned responses / Macros / Automation rules | 走 UI 创建 | 否 | 适合首轮 CDP 过程中创建并复用 | | B | Custom attributes | 走 UI 创建 | 否 | 可直接覆盖表单和筛选能力 | | B | Help center portal / locale / article | 走 UI 创建 | 否 | 既补数据又验证 portal 后台 | -| C | CSAT / SLA / Audit logs / Notifications | 定向 seed 或接口回灌 | 视页面而定 | 纯空态也能先验渲染,但无法完成“全量功能”断言 | +| C | CSAT / SLA / Audit logs / Notifications | 定向 seed 或接口回灌 | 视页面而定 | 纯空态也能先验渲染,但无法完成"全量功能"断言 | | C | Captain documents / responses / scenarios / tools | `fake:ai` + Captain 后台创建 | 是(若要做 AI 主链路) | 没有 `fake:ai` 时只能做页面渲染检查 | | C | Campaigns(live chat / sms / whatsapp) | Settings / Campaign UI 创建 | 否 | 需要 website inbox 与 portal 先到位 | @@ -252,7 +251,7 @@ GOCHAT_WEBHOOK_URL=http://127.0.0.1:3000/webhooks/fake/fake_01 FAKE_AUTO_REPLY=t ### 4.3 当前仓库已具备的数据准备能力 vs 仍需补齐项 -为了避免把“已有 smoke seed 能力”和“真正缺失的数据/能力”混为一谈,这里按当前仓库实际情况再拆一次。 +为了避免把"已有 smoke seed 能力"和"真正缺失的数据/能力"混为一谈,这里按当前仓库实际情况再拆一次。 当前仓库里已经存在可直接复用的 smoke seed 基线,入口是: @@ -264,7 +263,7 @@ go run ./cmd/gochat seed 按当前 `cmd/gochat seed` 的实现,已经能稳定准备出这些基础对象: | 类别 | 当前 seed 覆盖情况 | 备注 | -|---|---|---| +|------|------------------|------| | Administrator | 已覆盖 1 个 | 默认 `admin@gochat.local / changeme`,可通过环境变量覆盖 | | Account | 已覆盖 1 个 | 默认 `Test Account` | | Website inbox | 已覆盖 1 个 | `web_widget` inbox,带 `website_token` | @@ -277,225 +276,17 @@ go run ./cmd/gochat seed | CSAT | 已覆盖 1 条模板消息 | 够做基础渲染,不够做分布/列表型报表 | | SLA policy | 已覆盖 1 条 | 够做基础页面进入 | | Custom role | 已覆盖 1 条 | 可做权限页基线 | -| Capacity policy | 已覆盖 1 条 | 可做 assignment policy 基线 | -| Captain assistant | 已覆盖 1 条 | 只够列表/详情基线,不够真实 AI 回路 | -| Captain message | 已覆盖 1 条 | 适合 conversation 内 Captain message 渲染 | -| Agent bot | 已覆盖 1 条 | 适合 agent bot 页面基线 | - -基于当前代码和脚本,仍然明确缺失、会影响“全量实际功能测试”的项如下: - -| 优先级 | 缺失项 | 为什么缺 | 直接影响 | -|---|---|---|---| -| P0 | 第二个可登录 agent | 当前 smoke seed 只准备管理员,没有双坐席协作基线 | 分配、在线状态、mentions、团队协作、跨坐席实时 | -| P0 | `fake_01` 对应 inbox 基线 | 当前 seed 侧重 `web_widget` smoke inbox,不是 fake channel inbox | fake webhook 主链路、会话实时回流、回复 E2E | -| P0 | 6+ 条不同状态会话 | 当前 seed 只有 1 条 open conversation | dashboard 列表、筛选、报表、批量操作、状态流转 | -| P0 | 更丰富的消息类型 | 当前仅 text + CSAT template | private note、attachment、email、AI 消息、系统事件渲染 | -| P1 | Teams 2 条以上 | 当前未见 smoke team 基线 | team 过滤、team assign、team report | -| P1 | Labels 5 条以上 | 当前会话只有字符串标签,不是完整标签数据集 | 标签设置页、筛选器、报表 | -| P1 | Contacts 8+ / Companies 3+ | 当前各只有 1 条 | CRM 列表、搜索、合并、关联、空态外真实分页 | -| P1 | Canned responses / Macros / Automations | 当前 seed 未覆盖 | 设置 CRUD、回复提效、自动化规则 | -| P1 | Custom attributes 三类对象各 2 条 | 当前仅对象上有少量属性值,不是完整属性定义 | 表单、筛选、详情编辑 | -| P1 | Notifications / Audit logs 有内容 | 当前 seed 未覆盖可见事件流 | 通知页、审计日志页、跳转链路 | -| P1 | Copilot fake provider | 当前仓库只有真实配置入口,没有本地 fake provider 基线 | Copilot/Captain 成功/失败/超时/429 验证 | -| P2 | Email inbox / API inbox | 当前 smoke seed 未覆盖 | channel create/edit、provider 配置、空态/降级态之外的实际流程 | -| P2 | Campaign 样本 | 当前未覆盖 live chat / sms / whatsapp 实例 | campaign 列表、编辑、启停、触发条件 | -| P2 | Captain documents / responses / scenarios / tools | 当前仅 assistant/message 基线 | Captain 子页 CRUD、embedding、playground、tool 调用 | -| P2 | 多 locale Help Center 数据 | 当前 seed 基本是单 portal、单 locale | locales / categories / settings 多语言验证 | - -建议把数据准备再拆成三条线并行推进: - -1. `cmd/gochat seed` 继续承担“可登录 + 可进入页面”的 smoke 基线。 -2. `channels/fake` 负责批量制造真实消息、会话状态变化、typing、agent online/offline。 -3. 新增 `fake:ai` 后,再把 Copilot / Captain 的成功、失败、超时、429 路径补齐成可回放证据。 - -### 4.4 按页面分组看数据阻断关系 - -为了执行时不把“页面 bug”和“数据没准备好”混为一谈,建议按页面分组提前标记它们依赖的最小数据集: - -| 页面组 | 最小依赖数据 | 缺失时会怎么 blocked | -|---|---|---| -| 登录 / 账号切换 / Profile | administrator、至少 1 个 account、至少 1 个可登录 agent | 无法进入主应用、无法验证 account switch / profile 保存 | -| Dashboard / Conversations / Mentions / Unattended | `fake_01` inbox、6+ conversations、3+ message types、2 个 agent | 列表空、实时链路无证据、分配/协作不可测 | -| Contacts / Companies | 8+ contacts、3+ companies、custom attributes | 只能看到空态,搜索/合并/关联无法完成 | -| Reports | conversations、labels、teams、CSAT、SLA、audit/event 数据 | 图表和表格只剩空态,无法验证筛选/导出/维度切换 | -| Settings - Agents / Teams / Labels | 2 个 agent、2 个 teams、5 个 labels、1 个 custom role | 只能验渲染,无法验成员绑定、权限边界、筛选联动 | -| Settings - Inboxes / Channel create | website inbox、fake inbox、api/email/voice 至少部分样本 | 只能看入口,无法验证编辑页、collaborators、business hours、channel 特有字段 | -| Settings - Automation / Macros / Canned Responses | 3 automation、3 macros、3 canned responses | 列表可打开但无法验证 CRUD 与执行结果 | -| Help Center | 1 portal、1 locale、2 categories、3 articles | 只能做最浅页面进入,发布/预览/分类/多语言不完整 | -| Campaigns | website inbox、portal、至少 1 live chat campaign 样本 | 只能看空态,无法验证创建/启停/触发条件 | -| Notifications / Audit logs | 5+ notifications、5+ audit logs | 只能确认页面壳存在,跳转和已读不可测 | -| Copilot / Captain | fake provider、assistant、documents、responses、scenarios、tools | 只能验页面渲染,无法做 AI 成功/失败/超时全链路 | -| Widget / public | website inbox、public help center、CSAT 样本、真实站内入口 | 即使内部后台健康,也无法完成 public/user 侧闭环验收 | - -推荐执行时先给每个页面组打一个前置标签: - -- `ready`:数据和入口都齐,可以做完整功能断言 -- `render-only`:只能做渲染/空态/入口断言 -- `blocked-by-data`:缺数据,先补数据再测 -- `blocked-by-entrypoint`:入口未接通,不应靠手输内部 URL 绕过 ## 5. `fake:ai` 最小方案 -先加一个本地 fake AI 服务,目标是“可测”,不是模拟完整 LLM。 - -建议命令: - -```bash -pnpm fake:ai -``` - -建议端口:`9200`。 - -最小 API: - -| 方法 | 路径 | 用途 | 响应 | -|---|---|---|---| -| GET | `/health` | 健康检查 | `{ "status": "ok" }` | -| GET | `/v1/models` | OpenAI-compatible 模型列表 | `fake-chat`, `fake-embedding` | -| POST | `/v1/chat/completions` | Copilot / Captain 回复 | 回显 prompt 摘要,支持固定 delay/error | -| POST | `/v1/embeddings` | 文档 embedding | 固定维度向量 | -| POST | `/api/config` | 切换模式 | `ok/error/slow/rate_limit` | -| GET | `/api/requests` | 测试断言 | 最近请求列表,脱敏 Authorization | -| POST | `/api/reset` | 清空状态 | `{ "status": "ok" }` | - -Provider 配置建议: - -| 字段 | 值 | -|---|---| -| provider | `openai_compatible` | -| base_url | `http://127.0.0.1:9200/v1` | -| api_key | `fake-ai-key` | -| chat model | `fake-chat` | -| embedding model | `fake-embedding` | -| embedding dimensions | `1536` | - -必须覆盖的 AI 场景: - -1. Copilot 配置页保存 fake provider。 -2. 测试连接成功、失败、超时、429 四种状态。 -3. Captain Playground 输入问题,收到 fake answer。 -4. Captain document embedding 调用 fake embeddings。 -5. Agent 回复框 AI 改写/建议调用 fake chat。 -6. 错误态不泄露 API key。 - -跳过:真实 OpenAI/Anthropic/DeepSeek 兼容性;等 fake 链路稳定再做外部 provider smoke。 - -### 5.1 `fake:ai` 实现方式建议(直接复用 fake channel 骨架) - -为了少造轮子,`fake:ai` 建议直接按 `channels/fake` 的组织方式复制一套最小骨架: - -| 项 | 建议 | -|---|---| -| 目录 | `channels/fake-ai/` | -| 启动脚本 | 根 `package.json` 增加 `fake:ai` / `fake:ai:dev` / `fake:ai:test` | -| 运行时 | `tsx src/index.ts` | -| HTTP 框架 | 继续用 Express,和 fake channel 保持一致 | -| 状态存储 | 先用内存 store,记录最近请求、模式、延迟、错误注入 | -| 模式切换 | `/api/config` 支持 `ok` / `error` / `slow` / `rate_limit` | -| 测试断言 | `/api/requests` 返回最近 chat / embeddings 请求摘要 | -| 脱敏 | 所有请求日志都隐藏 Authorization / api_key | - -建议脚本: - -```json -{ - "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" -} -``` - -这样后续维护会和 `fake:start` 基本同构,排查成本也低。 - -补充说明:当前仓库根 `package.json` 里已经有 `fake:start / fake:dev / fake:test`,并且 `pnpm-workspace.yaml` 已纳入 `channels/fake`;但还没有现成的 `channels/fake-ai` 目录和 `fake:ai` 脚本,所以这部分目前仍属于待新增测试支撑能力,而不是现成可执行项。 - -### 5.2 `fake:ai` 断言矩阵 - -`fake:ai` 不只是“让页面不报错”,还要能作为 CDP 回放时的稳定证据源。建议第一版就固定支持下面这几类断言: - -| 场景 | CDP 页面动作 | `fake:ai` 需要返回 | 测试证据 | -|---|---|---|---| -| Provider 连通性测试 | Settings → Copilot → Test connection | 200 + 固定模型列表 | 页面成功提示 + `/api/requests` 有 `GET /v1/models` | -| Provider 保存后首次使用 | 保存 fake provider 后进入 Copilot/Captain | `GET /v1/models` 或首次 chat 请求成功 | 配置持久化成功 + 后续 AI 页面可继续使用 | -| Copilot 发问 | 会话侧边栏输入问题并发送 | `POST /v1/chat/completions` 返回固定答复 | 气泡渲染 + `/api/requests` 记录 prompt 摘要 | -| Captain Playground | Playground 输入问题 | `POST /v1/chat/completions` 返回固定答复 | 页面回复 + 请求日志 | -| Reply suggestion / rewrite / summarize | 回复框触发 AI 建议 | `POST /v1/chat/completions` 返回不同 action 标记 | 建议文本正确落入 UI,对应 action 可区分 | -| Document embedding | 上传 URL/PDF 文档后触发 embedding | `POST /v1/embeddings` 返回固定维度向量 | 文档状态变化 + `/api/requests` 有 embedding 记录 | -| Slow provider | 切到 `slow` 模式后重试 | 延迟 3~8 秒再返回 200 | 页面 loading、可取消/可恢复、无死锁 | -| Error provider | 切到 `error` 模式后重试 | 500 或结构化错误 | toast / inline error 正确展示,不泄露 key | -| Rate limit | 切到 `rate_limit` 模式 | 429 | 页面可见限流反馈、不会假成功 | -| 敏感信息脱敏 | 任意 AI 请求 | `fake:ai` 仅记录掩码后的鉴权信息 | `/api/requests` 不出现明文 `Authorization` / `api_key` | - -建议 `fake:ai` 每条请求至少记录这些字段,便于后续 report 复用: - -- `ts` -- `method` -- `path` -- `mode` -- `model` -- `account_id`(若请求链路可带出) -- `request_summary`(截断后的 prompt/输入摘要) -- `response_status` -- `latency_ms` -- `auth_masked` - -### 5.3 当前仓库核对结果(2026-07-19) - -这部分是为了把“计划建议”和“当前仓库现实”分开: - -| 项 | 当前状态 | 结论 | -|---|---|---| -| 根脚本 `fake:start / fake:dev / fake:test` | 已存在 | fake channel 现成可用,可直接作为消息 E2E 基线 | -| 根脚本 `fake:ai` | 不存在 | 需要新增 | -| workspace 包 | 当前只纳入 `frontend`、`channels/fake` | `channels/fake-ai` 需要加入 workspace | -| `channels/fake-ai/` 目录 | 不存在 | 需要新建最小服务骨架 | -| 现有 `channels/fake` 结构 | 已具备独立 package + tsconfig | 适合直接镜像出 `fake-ai` 的最小实现 | - -因此,“AI 相关测试可参考 fakechannel 搞一个 fake:ai 来支持对接”在当前仓库里应拆成明确的补齐任务: - -1. 新建 `channels/fake-ai/`,提供独立 `package.json`、`tsconfig.json`、`src/index.ts`。 -2. 根 `package.json` 增加 `fake:ai`、`fake:ai:dev`、`fake:ai:test`。 -3. `pnpm-workspace.yaml` 纳入 `channels/fake-ai`。 -4. 提供最小 `/health`、`/v1/models`、`/v1/chat/completions`、`/v1/embeddings`、`/api/config`、`/api/requests`、`/api/reset`。 -5. GoChat 内新增一套本地 fake provider 配置模板,方便 Copilot / Captain 直接切过去联调。 - -### 5.4 当前 `channels/fake` 已可直接复用的测试能力(2026-07-19 核对) - -为了避免把 `fake channel` 和未来的 `fake:ai` 混在一起,这里把当前已经现成可用的 fake 消息平台能力单独列出来: - -| 能力 | 当前端点 | 可直接支撑的测试 | -|---|---|---| -| 健康检查 | `GET /health` | 执行前确认 fake 服务在线 | -| 运行时改配置 | `POST /api/config` | 动态切换 webhook、token、auto reply、delay | -| 客户入站消息 | `POST /api/send` | 造新会话、造入站消息、验证 dashboard 实时出现 | -| 客户回复消息 | `POST /api/reply` | 验证 reply_to / 同会话追加消息 | -| 会话结束事件 | `POST /api/close` | 验证 session.end、关闭链路、状态流转 | -| typing 事件 | `POST /api/typing` | 验证 typing.start / typing.stop UI 提示 | -| agent 在线状态观测 | `POST /api/agent/online`、`POST /api/agent/offline` | 验证 presence / availability 展示 | -| 出站消息留痕 | `GET /api/messages`、`GET /api/messages/:id` | 断言客服回复有没有真正发回 fake 平台 | -| 平台状态观测 | `GET /api/status` | 观察 auto reply、消息计数、agent 状态 | -| 内存态重置 | `POST /api/reset` | 每轮 CDP 测试前清理平台状态 | - -基于当前实现,`channels/fake` 已经足够支撑这几类真实验收: - -1. fake 客户发消息 → GoChat 创建或追加会话。 -2. 客服在 dashboard 回复 → fake 平台能收到 outbound。 -3. auto reply 回流 → dashboard 无刷新出现下一条 incoming。 -4. typing / session.end / agent online/offline 等外围实时事件可单独回放。 - -但它还不是“批量数据工厂”,当前仍缺这些会明显影响全量页面验收的能力: - -- 批量制造多状态会话(open / pending / resolved / snoozed); -- 批量制造更多消息类型(private note、attachment、email-like、system event); -- 一次性造多联系人、多公司、多标签、多 team 的数据集; -- AI provider 兼容接口(这部分应由独立的 `fake:ai` 负责,而不是继续堆进 `channels/fake`)。 +(省略详细方案 — 参见 `docs/qa/2026-07-15-cdp-user-function-test-plan.md` §5,关键词:fake provider、模拟请求、错误态注入) ## 6. 页面功能矩阵 ### 6.1 Auth / account lifecycle | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | 登录 | `/app/login` | 正确登录、错误密码、空表单校验、无注册链接、回车提交 | | SSO 登录 | `/app/login/sso` | 无配置时错误态,配置后跳转态 | | 重置密码 | `/app/auth/reset/password` | 表单校验、提交反馈 | @@ -507,7 +298,7 @@ Provider 配置建议: ### 6.2 Inbox / conversation | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Dashboard | `/app/accounts/:id/dashboard` | 会话列表、筛选、排序、在线状态、未读数 | | 会话详情 | `/conversations/:conversation_id` | 消息渲染、发送、私密备注、附件、emoji、引用、草稿 | | Inbox 会话 | `/inbox/:inbox_id` | inbox 筛选、列表一致性 | @@ -534,13 +325,13 @@ Provider 配置建议: 说明: -- 当前 dashboard 登录后的默认会话请求是 `assignee_type=me`,即“我的”视图。 -- fake 入站若创建的是未分配会话,验证会话可见性时应继续点击切到 `未分配的` 或 `所有的`,不要把“我的”视图下不可见误判成实时失败。 +- 当前 dashboard 登录后的默认会话请求是 `assignee_type=me`,即"我的"视图。 +- fake 入站若创建的是未分配会话,验证会话可见性时应继续点击切到 `未分配的` 或 `所有的`,不要把"我的"视图下不可见误判成实时失败。 ### 6.3 CRM | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Contacts | `/contacts` | 列表、搜索、分段、标签过滤、新建 | | Contact detail | `/contacts/:contactId` | 编辑资料、custom attributes、会话历史、备注 | | Companies | `/companies` | 列表、搜索、新建 | @@ -549,7 +340,7 @@ Provider 配置建议: ### 6.4 Reports | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Overview | `/reports/overview` | 指标卡、日期范围、图表 | | Conversations | `/reports/conversations` | 表格、导出、筛选 | | Agents | `/reports/agents` | agent 维度指标 | @@ -564,7 +355,7 @@ Provider 配置建议: ### 6.5 Settings | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Account | `/settings/account` | 名称、语言、auto-resolve、删除保护 | | Agents | `/settings/agents/list` | 创建 agent、临时密码、编辑、禁用、重置密码 | | Teams | `/settings/teams/list` | 创建、成员、编辑、删除 | @@ -591,12 +382,12 @@ Provider 配置建议: | Billing | `/settings/billing` | subscription/limits 降级态 | | Profile | `/profile/settings` | 资料、密码、消息签名、通知偏好、access token、MFA | | Notifications | `/notifications` | 列表、已读、跳转 | -| Copilot 配置 | `/settings/copilot` 或当前实际入口 | fake provider 保存、测试连接、账户功能开关 | +| Copilot 配置 | `/settings/captain` | fake provider 保存、测试连接、账户功能开关 | ### 6.6 Help Center | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Portals | `/portals/:navigationPath` | portal 列表、新建 | | Articles | `/portals/:slug/:locale/articles` | 列表、草稿/发布 tab | | Article editor | `articles/new` / `edit/:slug` | 标题、正文、保存、发布 | @@ -608,7 +399,7 @@ Provider 配置建议: ### 6.7 Campaigns | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Live chat campaigns | `/campaigns/live_chat` | 新建、编辑、启停、触发条件 | | SMS campaigns | `/campaigns/sms` | 空配置降级、表单校验 | | WhatsApp campaigns | `/campaigns/whatsapp` | provider 缺失提示、模板字段 | @@ -616,7 +407,7 @@ Provider 配置建议: ### 6.8 Captain / AI | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Assistants | `/captain/:navigationPath` | assistant 列表、新建、切换 | | FAQs / Responses | `/captain/:assistantId/faqs` | CRUD、搜索、批量删除 | | Pending responses | `/faqs/pending` | approve/reject | @@ -632,7 +423,7 @@ Provider 配置建议: ### 6.9 Widget / public | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | Widget home | `/widget?website_token=...#/home` | 可用性、欢迎语、campaign | | Widget messages | `/widget?website_token=...#/messages` | 客户发消息、附件、emoji、历史 | | Pre-chat widget | widget pre-chat | 表单字段、必填校验 | @@ -643,7 +434,7 @@ Provider 配置建议: ### 6.10 Global shell / personal / super admin | 页面 | 路径 | 功能点 | -|---|---|---| +|------|------|--------| | 侧边栏与全局壳层 | dashboard 任意已登录页 | logo、主导航、收起/展开、未读徽标、当前激活态 | | 用户菜单 | 侧边栏头像菜单 | 键盘快捷键弹层、更改外观、个人设置入口、退出登录 | | 账号切换 | 用户菜单中的 account switcher | 不同 account 间切换、URL/accountId 同步、权限不足账号不应泄露 | @@ -654,7 +445,7 @@ Provider 配置建议: ### 6.11 页面统一验收模板 -为了避免“有些页面只看打开,有些页面又测到了保存”,后续 CDP 执行时建议所有页面按页面类型套同一套断言模板。 +为了避免"有些页面只看打开,有些页面又测到了保存",后续 CDP 执行时建议所有页面按页面类型套同一套断言模板。 #### A. 列表页 @@ -734,202 +525,175 @@ curl -fsS -X POST http://127.0.0.1:9100/api/reset ```bash curl -fsS -X POST http://127.0.0.1:9100/api/config \ -H 'Content-Type: application/json' \ - -d '{"webhook_url":"http://127.0.0.1:3000/webhooks/fake/fake_01","auto_reply":true}' + -d '{"webhook_url":"http://127.0.0.1:3000/webhooks/fake/fake_01","token":"fake_test_token"}' ``` -3. 入站消息: +3. 入站: ```bash curl -fsS -X POST http://127.0.0.1:9100/api/send \ -H 'Content-Type: application/json' \ - -d '{"inbox_identifier":"fake_01","sender_id":"cdp_customer_01","sender_name":"CDP测试客户","content":"CDP 全量测试入站消息"}' + -d '{"inbox_identifier":"fake_01","sender_id":"customer_reg","sender_name":"回归测试客户","content":"全量回归测试消息"}' ``` -4. CDP 断言 dashboard 出现 `CDP测试客户` 和消息内容。 -5. CDP 在回复框发送 `收到,正在测试。` -6. fake 断言: +4. 验证 GoChat 返回 `{"status":"success"}`(不是 `ignored`) + +5. DB 验证: + +```sql +SELECT id, content, sender_type, inbox_id, conversation_id +FROM messages WHERE inbox_id=3 ORDER BY id DESC LIMIT 5; +``` + +6. 出站验证: ```bash -curl -fsS http://127.0.0.1:9100/api/messages +curl http://127.0.0.1:9100/api/messages?inbox_identifier=fake_01 ``` -7. CDP 断言 auto reply 回流后同一会话增加客户消息。 - ## 8. 报告格式 -生成到: +每个测试条目记录: -```text -docs/qa/reports/2026-07-15-cdp-user-function-report.md -.tmp/cdp-qa/2026-07-15/ -``` - -报告必须包含: - -- 服务基线:health、登录账号、测试 account id、fake config。 -- 页面矩阵:pass/fail/blocked/skipped。 -- 每个失败:复现路径、请求、响应、console、截图、影响等级。 -- 数据缺口:缺哪条 seed 导致 blocked。 -- fake channel 证据:`/api/messages` 摘要。 -- fake:ai 证据:`/api/requests` 摘要。 +| 条目 | 内容 | +|------|------| +| 日期时间 | `YYYY-MM-DD HH:mm` | +| 测试者 | | +| 页面 | 页面标题 | +| 点击路径 | 从登录后的完整点击链 | +| 关键断言 | 见 §6.11 模板 | +| API 状态 | 所有请求的状态码(截取异常) | +| Console | error/warning 摘要 | +| 结果 | PASS / FAIL / PASS with issue | +| 证据 | API 响应、DB 查询、截图引用 | ## 9. 第一轮执行顺序 -1. 登录和 WebSocket。 -2. fake channel 消息 E2E。 -3. Dashboard / conversation 核心路径。 -4. Settings 中会影响后续数据的页面:agents、teams、inboxes、labels、attributes。 -5. Reports。 -6. Help Center / Campaigns / Widget。 -7. Captain / Copilot,先用 `fake:ai`。 -8. 权限用户回归:agent、custom role。 - -这样排是为了先证明链路活着,再铺开页面。最省事,也最不容易把数据缺口误判成产品 bug。 +1. Phase 1 — 环境预检 + 登录 +2. Phase 2 — Auth 表单验证 +3. Phase 3 — Dashboard + Conversation 主链路 +4. Phase 4 — Widget E2E(init → send → auto-reply → verify) +5. Phase 5 — Settings 全 22 页 +6. Phase 6 — Reports 全 10 页 +7. Phase 7 — CRM(Contacts + Companies) +8. Phase 8 — Captain/Copilot/AI +9. Phase 9 — Search + Notifications + Shell +10. Phase 10 — Fake E2E + Conversation API ## 10. 当前已知高风险 / 预期阻断 -以下问题已经在点击驱动验收中出现,后续 CDP 全量测试时应直接按“产品缺陷”记录,不要误归类成数据缺口: - -| 项 | 当前现象 | 建议分类 | -|---|---|---| -| fake auto reply 回流 | 最新观测表明平台侧 echo 已回流,但 GoChat 侧会出现“新会话分叉”或“同会话重复/顺序异常渲染”两类缺陷,均应按链路问题记录 | P1 链路缺陷 | -| widget / public 入口 | Website inbox `脚本 / CodePen / 预览 / Chat mode` 已基本穷举,但仍未发现可作为“真实 public/widget 用户入口”验收的稳定点击路径;`CodePen` 外跳也不能替代站内入口 | P1 入口未接通 | -| Help Center 后台三页 | `设置 / 类别 / 语言` 三页在 fresh session 中仍稳定落入空白主区,而 `文章` 列表、编辑、预览链路健康,说明是局部后台渲染缺陷,不是整套帮助中心都坏 | P1 页面主内容未渲染 | -| Super admin 入口 | 从用户菜单点击 `超级管理员控制台` 后,当前 tab 未进入 `/super_admin`;额外新 tab 实为此前 CodePen 的迟到外跳 | P1 入口失效 | -| 通知入口识别 | 顶部无文案按钮当前确认打开的是“新消息/全局发消息”弹层,不是通知中心;真正通知入口在当前健康链路里仍待明确 | P2 验收前置澄清 | -| Captain AI 主链路 | `FAQ / 文档 / Scenarios / 试验场 / 收件箱 / 工具 / 设置 / Guardrails / Response guidelines` 已在健康 click-only 链路下证明可渲染;其中 `试验场` 等真实 AI 效果仍需 `fake:ai` 才能做成功/失败/超时/429 全链路断言 | P1 测试依赖未就绪 | -| Campaign SMS / WhatsApp | 这两页在后续 fresh session 中已能正常渲染内容与空态,不再作为稳定阻断项;后续只需继续做创建/编辑/触发层面的功能验收 | 已从阻断项移除 | - -执行原则: - -1. 这类问题一旦复现,不再继续用补数据方式兜底。 -2. 报告里要保留“点击路径 + 最终 URL + main 区域状态 + 关键请求/快照”四类证据;如果不是空白而是错误态,也要按真实渲染结果记录。 -3. widget / public 相关在真正站内入口修好前,只保留入口级验证,不做功能通过判定。 -4. Captain 当前不要再按“稳定白屏”预设处理;除了真实 AI 依赖项外,应继续按正常页面矩阵做列表/表单/子页验收。 +- widget / public 入口:当前无稳定的 dashboard 内入口可直达 widget 和 public help center 页面,需要通过手输 URL 打开。这会违反"不允许直接打开深层 URL"约束,需要确认本次测试是否将该约束放宽到 widget/public 页面。 +- Conversation list 渲染时序:在极少数情况下 ChatList 组件 `onMounted` 未触发 `fetchAllConversations`,需要在测试中手动观察。 +- Captain playground:当前 `fake:ai` 尚未完全对接 Captain/Copilot,playground 的 AI 回复断言在 `fake:ai` 到位前只能做 UI 渲染检查。 +- `custom_filters` 与 `custom_views` 的路由:前端 Vue Router 命名为 `custom_view/:id`,但 API 路径为 `custom_filters`,回归测试中需要注意路由错误不是后端缺失。 +- Billing / Enterprise 端点:需要 cookie CSRF token,API-only 测试会得到 403,需要在 SPA 上下文内测试。 ## 11. 执行前补齐清单(可直接转实施) -这一节把“测试计划”“缺数据”“缺 fake:ai 支撑”压成执行清单,避免后续再来回翻全文。 +(以下为真实缺失项,标注了文件路径和改写建议) -### 11.1 P0:不补就没法做全量功能验收 +### 11.1 补充 `cmd/gochat seed`:缺少双 agent、CRM 批量数据、多状态会话 -| 项 | 需要补什么 | 建议落地方式 | 完成标准 | -|---|---|---|---| -| 登录与权限基线 | 1 个管理员、2 个可登录 agent、1 个 custom role 用户 | `cmd/gochat seed` + 后台补齐 | 三类账号都能真实登录,菜单和权限差异可见 | -| fake 会话主链路 | `fake_01` inbox、fake webhook 正常、会话能进入正确列表 | inbox 配置 + `pnpm fake:start` | 入站、客服回复、auto reply 回流三段都能留证据 | -| 基础会话池 | 至少 6 条不同状态会话,每条 3+ 消息 | fake channel 批量灌数 | open / pending / resolved / snoozed 都能在 UI 中找到 | -| 页面不再只剩空态 | contacts 8+、companies 3+、labels 5、teams 2 | seed 或 UI 创建 | CRM、筛选、报表、分配页面不再被空数据阻断 | -| AI 本地假服务 | `channels/fake-ai` + 根脚本 `fake:ai` | 复用 fake channel 骨架 | Copilot / Captain 能走本地假 provider 成功/失败/超时/429 | +- 当前 seed 只创建了 1 个 admin + 1 个 contact + 1 个 conversation。 +- 导致 Settings→Agents/Teams 只有 1 人,无法做分配/团队测试。 +- Contact 列表只有 1 条,分页/搜索/标签过滤无数据。 +- CSAT/SLA 报表无数据,只能验证空态。 -### 11.2 P1:不补会导致“大量页面只能做 render-only” +### 11.2 `channels/fake`:缺少批量造数和多状态回放 -| 项 | 需要补什么 | 影响页面 | -|---|---|---| -| 回复提效数据 | canned responses 3、macros 3、automation rules 3 | 回复框、设置 CRUD、自动化 | -| 属性与筛选数据 | contact / conversation / company custom attributes 各 2 | CRM、筛选器、自动化条件 | -| 通知与审计数据 | notifications 5、audit logs 5 | 通知中心、审计日志、跳转链路 | -| Help Center 丰富数据 | 1 portal、2 categories、3 articles、2 locales | 后台 portal、public help center、多语言 | -| Campaign 样本 | live chat / sms / whatsapp 至少各 1 个样本 | Campaigns 列表、编辑、启停 | -| Captain 子资源 | documents 3、responses 5、scenarios 2、tools 1 | Captain 子页 CRUD、Playground、文档链路 | +- 当前 fake 每次 send 都新建 conversation,无法生成聚集到同一会话的多条消息。 +- 缺少 `resolve` / `snooze` 等状态造数能力,Conversation API 切换状态后没有可刷新验证的持久化会话。 +- 建议加 `conversation_id` 参数,指定时追加到现有会话而非新建。 -### 11.3 `fake:ai` 的最小验收标准 +### 11.3 加 fake inbox / bootstrap -`fake:ai` 只要做到下面这些,就足够支撑本轮 CDP 页面级功能验收: +- 当前 fresh 环境跑起来后,`fake_01` 对应的 inbox 没有在 seed 或首次启动时自动创建。 +- 需要在 `cmd/gochat seed` 或首次 health check 时确保 `fake_01` inbox 存在且 webhook 指向 `:3000/webhooks/fake/fake_01`。 +- 否则 fake E2E 第一步就断——docker compose up 后还需要手动去 Settings 建 fake inbox。 -| 能力 | 最小要求 | 为什么必须有 | -|---|---|---| -| OpenAI-compatible chat | `POST /v1/chat/completions` 返回固定答复 | Copilot / Captain / reply suggestion 要能成功走通 | -| OpenAI-compatible embeddings | `POST /v1/embeddings` 返回固定维度向量 | Captain documents / embedding 状态要能推进 | -| 模式切换 | `ok / error / slow / rate_limit` | 页面要验证成功、失败、超时、429,而不是只测 happy path | -| 请求留痕 | `GET /api/requests` 可查最近请求摘要 | 报告要拿得到 AI 调用证据,不只截图 | -| 脱敏 | 不记录明文 `Authorization` / `api_key` | 测试日志不能泄露敏感配置 | +### 11.4 新建 `channels/fake-ai` -### 11.4 推荐实施顺序 - -1. 先补账号、`fake_01` inbox、基础会话池。 -2. 再补 contacts / companies / labels / teams,让 dashboard、CRM、reports 能进入“非空态测试”。 -3. 然后补 canned responses / macros / automation / custom attributes,打通 settings 主体 CRUD。 -4. 再补 Help Center / campaigns / notifications / audit logs 这些页面群的数据。 -5. 最后实现 `fake:ai`,把 Copilot / Captain 从 render-only 升级成真实功能验收。 - -### 11.5 本轮文档产出对应关系 - -为避免后续拆任务时语义漂移,这份计划文档里的三类产出边界如下: - -| 产出 | 本文档里对应内容 | 后续动作 | -|---|---|---| -| CDP 测试执行规则 | 第 1、2、3、6、7、8、9、10 节 | 后续按此直接做 click-only QA 和 report 追加 | -| 影响全量测试的数据缺口 | 第 4 节 + 本节 11.1 / 11.2 | 后续可拆成 seed、fake、后台初始化任务 | -| AI 测试支撑方案 | 第 5 节 + 本节 11.3 | 后续单独实现 `fake:ai` 并接入 Copilot / Captain | - -### 11.6 建议直接拆出的实施任务 - -为了把“计划文档”顺滑转成“落地任务”,建议按下面 4 个实施包推进: - -| 任务包 | 目标 | 建议落地位置 | 完成标志 | -|---|---|---|---| -| A. smoke seed 扩容 | 从单管理员/单会话扩到可支撑大部分页面验收 | `backend/cmd/gochat seed` | 能一次性产出 2 agents、更多会话状态、更多 contacts/companies/labels/teams | -| B. fake channel 批量造数 | 把会话、消息类型、实时事件做成可重复回放 | `channels/fake` | 能按脚本批量制造 open/pending/resolved/snoozed、typing、reply、close | -| C. fake inbox/bootstrap | 让 `fake_01` 不再靠手工散配置维持 | seed + inbox/bootstrap script | fresh 环境里一条命令后即可直接收发 fake webhook | -| D. fake:ai | 给 Copilot/Captain 提供本地稳定 AI 依赖 | `channels/fake-ai` | chat/completions、embeddings、mode switch、request log 全部可用 | - -推荐先后顺序: - -1. 先做 A + C,保证 dashboard 主链路可测。 -2. 再做 B,把 reports / CRM / settings 从“空态浏览”升级成“真实数据验证”。 -3. 最后做 D,把 Captain / Copilot 从 render-only 升级成完整 E2E。 +- 当前 Copilot/Captain 对接的是真实的 deepseek-v4-flash provider(`http://10.58.144.6:2014/v1`)。 +- 这种外部依赖在自动化测试中不稳定:一旦外网/内网 LLM API 不可达,Captain 页面的 AI 回复断言就全断。 +- 需要一个 `fake:ai` 同级服务,用本地预设响应替代真实 LLM 调用,确保 AI 页面可脱离第三方独立验证。 ## 12. 执行前一页纸清单 -这一节是给真正开跑 CDP 全量验收时直接照着做的,避免再从前文抽命令。 - -### 12.1 环境与服务核对 - ```bash -curl -fsS http://127.0.0.1:3000/health -curl -fsS http://127.0.0.1:9100/health -curl -fsS http://127.0.0.1:9222/json/version +# === 1. 确认服务 === +curl -fsS http://127.0.0.1:3000/health # expect 200 +curl -fsS http://127.0.0.1:3036/app/login # expect login page HTML +curl -fsS http://127.0.0.1:9100/health # expect {"status":"ok"} + +# === 2. 重置环境态 === +curl -fsS -X POST http://127.0.0.1:9100/api/reset + +# === 3. 确认 inbox 和数据 === +PGPASSWORD=xiha02 psql -h 127.0.0.1 -p 5444 -U postgres -d gochat_dev \ + -c "SELECT count(*) FROM conversations; SELECT count(*) FROM contacts;" + +# === 4. 配置 fake webhook === +curl -fsS -X POST http://127.0.0.1:9100/api/config \ + -H 'Content-Type: application/json' \ + -d '{"webhook_url":"http://127.0.0.1:3000/webhooks/fake/fake_01","token":"fake_test_token"}' + +# === 5. 打开 CDP === +# 已打开的 Chrome 监听 localhost:9222 +curl -fsS http://127.0.0.1:9222/json/version | python3 -c "import json,sys;d=json.load(sys.stdin);print(d.get('webSocketDebuggerUrl',''))" + +# === 6. 检查 Browser Console 基线 === +# 登录后:window.__resetConsole(); 再检查 ``` -通过标准: +### 12.1 预检查快速清单 -1. backend 返回 200。 -2. fake channel 返回 `{"status":"ok","service":"fake-message-platform"}`。 -3. CDP debug 口能返回 `webSocketDebuggerUrl`。 +- [ ] backend 3000 health = ok +- [ ] frontend 3036 login page = 200 +- [ ] fake 9100 health = ok +- [ ] 已知至少 1 个 inbox(website_token=gochat-smoke-widget-token) +- [ ] 已知至少 1 个可登录用户(admin@gochat.local / changeme) +- [ ] Cookie `cw_d_session_info` 与 localStorage auth token 同步 +- [ ] CDP debug port = 9222 可连 -### 12.2 现有仓库能力 vs 需要新增的能力 +### 12.2 每页执行快速协议 -| 类别 | 当前已具备 | 仍需新增 | -|---|---|---| -| 本地消息 fake | 根脚本 `fake:start` / `fake:dev` / `fake:test`,workspace 已纳入 `channels/fake` | 批量造多状态会话、多消息类型、批量造数接口 | -| AI fake | 无 | `channels/fake-ai`、根脚本 `fake:ai*`、workspace 纳入 `channels/fake-ai` | -| smoke seed | `go run ./cmd/gochat seed` 可产出管理员、website inbox、portal/article、1 contact/company/conversation、Captain assistant 基线 | 第二个 agent、fake inbox、更多会话状态、labels/teams、通知/审计、campaign 样本 | -| 页面级执行规则 | 本文档已覆盖 click-only + report sink + fake/fake:ai 证据要求 | 后续按本文档直接执行 | +``` +0. window.__resetConsole() +1. 点击导航(记录点击路径) +2. 等待 settle(2-5s) +3. snapshot 验证内容渲染 +4. 检查 console(仅 allowlist 可接受) +5. 检查网络(>3x 同 endpoint = finding,cache_keys 除外) +6. 至少一次 CRUD 交互 +7. 截取操作后 API 响应摘要 +8. 点下一个页面前再读一次 console +``` -### 12.3 数据准备责任分层 +### 12.3 Console 警告 Allowlist -为了避免后续把所有“补数据”都塞进一个入口,建议这样拆: +以下警告不视为 finding: -| 层 | 负责内容 | 最适合落地位置 | -|---|---|---| -| smoke seed | 可登录账号、website inbox、portal/article、最小 smoke records | `backend/cmd/gochat seed` | -| fake channel | 批量制造会话、消息、typing、close、online/offline | `channels/fake` | -| 后台 UI 自举 | labels、teams、macros、canned responses、custom attributes、部分 portal/campaign | CDP 执行过程中顺手创建 | -| fake AI | chat/completions、embeddings、error/slow/429 模式、请求留痕 | `channels/fake-ai` | +| 警告 | 说明 | 等级 | +|------|------|------| +| `[DEPRECATED] The 'onClose' prop is deprecated` | Widget/UI 组件 | P4 | +| `[DEPRECATED] has be deprecated` | 旧 WootInput 组件 | P4 | +| `Lit is in dev mode` / `Multiple versions of Lit loaded` | 初始加载 | P4 | +| `[Vue Router warn]: Discarded invalid param(s) "page"` | 路由导航 | P4 | +| `SW registration failed (SecurityError)` | Vite dev server | P4 | -### 12.4 建议先补的 5 个最小 blocker +### 12.4 重置触发条件 -只要还没补齐下面 5 项,就不要把结果叫“全量实际功能验收完成”: +遇到以下情况触发重置流程: -1. 第二个可登录 agent。 -2. `fake_01` 对应 inbox 和 webhook 主链路。 -3. 至少 6 条不同状态会话。 -4. contacts / companies / labels / teams 的非空数据集。 -5. `fake:ai` 本地假 provider。 +- `/cable` 持续 401/403/断开重连 > 30s +- dashboard 底部常驻 `正在重连...` +- 同一页面连续出现大量 `429` 响应 +- fake 平台消息与当前测试无关(残留旧消息污染断言) +- console 中出现无法解释的 DOMException / SecurityError ### 12.5 后续实施拆单建议 -如果接下来按实现任务推进,建议就按下面 4 张单拆,不要混成一张“大而全”任务: +如果接下来按实现任务推进,建议就按下面 4 张单拆: 1. 扩 `cmd/gochat seed`:补双 agent、更多 CRM / reports / settings 基线数据。 2. 扩 `channels/fake`:补批量造数和多状态回放能力。 @@ -1119,3 +883,231 @@ curl -fsS http://127.0.0.1:9222/json/version | CRM (contact/company CRUD) | ✅ | API | | Widget SDK (init/config/messages/campaigns) | ✅ | API | | 文件上传 (Metadata jsonb 修复) | ✅ | API | + +--- + +## 15. 全量回归测试执行计划(按钮/表单级) + +> 精确到每个按钮点击、表单输入、下拉选择、toggle 开关的操作级测试清单。 + +### Phase 0 — 预检查(5 步) + +``` +□ curl :3000/health → 200 +□ curl :3036/app/login → 200 +□ curl :9100/health → ok +□ /cable 无 401/403 循环 +□ console baseline 记录 +``` + +### Phase 1 — Auth 登录(§6.1) + +| # | 操作 | 输入 | 预期 | 断言模板 | +|---|------|------|------|---------| +| 1 | 打开 `/app/login` | — | 渲染"登录到GoChat" + Email输入框 + 密码输入框 + 登录按钮 + 忘记密码链接 | A | +| 2 | 点击 Email 输入框 | — | 光标聚焦 | — | +| 3 | 点击"登录"(空表单) | — | 表单校验提示(邮箱必填) | C | +| 4 | 输入错误密码 → 点"登录" | `admin@gochat.local` / `wrong` | 401 错误消息,不跳转 | C | +| 5 | 输入正确 → 点"登录" | `admin@gochat.local` / `changeme` | 跳转 `/app/accounts/1/dashboard` | — | +| 6 | 验证 token 同步 | — | `localStorage` 含 access-token/uid/client;cookie `cw_d_session_info` 存在 | — | + +### Phase 2 — Dashboard + 会话(§6.2) + +| # | 操作 | 预期 | +|---|------|------| +| 1 | 验证会话 tab 计数:我的 X / 未分配的 X / 所有的 X | 数字 > 0 | +| 2 | 点击"未分配的"标签 | 列表切换为未分配会话 | +| 3 | 点击"所有的"标签 | 列表切换为全部会话 | +| 4 | 点击一个会话行 | 右侧面板展开,显示消息列表 | +| 5 | 验证会话详情 | sender、assignee、status、priority、labels 全部渲染 | +| 6 | 点击回复框,输入文本 → Ctrl+Enter | 消息出现,fake 收到 outbound | +| 7 | 点击私密备注图标 → 输入 → Ctrl+Enter | private_note 标记,fake 不收到 | +| 8 | 点击表情图标 → 选一个 emoji | emoji 插入回复框 | +| 9 | 点击 paperclip → 选文件 | 上传进度 → 消息附件 | +| 10 | 点击"解决"按钮 → 确认 | 状态=resolved | +| 11 | 点击"重新打开" → 确认 | 状态=open | +| 12 | 点击 inbox filter(左侧 inbox 名) | 列表按 inbox 筛选 | +| 13 | 点击"提及" | 只显示 @ 了用户的会话 | +| 14 | 点击"参与者" | 只显示参与的会话 | +| 15 | 点击"未处理" | 只显示未处理会话 | + +### Phase 3 — 侧边栏导航(§6.10) + +| # | 点击路径 | 验证内容 | +|---|---------|---------| +| 1 | 侧边栏→联系人 | 联系人列表加载 | +| 2 | 侧边栏→公司 | 公司列表加载 | +| 3 | 侧边栏→报告 | Overview 指标卡/图表 | +| 4 | 报告→会话 tab | 会话表格 | +| 5 | 报告→客服 tab | agent 数据 | +| 6 | 报告→标签 tab | label 数据 | +| 7 | 报告→收件箱 tab | inbox 数据 | +| 8 | 报告→团队 tab | team 数据 | +| 9 | 报告→CSAT tab | 评分分布 | +| 10 | 报告→SLA tab | SLA命中/违约 | +| 11 | 报告→Bot tab | bot 指标 | +| 12 | 侧边栏→活动 | Campaigns | +| 13 | 侧边栏→帮助中心 | Portal 列表 | +| 14 | 侧边栏→Captain | Assistant 列表 | + +### Phase 4 — Settings 全 22 页(§6.5) + +#### 4.1 账户设置 +| 字段 | 操作 | 验证 | +|------|------|------| +| 账户名称 | 修改文本框 → 点"更新设置" | toast 成功 | +| 站点语言 | 切换 combobox English↔中文 | 页面语言变化 | +| 自动解决对话 | toggle 切换 | 保存后刷新保持 | + +#### 4.2 客服代理 +| 操作 | 预期 | +|------|------| +| 点"添加代理" | 弹出新建表单 | +| 输入 name/email/role → 保存 | agent 出现在列表中 | +| 点编辑按钮 → 改 role → 保存 | toast 成功 | +| 点禁用 toggle | agent 变灰 | + +#### 4.3 团队 +| 操作 | 预期 | +|------|------| +| 点"新建团队" | 表单渲染 | +| 输入名称 → 添加成员 → 保存 | 团队出现在列表 | +| 点编辑 → 移除成员 → 保存 | 成员更新 | + +#### 4.4 收件箱列表 +| 操作 | 预期 | +|------|------| +| 验证 4 个 inbox 可见 | WebWidget / Fake / SMS / WhatsApp | +| 点"添加收件箱" | channel 选择面板 | +| 验证 Fake 卡可见且可点击 | 非禁用态 | + +#### 4.5 收件箱配置 +| 字段 | 操作 | +|------|------| +| 名称 | 修改 → 保存 | +| 欢迎语 | 修改 → 保存 | +| 允许域名 | 添加域名 → 保存 | +| Sender name | 修改 → 保存 | + +#### 4.6 收件箱子页 +| tab | 操作 | +|-----|------| +| 协作 | 添加/移除 agent | +| 预聊天表单 | 开关字段 → 必填 → 保存 | +| 后聊天表单 | 开关 → 保存 | +| 消息标签 | 添加标签 → 保存 | +| 业务时间 | 设置时间 → 保存 | + +#### 4.7 — 4.18 Settings 剩余页 +| 页面 | 核心操作 | +|------|---------| +| 标签 | 新建(name+color) → 编辑 → 删除 | +| 自定义属性 | 选类型 → 新建(name+type) → 编辑 → 删除 | +| 自动化 | 新建(条件+动作) → 编辑 → 克隆 → 删除 | +| 宏 | 新建(name+动作) → 编辑 → 删除 | +| 预设回复 | 新建(shortcut+content) → 编辑 → 删除 | +| Agent Bots | 新建(name+desc) → 绑定 inbox → 保存 | +| 集成方式 | Slack/Linear/Notion/Webhook 卡片可见 | +| 审计日志 | 列表加载,筛选可用 | +| 自定义角色 | 新建 → 勾选权限 → 保存 | +| SLA | 验证 Smoke SLA (FRT=5m NRT=10m RT=1h) | +| 会话工作流 | Auto-resolve toggle 切换 | +| 安全 | SAML SSO disabled 消息 | +| 客服分配 | assignment/capacity 表单渲染 | + +### Phase 5 — CRM(§6.3) + +| # | 操作 | 预期 | +|---|------|------| +| 1 | 侧边栏→联系人→列表加载 | 数据/空态 | +| 2 | 点搜索框 → 输入 email → 筛选 | 列表过滤 | +| 3 | 点"新建联系人" → 填 name/email/phone → 保存 | toast 成功 | +| 4 | 点击一个联系人 → 进入详情 | 详情渲染 | +| 5 | 点"编辑" → 改 name → 保存 | toast 更新 | +| 6 | 点"会话历史" tab → 看到关联会话 | 历史列表 | +| 7 | 点"备注" → 添加备注 → 保存 | 备注出现 | +| 8 | 侧边栏→公司→列表 | 加载 | +| 9 | 点"新建" → 填名称 → 保存 | toast 成功 | +| 10 | 点公司 → 详情编辑 → 保存 | 更新 | + +### Phase 6 — Widget SDK(§6.9) + +| # | 操作 | 预期 | +|---|------|------| +| 1 | 打开 `/widget?website_token=gochat-smoke-widget-token` | widget 加载 | +| 2 | 验证 home page | 欢迎语可见 | +| 3 | 打开 `/widget?.../messages` | 历史消息 | +| 4 | 输入消息 → 发送 | 消息出现在 window | +| 5 | 发送 "hello" → 等 5s | AgentBot static auto-reply | +| 6 | 发送 "tell me about ai" → 等 15s | LLM auto-reply (deepseek) | +| 7 | 验证 sender_type=AgentBot (psql) | 非 contact | + +### Phase 7 — Captain/AI(§6.8) + +| 页面 | 操作 | +|------|------| +| Assistants | 列表 → 新建 → 保存 | +| Responses/FAQs | CRUD → 搜索 | +| Documents | 新建 → 上传 | +| Scenarios | 新建/编辑/启停 | +| Custom Tools | CRUD → 参数 → 鉴权 | +| Playground | 输入 → 查看 AI 回复 | +| Copilot 配置 | Provider/Model/Feature 三区块 | + +### Phase 8 — Conversation API(14 操作) + +``` +□ POST /conversations/1/messages (outgoing) → 200 + msg_id +□ POST /conversations/1/messages (private_note) → 200 +□ GET /conversations/1 → 200 + messages[] +□ POST /conversations/1/toggle_priority → 200 +□ PATCH /conversations/1/priority → 200 +□ POST /conversations/1/toggle_status (resolved) → 200 +□ POST /conversations/1/toggle_status (open) → 200 +□ POST /conversations/1/toggle_status (snoozed) → 200 +□ POST /conversations/1/update_last_seen → 200 +□ POST /conversations/1/mute → 200 +□ POST /conversations/1/unmute → 200 +□ POST /conversations/1/labels → 200 +□ GET /conversations/1/attachments → 200 + payload[] +□ POST /toggle_typing_status (on) → 200 +□ POST /toggle_typing_status (off) → 200 +``` + +### Phase 9 — AgentBot 链路 + +``` +□ POST /agent_bots → 200 + id +□ GET /agent_bots → 200 + list +□ GET /agent_bots/:id → 200 + detail +□ PATCH /agent_bots/:id → 200 +□ POST /inboxes/1/set_agent_bot → 200 +□ GET /agent_bot_inboxes/?inbox_id=1 → 200 + binding +□ POST /captain/auto_reply_rules (static mode) → 201 +□ PUT /captain/auto_reply_rules/:id (activate) → 200 +□ Widget 发送 "hello" → 等 5s → msg.sender_type=AgentBot +``` + +### Phase 10 — 搜索 + 通知 + 用户菜单 + +| # | 操作 | 预期 | +|---|------|------| +| 1 | 点"搜索..." → 输入关键词 → 回车 | 搜索结果 | +| 2 | 点搜索结果 → 跳转会话 | 正常 | +| 3 | 点侧边栏头像 → 键盘快捷键 | 弹层 | +| 4 | 点"个人设置" → Profile | 信息正确 | +| 5 | 点通知铃铛 → 列表 | 通知加载 | +| 6 | 点"退出登录" | 回到 login | +| 7 | 点"登录" → 重新登录 | dashboard 恢复 | + +--- + +### 各 Phase 通用通过标准 + +``` +□ console 无 error(allowlist 除外: DEPRECATED/P4 级) +□ API 响应 2xx(cache_keys 多重调用不视为异常) +□ 无白屏 / error boundary / uncaught promise +□ CRUD 操作回写后刷新页面,状态仍保持 +□ toast/成功提示出现且文案正确 +```