Skip to content

test(ws-client): cover relay message parsing, NIP-42 auth flow, and connection state machine - #2609

Open
SeanGearin wants to merge 1 commit into
block:mainfrom
SeanGearin:test-ws-client-coverage
Open

test(ws-client): cover relay message parsing, NIP-42 auth flow, and connection state machine#2609
SeanGearin wants to merge 1 commit into
block:mainfrom
SeanGearin:test-ws-client-coverage

Conversation

@SeanGearin

@SeanGearin SeanGearin commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Problem

crates/buzz-ws-client is the NIP-42 WebSocket client that buzz-cli and
buzz-test-client use to talk to relays, but it currently has almost no test
coverage: the only tests are three const assertions on timeout floors. The
crate's actual behavior — NIP-01 frame parsing, NIP-42 AUTH event
construction, challenge handling, OK-response matching, out-of-order message
buffering, ping/pong keepalive, and close/timeout error paths — is entirely
unexercised, so regressions in any of it would only surface as live relay
failures.

Fix

Pure test addition — no production code changes, no new dependencies (dev or
otherwise).

src/message.rs (+217): unit tests for parse_relay_message and
build_auth_event:

  • every frame type parses (EVENT with a real signed event, OK, EOSE, CLOSED,
    NOTICE, AUTH), including the NIP-01 defaulting rules (short OK defaults to
    rejected/empty message, CLOSED without reason defaults to empty);
  • every rejection path (missing fields, non-array JSON, non-string type tag,
    unknown message type, malformed event payload) maps to the right
    WsClientError variant;
  • AUTH events are signed Kind::Authentication events carrying the NIP-42
    challenge/relay tags, the optional NIP-OA auth tag is injected when
    provided, and invalid relay URLs are rejected.

src/connection.rs (+323): integration-style tests for NostrWsConnection
and publish_event against an in-process scripted relay (bind
127.0.0.1:0 + tokio_tungstenite::accept_async — same idiom as the
existing test_ws_pair helper in buzz-acp/src/relay.rs; no network, no
mock frameworks):

  • full authenticate handshake: client signs the relay's challenge and the
    sent AUTH event verifies (kind/pubkey/signature/challenge tag);
  • relay-rejected auth surfaces AuthFailed with the relay's reason;
  • messages arriving before the AUTH challenge are buffered and delivered
    in order by next_event afterwards;
  • oversized (>1024 byte) challenges are rejected;
  • send_event matches the OK for its own event id, buffering interleaved
    EOSE/foreign-OK frames for later delivery;
  • pings received mid-wait are answered with payload-matching pongs without
    disrupting the OK wait;
  • an AUTH challenge received while waiting for a publish OK is stored and
    reused by a later authenticate() call (no second challenge needed);
  • silent relay → Timeout; server-initiated close → ConnectionClosed;
    invalid URL → Url error;
  • publish_event one-shot helper: connect → auth → publish → OK end to end.

All server-side reads are bounded by 5s timeouts so failures are fast, and
ephemeral ports keep the tests parallel-safe under nextest.

Test evidence

Against the pinned toolchain (Rust 1.95.0, per rust-toolchain.toml):

cargo clippy -p buzz-ws-client --all-targets -- -D warnings   # clean
cargo nextest run -p buzz-ws-client                           # 34 tests run: 34 passed, 0 skipped

Links

  • Crate: crates/buzz-ws-client (used by crates/buzz-cli, crates/buzz-test-client)
  • Test-server idiom precedent: crates/buzz-acp/src/relay.rs tests

@SeanGearin
SeanGearin requested a review from a team as a code owner July 23, 2026 20:13
…onnection state machine

Signed-off-by: Sean Gearin <sgearin@gmail.com>
@SeanGearin
SeanGearin force-pushed the test-ws-client-coverage branch from a23e93d to f8410b8 Compare July 23, 2026 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant