Skip to content

test(client): happy-path tests for voice mutators (#414)#464

Merged
intendednull merged 1 commit into
claude/friendly-maxwell-Oggvwfrom
auto-fix/issue-414-voice-mutation-tests
Apr 28, 2026
Merged

test(client): happy-path tests for voice mutators (#414)#464
intendednull merged 1 commit into
claude/friendly-maxwell-Oggvwfrom
auto-fix/issue-414-voice-mutation-tests

Conversation

@intendednull
Copy link
Copy Markdown
Owner

what + why

Voice mutation API in crates/client/src/mutations.rs had zero test coverage at any tier. New file crates/client/src/tests/voice.rs adds one happy-path test per mutator. Tier 2 (client) per CLAUDE.md — lowest tier covering behaviour, no DOM needed.

Six mutators, six tests:

  • join_voice_sets_active_channel_and_inserts_selfactive_voice_channel() flips to the joined id, voice_participants() contains the local peer.
  • leave_voice_clears_active_channel_and_removes_self — after join+leave, active_voice_channel() is None, local peer no longer in participants.
  • toggle_mute_flips_state_and_returns_new_value — first call returns true and is_voice_muted() is true; second call returns false and round-trips.
  • toggle_deafen_flips_state_and_returns_new_value — same shape as toggle_mute against is_voice_deafened().
  • voice_peer_joined_inserts_peer_and_emits_event — synthetic peer id; participants set updated; ClientEvent::VoiceJoined surfaces on the broker.
  • voice_peer_left_removes_peer_and_emits_event — seed via voice_peer_joined, drain its event, then call voice_peer_left; participants set updated; ClientEvent::VoiceLeft surfaces.

verification

  • cargo test -p willow-client tests_voice — 6 passed.
  • cargo test -p willow-client — 293 passed (was 287, +6).
  • cargo fmt --check — clean.
  • cargo clippy --workspace --all-targets -- -D warnings — zero warnings.
  • cargo test --workspace — all green.
  • cargo check --target wasm32-unknown-unknown -p willow-client — clean.

(just not available in sandbox — used raw cargo per fallback.)

tradeoffs

  • voice_peer_joined / voice_peer_left arrive in production via the gossip listener unpacking WireMessage::VoiceJoin / VoiceLeave. Driving them through a fake wire message would re-test serialisation; the mutators themselves are best exercised directly with a synthetic peer id. Mirrors how multi_peer_sync::typing_indicator_updates_peer_state calls record_typing directly instead of synthesising a WireMessage::TypingIndicator.
  • join_voice / leave_voice call broadcast_on_topic, which no-ops if no topic is subscribed. The test_client() harness has no network → no topic → broadcast drops silently, but the voice StateActor mutation still runs and that's what the UI binds to. Wire-delivery between peers is exercised in the existing listener / multi-peer tests, not duplicated here.
  • Strictly tests-only — no source changes outside the mod tests_voice; registration in lib.rs.

Refs #414


Generated by Claude Code

Voice mutation API in crates/client/src/mutations.rs had zero test
coverage at any tier. Added crates/client/src/tests/voice.rs with one
happy-path test per mutator using the test_client() harness — tier 2
per CLAUDE.md (lowest tier covering behaviour, no DOM needed).

Coverage:
- join_voice: active channel set, local peer in participants
- leave_voice: active channel cleared, local peer removed
- toggle_mute: returns new value, is_voice_muted reflects, round-trip
- toggle_deafen: same shape as toggle_mute
- voice_peer_joined: peer inserted into participants, ClientEvent::VoiceJoined fired
- voice_peer_left: peer removed, ClientEvent::VoiceLeft fired

Tradeoffs:
- voice_peer_joined / voice_peer_left arrive in production via the
  gossip listener unpacking WireMessage::VoiceJoin / VoiceLeave.
  Driving them end-to-end through a fake wire message would re-test
  serialisation; the mutators themselves are best exercised directly
  with a synthetic peer id (mirrors what record_typing does in
  multi_peer_sync.rs).
- join_voice / leave_voice's broadcast_on_topic call no-ops without a
  subscribed topic, so the test_client harness suffices — no MemHub
  needed. Wire delivery between peers is exercised in the listener
  tests already.

Refs #414
@intendednull intendednull merged commit f384f78 into claude/friendly-maxwell-Oggvw Apr 28, 2026
intendednull added a commit that referenced this pull request Apr 28, 2026
Adds five tests in crates/client/src/tests/governance.rs covering
the mutators previously only Playwright-covered (or with zero
coverage anywhere):

  * propose_grant_admin     -> Propose { GrantAdmin }
  * propose_revoke_admin    -> Propose { RevokeAdmin }
  * propose_kick_member     -> Propose { KickMember }
  * propose_set_threshold   -> Propose { SetVoteThreshold }
  * delete_role             -> DeleteRole

Each test drives the mutator against a `test_client()` fixture
(genesis author = owner = automatic admin) and inspects the
managed DAG to assert the expected EventKind variant and payload.
Downstream materialisation (vote tally, role removal) is tier-1
state-machine territory and stays out of scope, mirroring the
convention from voice.rs (#464).

Refs #416

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants