Chat Test Client

1:1 messaging: versioned state, read markers, inbox and requests, send, reply, accept, history, catch-up. One user per browser tab. Signed in as —
not connected
Config not fetched yet.
9:41offline

Live events

Replace the whole member state only when its version is at least the held version. Insert messages by id when absent, even from stale updates; render and gap-check by seq, never by version. Full rows apply their peer card with their state; unknown conversations fetch a full row. A reply without a version keeps held state and fetches a versioned copy. Every applied state gap-checks the open thread's visible horizon (1 for a pending receiver, otherwise lastSeq). Pause to hold events, or drop them to simulate lost events; foreground, reconnect and inbox open refresh lost state.

Applying events live.

Diagnostics

The missing-message control sends sample text in the open thread. A 1411 refusal offers to send that text without a quote under a new key. Retry same key preserves the original body and reply target, including after a timeout or temporary error.

No thread open.

Hold an HTTPS response

Fetch a list or the open conversation and hold its response without applying it. Read on another tab (AE5), or Accept here (AE10), then apply the held response: an older version must leave the state and peer card unchanged.

No HTTPS response held.

Raw command

Any method and payload over the connection, e.g. accept your own request (1403), send as the receiver of a pending request (1409), an unknown method or a bad payload (1401).

Log

Notes for local use

Serve this file over http (for example npx http-server test -p 8765) rather than opening it from disk, and open one tab per user (the login is kept per tab).

Gateway calls blocked by the browser: with NODE_ENV=development every origin is allowed; under any other NODE_ENV the page's origin must be listed in ALLOWED_ORIGINS in the gateway's process environment.

Connection fails with only "transport closed" and no close code: the chat server refuses browser connections whose origin it does not know. Set CHAT_CENTRIFUGO_ALLOWED_ORIGINS to this page's origin (scheme://host[:port], no path, no trailing slash, never *; space-separated for several), e.g. CHAT_CENTRIFUGO_ALLOWED_ORIGINS=http://localhost:8765, in .env for docker-compose.yml or .env.test for the test stack, then recreate the chat server container(s). Do not set CENTRIFUGO_CLIENT_ALLOWED_ORIGINS directly: the compose files set it from the CHAT_ key, empty when that is unset. The login itself needs nothing extra: the token travels inside the connect command and the server forwards it as the Authorization header.

Reads send only from a visible thread on a focused page, with one command in flight per conversation and the highest displayed seq queued. Pending reads retry after reconnect; a capped reply never causes a resend. The Requests dot turns on from applied unread-request state and clears only from the summary route, refreshed on open, foreground, reconnect and request changes (at most once a second). Ignore, Block and the archived requests list are not built yet.