Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

14 — QA Checklist (WS / Realtime Module)

Test cases for the realtime layer. Server side (Jest) + client side (widget/unit). Shared baseline: 00-shared/10. Every case lists pass criteria. Source anchors included; a "source" gap means the behavior is defined by us, not the server.


Q1 — Reconnect storms (client + server)

  • Scenario: 100 clients behind the same NAT lose connectivity simultaneously and all retry in lockstep.
  • Pass: reconnects spread over time (client backoff jitter, 13 §3, 15 §4); server accepts them without CPU/connection spikes; no tenant event lost after each reconnect.
  • Server evidence: handleConnection logs connect (ws.gateway.ts:51-53); verify log rate stays linear, not bursty.
  • Client: no two consecutive retries with identical delay; cap 30 s (13).

Q2 — Auth on reconnect

  • Scenario: session token expires mid-connection; socket drops; client reconnects with the stale token.
  • Pass: server closes the socket (ws.gateway.ts:42-44,54-56); client enters AuthError (never infinite loop), refreshes token via REST, reopens socket, resumes in tenant room (ws.gateway.ts:50).
  • Negative: refresh fails → sign-out path with snackbar (06 §1.2), no retry loop.
  • Regression: missing token (neither auth nor query) → clean disconnect (ws.gateway.ts:37-40).

Q3 — Event fan-out leaks (tenant isolation)

  • Scenario: tenant A emits payment.completed; tenant B is connected concurrently.
  • Pass: only sockets in tenant:{A} receive it (ws-bridge.service.ts:16-22, ws.gateway.ts:76-78); B receives nothing.
  • Multi-socket: same user with 2 tabs in A receives exactly 2 copies (client dedups).
  • This is the highest-severity test on the list — isolation is the module's core security boundary (04 §2).

Q4 — Heartbeat loss (silent half-open connection)

  • Scenario: device sleeps; TCP stays half-open; no data flows.
  • Pass: server pings time out (socket.io heartbeat defaults — **untuned in source, G6 12); server cleans the dead socket (visible in disconnect log, ws.gateway.ts:59-61); client detects loss and enters Reconnecting, not Offline forever.
  • Tune check: pingInterval/pingTimeout explicitly set once proxy timeouts are known (pending decision, G6).

Q5 — Event fan-out leaks (client side)

  • Scenario: user navigates between 10 screens in a session.
  • Pass: no duplicate Bloc subscriptions after navigation; bloc close() cancels stream subs (13 §2); memory flat over 15 min of navigation; single toast per event (dedup window, 10 §3).

Q6 — Subscribe / unsubscribe semantics

  • Scenario: user subscribes to class:10-A, then unsubscribes, then resubscribes.
  • Pass: broadcastToRoom reaches exactly the subscribed sockets (ws.gateway.ts:80-82); unsubscribe stops delivery (ws.gateway.ts:70-74); double-subscribe is idempotent; non-string payload ignored (ws.gateway.ts:65,71).
  • Security negative: subscribe to arbitrary room tenant:other or __adminno server rejection today (G2); document as known-risk until allow-list lands.

Q7 — Reconnect resubscription

  • Scenario: connected with extra rooms → network flap → reconnect.
  • Pass: client re-subscribes all extra rooms after handshake (rooms die with socket, ws.gateway.ts:63-68; client replay 13 §4); tenant room auto-restored (ws.gateway.ts:50); one reconcile refetch per visible live screen (06 §3.1).

Q8 — Malformed payloads & unknown events

  • Scenario: server sends envelope with wrong shape, or an unknown eventType.
  • Pass: client ignores + logs eventType only (06 §6); app never crashes; unknown eventType routed to no bloc; payload size cap (e.g. 1 MB) prevents memory blowup.

Q9 — Payload integrity

  • Scenario: event carries entityId; REST fetch of that entity.
  • Pass: live row update matches REST data after reconcile; insert/refetch-bound logic per 06 §3.1; aggregate tiles recompute without refetch.

Q10 — Scale (planned, per plan)

  • Scenario: 10k concurrent connections (plan flags this as a risk — docs/IMPLEMENTATION_PLAN.md:842).
  • Pass (when executed): single-instance target met OR Redis pub/sub adapter added (currently absent — G5 12); broadcast latency p95 < 1 s; reconnect storm Q1 holds.

Q11 — Broadcast correctness after redeploy

  • Scenario: server restarts with new bridge; clients reconnect.
  • Pass: bridge re-activates on onModuleInit (ws-bridge.service.ts:15-23); no double registration (EventBus onAny not stacked — verify listener count after N restarts).

Q12 — Logging hygiene

  • Pass: no token, payload content, or PII in gateway/bridge logs; only userId/tenantId
    • eventType (ws.gateway.ts:51-53,59-61; 10 §8). Grep CI check.

Test surface summary

LayerToolingCases
Server (gateway)Jest + @nestjs/websockets mockhandshake ok/fail, room join, subscribe validation, broadcast target
Server (bridge)JestonAny wiring, envelope shape, single registration
Server (e2e)socket.io-client against test serverQ1, Q3, Q6, Q11 (requires Mongo+Redis, npm run test:e2e)
Clientwidget tests + fake clientQ2, Q5, Q7, Q8