Files
gochat/docs/TEST_PLAN_2026-07-08_cdp_full_page_testing.md
T
2026-07-09 13:59:31 +08:00

11 KiB

Test Plan — CDP Full-Page Functional Testing

Date: 2026-07-08 Environment: backend (:3000) + frontend Vite (:3036), CDP browser at :9222 Login: admin@gochat.local / changeme


Background

You reported a persistent WebSocket auth error in the backend logs:

{"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

Root Cause Analysis

The frontend ActionCable connector (BaseActionCableConnector.js) builds its WebSocket URL like this:

let websocketURL = websocketHost ? `${websocketHost}/cable` : undefined;
if (websocketURL && accessToken) {
  websocketURL += `?access-token=${encodeURIComponent(accessToken)}`;
}
this.consumer = createConsumer(websocketURL);

websocketHost comes from window.chatwootConfig.websocketURL, which is not set in frontend/index.html (the static config injected after Rails decoupling). So websocketHost is '' (empty string), which is falsy, so websocketURL stays undefined.

When createConsumer(undefined) is called, ActionCable falls back to its internal INTERNAL.default_mount_path = "/cable". This produces a relative WebSocket URL that the browser resolves against the frontend origin (ws://127.0.0.1:3036/cable), not the backend.

The Vite dev proxy does forward /cable to the backend with ws: true, so the upgrade request reaches the Go backend. However, because websocketURL was undefined, the ?access-token=... query param was never appended. The backend's extractWSToken() checks c.Query("token"), c.Query("access-token"), and the Authorization header — all empty — so it falls through to the pubsub_token path, which also fails because no pubsub_token or user_id query params are present either.

Result: Every WebSocket connection attempt to /cable returns HTTP 401.

Fix Direction

In BaseActionCableConnector.js, when websocketHost is empty, default to the current page origin so the URL is never undefined. This ensures:

  1. The ?access-token= query param is appended.
  2. The WebSocket URL resolves against the correct origin.
// If no explicit websocketURL configured, use same origin as the page
const origin = websocketHost || window.location.origin;
let websocketURL = `${origin}/cable`;
if (accessToken) {
  websocketURL += `?access-token=${encodeURIComponent(accessToken)}`;
}

Testing Principles (Must Follow)

These rules apply to every page and every transition throughout the entire test run. They are not optional checks — they define how navigation and observation must be performed.

Rule 1: Console is a first-class failure signal

  • Warnings count as errors. console.warn, Vue warnings, deprecation notices, i18n fallback warnings — all are recorded as issues, not ignored.
  • The only acceptable console state is completely clean (zero errors, zero warnings) unless the issue is already documented as a known pre-existing bug.
  • Before navigating away from any page, capture the full console log. Any new warning or error that appeared during the page's lifetime is a finding.
  • Use agent-browser eval or CDP Log.enable + Runtime.consoleAPICalled to capture console output programmatically. Do not rely on visual inspection.

Rule 2: Watch for infinite network request loops

  • Some pages have polling/retry logic that can enter infinite refresh loops (repeatedly calling the same API endpoint every few seconds, or hammering a failing endpoint with exponential retry storms).
  • After each page loads and settles, monitor network activity for 5-10 seconds. If the same endpoint is being called repeatedly without user interaction, that is a bug — record the endpoint, frequency, and response status.
  • Use agent-browser network requests to inspect what fired, and watch the backend logs for repeated request patterns.
  • A page that "loads fine" but silently generates 50+ API calls per minute is a failing page.

Rule 3: Navigate by clicking, never by URL input

  • All page transitions must be performed via UI clicks — sidebar links, buttons, breadcrumbs, tabs, card clicks. Never type a URL into the address bar or use agent-browser open <url> to jump directly to a page (except for the initial login page).
  • Direct URL navigation bypasses the Vue router's navigation guards, beforeEnter hooks, store preloading, and transition lifecycle. Bugs that only surface during real navigation (missing data preload, stale state, broken transition animations, orphaned event listeners) will be missed.
  • The test flow must mirror a real user's click path: login → dashboard → sidebar → each settings page → sub-tabs within settings → back navigation.
  • If a page is only reachable by URL (no UI link exists), note it as a navigation gap finding, then navigate to it directly as an exception with explicit annotation.

Test Plan

Phase 1: Fix the WebSocket auth error

  • Patch BaseActionCableConnector.js to default websocketHost to window.location.origin when empty.
  • Verify the access-token cookie read works (cookie name cw_d_session_info).
  • Confirm the backend extractWSToken() accepts access-token query param.

Phase 2: Start dev services

  • Start pnpm dev:backend (air hot-reload, port 3000).
  • Start pnpm dev:frontend (Vite dev server, port 3036).
  • Health check: curl http://127.0.0.1:3000/health.

Phase 3: CDP browser login

  • Connect agent-browser to CDP at :9222.
  • Navigate to http://127.0.0.1:3036/app/login (only direct URL allowed).
  • Login with admin@gochat.local / changeme.
  • Verify redirect to dashboard.
  • Capture console state — must be clean post-login.

Phase 4: WebSocket connection verification (the primary fix)

  • After login, check backend logs for ws: connection established.
  • Check no more ws: authentication failed errors in backend.
  • Check browser console: no 401 on /cable, no WebSocket connection errors.
  • Check no infinite /cable reconnect loop (ActionCable retries should stop after successful connection, not loop forever).
  • Verify the NetworkNotification component shows "online" status.
  • Monitor network for 10s — confirm /cable is not being repeatedly hit.

Phase 5: Full page-by-page functional testing (click-based navigation)

Navigation method: Start from dashboard. Use sidebar links, settings sub-menus, tabs, and buttons to reach every page. Never type URLs.

Per-page checklist (applies to every page below):

  1. Click to navigate to the page (record the click path).
  2. Wait for page to settle (networkidle or specific content appears).
  3. Capture full console log — any error OR warning is a finding.
  4. Monitor network for 5-10s — flag any infinite/repeated request loops.
  5. Verify core content renders (not a blank page, not an error boundary).
  6. Attempt at least one CRUD interaction where applicable.
  7. Capture backend logs for any errors during the page's lifetime.
  8. Navigate away via sidebar/back — verify no errors on transition.
# Page Click Path (from dashboard) Key Checks
1 Dashboard (already here after login) Conversation list loads, sidebar renders, online status
2 Conversation detail Click a conversation in list Message history, reply box, send a message, real-time delivery
3 Contacts Sidebar: 联系人 Contact list, edit contact, save, search
4 Reports — Overview Sidebar: 报告 → Overview Stats cards, charts render, date picker
5 Reports — Conversations Reports sub-tab: 会话 Table loads, filters work
6 Reports — Agents Reports sub-tab: 客服 Agent table loads
7 Reports — SLA Reports sub-tab: SLA SLA metrics render
8 Activity Sidebar: 活动 Known issue BUG-1: route missing — verify if fixed or still broken
9 Help Center Sidebar: 帮助中心 Portal list, articles, tabs
10 Settings — General Sidebar: 设置 → 账户设置 Form fields, update settings
11 Settings — Agents Settings sub-menu: 客服代理 Agent list, search
12 Settings — Teams Settings sub-menu: 团队 Team list, create team wizard
13 Settings — Inboxes Settings sub-menu: 收件箱 Inbox list, click config → all tabs load
14 Settings — Labels Settings sub-menu: 标签 Label list, create label
15 Settings — Custom Attributes Settings sub-menu: 自定义属性 List loads, tabs (会话/联系人)
16 Settings — Automation Settings sub-menu: 自动化 List loads
17 Settings — Agent Bots Settings sub-menu: 机器人 Known BUG-2: sidebar click may not navigate — verify
18 Settings — Macros Settings sub-menu: 宏 List loads
19 Settings — Canned Responses Settings sub-menu: 预设回复 List, create canned response
20 Settings — Integrations Settings sub-menu: 集成方式 Integration cards, click configure
21 Settings — Conversation Workflow Settings sub-menu: Conversation Workflows Toggle loads
22 Settings — Assignment Policy Settings sub-menu: Agent Assignment Policy forms, add buttons
23 Profile Click avatar / profile link Profile form, update, password change

Phase 6: Real-time WebSocket feature verification

These tests verify the WebSocket fix is actually working end-to-end:

  • Open a conversation, send a message — verify it appears instantly.
  • Check backend logs for ws: connection established (user=X, account=Y).
  • Verify presence/availability indicator shows correct status.
  • Monitor network: confirm /cable WebSocket is stable (connected, not reconnect-looping), and no 401s on /cable after the initial connection.
  • If possible, open a second browser session and verify real-time message delivery (message sent from session A appears in session B without refresh).

Phase 7: Collect and report

  • For each page: compile console errors/warnings, network issues, CRUD results.
  • Compile all backend errors (ws auth, 500s, panics) observed during testing.
  • Document any new bugs found with: reproduction steps (click path), root cause analysis, affected files, severity.
  • Re-verify known issues (BUG-1, BUG-2, BUG-3) — note if fixed or persisting.
  • Write final QA report to docs/QA_REPORT_2026-07-08_cdp_round2.md.

Known Issues from Prior QA (docs/QA_REPORT_2026-07-08_full_page_testing.md)

  1. BUG-1 (P2): Activity page route missing — sidebar link dead.
  2. BUG-2 (P3): Bots sidebar link not navigating.
  3. BUG-3 (P4): intlify empty key warnings.

These will be re-verified via click navigation (not URL). If still present, they will be documented with their click-path reproduction. The WebSocket auth fix is the primary focus of this round.


Issue Severity Definitions

Severity Definition
P0 Critical Feature completely broken, blocks core workflow, or infinite loop causing resource exhaustion
P1 High Core feature broken but workaround exists; or repeated console errors degrading UX
P2 Medium Non-core feature broken, or warnings that indicate a real code issue
P3 Low Minor cosmetic or edge-case issue, no functional impact
P4 Cosmetic Pure noise (dev-mode warnings, deprecation notices with no user impact)