清理: - 删除 34 份过时文档(gap reports/QA临时报告/验收报告/阶段性文档) - 删除 docs/.hermes/skills 第三方 skills 副本(16 文件) - 删除 skills-lock.json 目录归集: - 根目录仅保留 README.md 索引 - product/ — 产品与架构设计(PRD + ARCHITECTURE + P2设计文档 + AI/企业路线图) - tracking/ — Chatwoot parity 开发跟踪 - requirements/ — M01-M12 模块需求 - plans/ — 历史实现计划 - parity/ — 路由 parity 与前端契约 - qa/ — QA 报告与测试计划 - ops/ — 运维部署 命名规范: - 全小写 kebab-case,禁止全大写文件名 - product/tracking/ops 用 NN- 序号前缀 - requirements 用 MNN- 两位零填充模块号 - plans/qa 用 YYYY-MM-DD- 日期前缀 - requirements M1-M9 零填充为 M01-M09(修复字典序) 同步更新: - backend/cmd/route_parity/main.go 路径默认值 - backend/scripts/parity_frontend_smoke.sh 报告路径 - 所有 docs 内部交叉引用 - .gitignore 排除编译产物 (backend/gochat, backend/route_parity) - 新增迁移 000052/000053 - 前端 WS 相关修改
231 lines
10 KiB
Markdown
231 lines
10 KiB
Markdown
# Test Plan — CDP Strict Full-Page Functional Testing (Round 4)
|
|
|
|
**Date:** 2026-07-09
|
|
**Environment:** backend (:3000) + frontend Vite (:3036), CDP browser at :9222
|
|
**Login:** admin@gochat.local / changeme
|
|
**Prerequisite:** Round 2 reported all-pass but the WS 401 error still recurs
|
|
in backend logs. Round 3 plan was written but never executed (no round 3 QA
|
|
report exists). This round re-executes the full test suite with strict
|
|
observability rules and actually fixes any bugs found.
|
|
|
|
---
|
|
|
|
## Background
|
|
|
|
The user still observes WebSocket 401 errors:
|
|
|
|
```
|
|
{"level":"ERROR","caller":"ws/handler.go:62",
|
|
"msg":"ws: authentication failed: authentication required: provide 'token' (JWT) or 'pubsub_token' + 'user_id' params"}
|
|
HTTP GET /cable 401
|
|
```
|
|
|
|
Prior fixes applied (uncommitted, in working tree):
|
|
- `BaseActionCableConnector.js`: defaults `websocketHost` to
|
|
`window.location.origin`, appends `?access-token=` from cookie.
|
|
- `ws/auth.go`: `extractWSToken` now accepts both `token` and `access-token`
|
|
query params, removed Sec-WebSocket-Protocol path.
|
|
- `ws/handler.go`: added `actioncable-v1-json` subprotocol, welcome frame,
|
|
ActionCable-format ping, `CommandMessage` handling.
|
|
- `ws/protocol.go`: renamed confirm/reject types to match ActionCable
|
|
(`confirm_subscription`, `reject_subscription`), added `RoomChannel`,
|
|
reduced `PingInterval` to 5s.
|
|
- `ws/hub.go`: moved welcome frame to handler, added
|
|
`wrapActionCableMessage` for proper wire format.
|
|
- `ws/subscriber.go`: events now use `WSMessage` format wrapped in
|
|
ActionCable envelope.
|
|
|
|
These fixes need end-to-end verification. If the 401 still occurs, the fix
|
|
must be traced and corrected before page testing begins.
|
|
|
|
---
|
|
|
|
## Testing Rules (Mandatory — No Exceptions)
|
|
|
|
### Rule 1: Console warnings ARE errors
|
|
|
|
- `console.warn`, Vue warnings, i18n fallback warnings, deprecation notices —
|
|
ALL are recorded as findings.
|
|
- The only acceptable exceptions (pre-existing, documented):
|
|
- `onClose` prop deprecated (widget components)
|
|
- `WootInput` deprecated (4 occurrences)
|
|
- Lit dev mode / multiple versions
|
|
- Vue Router "Discarded invalid param(s)" (1 occurrence)
|
|
- Any NEW warning not in the above list is a bug.
|
|
- Console capture is set up via injected JS hooks BEFORE navigation, and read
|
|
AFTER the page settles. Buffers are reset before each page transition.
|
|
|
|
### Rule 2: Network infinite request loop detection
|
|
|
|
- After each page loads and settles, monitor network requests for 10 seconds.
|
|
- Flag any endpoint called more than 3 times in that window without user
|
|
interaction.
|
|
- Special attention to `/cable` reconnect loops, `/api/v1/.../poll` patterns,
|
|
and any endpoint returning 4xx/5xx being retried.
|
|
- A page that silently generates 50+ API calls/minute is a FAIL.
|
|
|
|
### Rule 3: Click-only navigation — NO URL input
|
|
|
|
- All page transitions via UI clicks: sidebar links, sub-menu links, tabs,
|
|
buttons, breadcrumbs, card clicks, avatar dropdown.
|
|
- The ONLY exception is the initial login page (`/app/login`).
|
|
- `agent-browser open <url>` and `window.location.href = '...'` are FORBIDDEN
|
|
for page navigation (login excepted).
|
|
- Settings sub-links that are collapsed in the sidebar are clicked via JS
|
|
`.click()` on the actual `<a>` element (this counts as a UI click, not URL
|
|
navigation).
|
|
- If a page is unreachable by any click, record it as a navigation-gap finding.
|
|
|
|
### Rule 4: Transition error capture
|
|
|
|
- Before navigating away from each page, capture the full console buffer.
|
|
- After arriving at the next page, capture again.
|
|
- Any error/warning that appeared during the transition itself is a finding.
|
|
- This catches: orphaned event listeners, stale store state, missing
|
|
beforeRouteLeave cleanup, transition animation errors.
|
|
|
|
### Rule 5: CRUD interaction where applicable
|
|
|
|
- Not just "page loads" — attempt at least one create/edit operation on pages
|
|
that support it.
|
|
- Verify the operation succeeds AND produces no new console errors.
|
|
- Verify no infinite refetch loop is triggered after the mutation.
|
|
|
|
---
|
|
|
|
## Pre-Test Setup
|
|
|
|
### Step 0a: Verify services running
|
|
- [ ] Backend on :3000 — `curl http://127.0.0.1:3000/health` → 200.
|
|
- [ ] Frontend Vite on :3036 — `curl http://127.0.0.1:3036/health` → 200.
|
|
- [ ] If either is down, start with `pnpm dev:backend` / `pnpm dev:frontend`.
|
|
|
|
### Step 0b: CDP browser connection
|
|
- [ ] Verify Chrome on :9222 is alive — `curl http://127.0.0.1:9222/json/version`.
|
|
- [ ] Connect via `agent-browser --cdp 9222`.
|
|
- [ ] Open a fresh tab for testing (avoid stale state).
|
|
|
|
### Step 0c: Console capture hooks
|
|
- [ ] Inject `console.error` and `console.warn` hooks via `agent-browser eval`.
|
|
- [ ] Hooks store messages in `window.__consoleErrors` and `window.__consoleWarnings`.
|
|
- [ ] These must be re-injected after every full page reload.
|
|
- [ ] Buffer reset function: `window.__resetConsole()`.
|
|
|
|
### Step 0d: Login (only allowed URL navigation)
|
|
- [ ] Navigate to `http://127.0.0.1:3036/app/login`.
|
|
- [ ] Fill email + password, click login button.
|
|
- [ ] Verify redirect to dashboard.
|
|
- [ ] Capture console — must be clean post-login.
|
|
- [ ] Verify cookie `cw_d_session_info` is set and contains `access-token`.
|
|
|
|
---
|
|
|
|
## Phase 1: WebSocket Authentication Deep Verification
|
|
|
|
This is the primary fix being tested. The 401 error must NOT recur.
|
|
|
|
- [ ] After login, wait 5s, check backend logs for `ws: connection established`.
|
|
Use `grep "ws:"` to filter worker-poll noise.
|
|
- [ ] Check backend logs: NO `ws: authentication failed` after login.
|
|
- [ ] Browser console: NO WebSocket errors, NO 401 on /cable.
|
|
- [ ] Network monitor 15s: /cable is NOT repeatedly hit (reconnect loop = FAIL).
|
|
- [ ] Verify ActionCable subscription is active (presence heartbeat every 20s
|
|
in backend logs: `ws: message command from user=1, data=...update_presence...`).
|
|
- [ ] Check online/availability indicator in sidebar or profile — must show
|
|
a status (online/busy/offline), not empty.
|
|
|
|
If the 401 still occurs: immediately switch to debug mode:
|
|
1. Check the actual WebSocket URL the browser is connecting to.
|
|
2. Check if `cw_d_session_info` cookie exists and has `access-token`.
|
|
3. Check if the Vite proxy forwards query params to the backend.
|
|
4. Trace the request through to `extractWSToken` — is `access-token` present?
|
|
5. Fix the root cause before continuing.
|
|
|
|
---
|
|
|
|
## Phase 2: Page-by-Page Strict Testing
|
|
|
|
**Navigation:** Start from dashboard. Click sidebar links, settings sub-menus
|
|
(collapsed links clicked via JS `.click()` on the `<a>` element), tabs,
|
|
buttons. Never type URLs.
|
|
|
|
**Per-page checklist (ALL items for EVERY page):**
|
|
1. Reset console capture buffers (`window.__resetConsole()`).
|
|
2. Click to navigate (record click path).
|
|
3. Wait for page to settle (content appears, network idle).
|
|
4. Capture console buffer — any error OR warning is a finding.
|
|
5. Monitor network for 10s — flag loops.
|
|
6. Verify core content renders (not blank, not error boundary).
|
|
7. Attempt CRUD interaction where applicable.
|
|
8. Check backend logs for errors during the page's lifetime.
|
|
9. Before leaving: capture console buffer again.
|
|
10. Click to next page.
|
|
11. Capture console buffer after transition — transition errors are findings.
|
|
|
|
| # | Page | Click Path | CRUD Test |
|
|
|---|------|-----------|-----------|
|
|
| 1 | Dashboard | (post-login) | Verify conversation list + online status |
|
|
| 2 | Conversation detail | Click conversation in list | Send a message, verify instant delivery |
|
|
| 3 | Contacts | Sidebar: 联系人 | Edit a contact, save, verify no refetch loop |
|
|
| 4 | Reports — Overview | Sidebar: 报告 → Overview | Date picker change, verify chart updates |
|
|
| 5 | Reports — Conversations | Reports tab: 会话 | Filter change |
|
|
| 6 | Reports — Agents | Reports tab: 客服 | Verify agent table |
|
|
| 7 | Reports — SLA | Reports tab: SLA | Verify SLA metrics |
|
|
| 8 | Reports — Labels | Reports tab | Verify load |
|
|
| 9 | Reports — Inboxes | Reports tab | Verify load |
|
|
| 10 | Reports — Teams | Reports tab | Verify load |
|
|
| 11 | Reports — CSAT | Reports tab | Verify load |
|
|
| 12 | Reports — Bot | Reports tab | Verify load |
|
|
| 13 | Activity | Sidebar: 活动 | Verify BUG-1 status (route missing?) |
|
|
| 14 | Help Center | Sidebar: 帮助中心 | Click portal, verify articles |
|
|
| 15 | Settings — General | Settings → 账户设置 | Update a field, save |
|
|
| 16 | Settings — Agents | Settings sub: 客服代理 | Verify list + search |
|
|
| 17 | Settings — Teams | Settings sub: 团队 | Open create team wizard |
|
|
| 18 | Settings — Inboxes | Settings sub: 收件箱 | Click inbox config, load ALL tabs |
|
|
| 19 | Settings — Labels | Settings sub: 标签 | Create a label, verify in list |
|
|
| 20 | Settings — Custom Attributes | Settings sub: 自定义属性 | Switch tabs (会话/联系人) |
|
|
| 21 | Settings — Automation | Settings sub: 自动化 | Verify list |
|
|
| 22 | Settings — Agent Bots | Settings sub: 机器人 | Verify BUG-2 (sidebar click nav) |
|
|
| 23 | Settings — Macros | Settings sub: 宏 | Verify list |
|
|
| 24 | Settings — Canned Responses | Settings sub: 预设回复 | Create a canned response |
|
|
| 25 | Settings — Integrations | Settings sub: 集成方式 | Click configure on one |
|
|
| 26 | Settings — Conv. Workflow | Settings sub: Conversation Workflows | Toggle switch |
|
|
| 27 | Settings — Assignment | Settings sub: Agent Assignment | Verify forms |
|
|
| 28 | Profile | Avatar dropdown → profile | Update profile, save |
|
|
|
|
---
|
|
|
|
## Phase 3: Real-Time WebSocket Feature Verification
|
|
|
|
- [ ] Open conversation, send message — verify instant appearance.
|
|
- [ ] Backend logs: `message.created` event dispatched.
|
|
- [ ] Presence indicator: correct status shown.
|
|
- [ ] Network: /cable stable, no 401s, no reconnect storm.
|
|
- [ ] Monitor 30s for any spontaneous /cable disconnect/reconnect.
|
|
|
|
---
|
|
|
|
## Phase 4: Collect and Report
|
|
|
|
- [ ] For each page: console errors/warnings, network issues, CRUD results,
|
|
transition errors.
|
|
- [ ] All backend errors (ws auth, 500s, panics) observed during testing.
|
|
- [ ] New bugs: reproduction steps (click path), root cause, affected files,
|
|
severity.
|
|
- [ ] Re-verify known issues (BUG-1, BUG-2, BUG-3).
|
|
- [ ] Write final QA report to `docs/qa/2026-07-09-qa-report-round4.md`.
|
|
- [ ] If the WS 401 error recurs, immediately trace root cause and fix before
|
|
continuing with page tests.
|
|
|
|
---
|
|
|
|
## Severity Definitions
|
|
|
|
| Severity | Definition |
|
|
|----------|------------|
|
|
| P0 Critical | Feature broken, blocks core workflow, infinite loop |
|
|
| P1 High | Core feature broken with workaround; repeated console errors |
|
|
| P2 Medium | Non-core feature broken, or warnings indicating real code issue |
|
|
| P3 Low | Minor cosmetic/edge-case, no functional impact |
|
|
| P4 Cosmetic | Pure noise (dev-mode, deprecation with no user impact) |
|