Skip to content

Accurate waiting room participation counts tests#305

Draft
mikewillems wants to merge 22 commits intostagingfrom
mw/debt/waiting-room-counts-testing
Draft

Accurate waiting room participation counts tests#305
mikewillems wants to merge 22 commits intostagingfrom
mw/debt/waiting-room-counts-testing

Conversation

@mikewillems
Copy link
Collaborator

What is in this PR?

This PR adds comprehensive test coverage and validation for the participant presence-tracking refactoring completed in PRs #281 and #282. It ensures the heartbeat mechanism, breakout room state transitions, and stale participant cleanup work correctly in the context of the actual UI state changes introduced by those PRs.

  • 10 presenceRoomIdForState unit tests
  • 8 Firestore contract tests
  • 8 UpdatePresenceStatus tests
  • 6 VoteToKick tests (4 original + 2 new)
  • 8 CleanupStaleParticipants tests

Changes in the codebase

1. Unit Tests: Presence Room ID Mapping (10 tests)

  • File: meeting_ui_state.dart + live_meeting_provider_presence_test.dart
  • Purpose: Tests the presenceRoomIdForState() function that maps UI state → room ID for heartbeat updates
  • Checks:
    • Waiting room always maps to 'waiting-room'
    • Breakout state returns the active breakout room ID
    • Main meeting, livestream, prescreen, and left states return null
    • Defensive case: breakout state without a room ID assigned

2. Firestore Contract Tests (8 tests)

  • File: presence_firestore_contract_test.dart
  • Purpose: Simulates all updateMeetingPresence writes and verifies document shape
  • Checks:
    • Join writes: isPresent: true, mostRecentPresentTime
    • Breakout room join: currentBreakoutRoomId set correctly
    • Waiting room presence: currentBreakoutRoomId: 'waiting-room'
    • Leave writes: isPresent: false
    • Tab close (onBeforeUnload): Sets isPresent: false with lastUpdatedTime
    • collectionGroup query compatibility for presence filtering
    • Room-scoped queries for participant lists

3. Cloud Function Tests: UpdatePresenceStatus (8 tests)

  • File: update_presence_status_test.dart
  • Purpose: Tests the Firestore function that processes heartbeat updates
  • Checks:
    • Marks participant online/offline based on heartbeat timing
    • Clears currentBreakoutRoomId when marking offline (null, not empty string)
    • Preserves room ID when participant is fresh
    • Uses lastUpdatedTime for staleness check

4. Cloud Function Tests: VoteToKick (6 tests, 4 new)

  • File: vote_to_kick_test.dart
  • Purpose: Tests kick voting that depends on presence data
  • Checks (new tests):
    • Kick threshold scales with number of present participants in room
    • Participants in other rooms don't affect threshold (room-scoped queries)

5. Cloud Function Tests: CleanupStaleParticipants (8 tests, from #282)

  • File: cleanup_stale_participants_test.dart
  • Purpose: Tests the background cleanup that removes stale presence records
  • Checks:
    • Marks stale participants offline
    • Preserves fresh participants
    • Leaves already-offline participants untouched
    • Preserves currentBreakoutRoomId during cleanup
    • Handles boundary conditions (exactly 60s stale)

Changes outside the codebase

None

Testing this PR

Run locally:

# Client tests
flutter test client/test/lib/features/events/features/live_meeting/data/providers/

# Firebase functions tests (requires Firestore emulator)
FIRESTORE_EMULATOR_HOST=127.0.0.1:8081 \
FIREBASE_AUTH_EMULATOR_HOST=127.0.0.1:9099 \
FIREBASE_DATABASE_EMULATOR_HOST=127.0.0.1:9000 \
GCLOUD_PROJECT=dev \
dart test firebase/functions/test/events/live_meetings/

Additional information

Architecture alignment

  • _presenceRoomId getter now delegates to presenceRoomIdForState() to prevent logic drift
  • Heartbeat timer writes presence every 5 seconds with _presenceRoomId value
  • getBreakoutRoomFuture() sets _inTransitionToBreakoutRoomId, heartbeat picks it up
  • leaveBreakoutRoom() clears transition state and notifies presence
  • dispose() and onBeforeUnload mark participant offline

Test coverage

  • 40 tests across unit, contract, and integration test levels
  • All updateMeetingPresence call sites verified
  • All presenceRoomIdForState state transitions covered
  • Server-side query shapes validated
  • Breakout room state machine verified

…ean online indicator. Fix log messages and null checks for breakout room transition variable. Replaced the generic warning in _presenceRoomId with a descriptive message explaining the uncommon null state. Change isNullOrEmpty check to a strict null check.
…TransitionToBreakoutRoomId on successful Agora connection. Separate caching logic into _cachedJoinInfoRoomId. Add a timer that logs a warning every 5 seconds if a breakout room transition has not completed, indicating a possible connection issue.
…oes not confirm a breakout room connection within 10 seconds, cancel the transition, return the user to the main meeting, and display an error message.
firebase-tools now requires Java 21+, but the workflow relied on the
runner's default JDK (Java 17). Add actions/setup-java@v4 with Temurin
21 before the emulator steps to fix the version mismatch.
@github-actions
Copy link

github-actions bot commented Feb 18, 2026

Visit the preview URL for this PR (updated for commit f17bf1b):

https://gen-hls-bkc-7627--pr305-mw-debt-waiting-room-q8o20ry8.web.app

(expires Fri, 06 Mar 2026 02:11:19 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: eed668cca81618d491d024574a8f8a6003deaa8d

@mikewillems mikewillems marked this pull request as draft February 19, 2026 10:22
…unts-testing

# Conflicts:
#	client/lib/features/events/features/live_meeting/data/providers/live_meeting_provider.dart
#	firebase/functions/lib/events/live_meetings/update_live_stream_participant_count.dart
#	firebase/functions/test/events/live_meetings/update_live_stream_participant_count_test.dart
#	firebase/functions/test/events/live_meetings/vote_to_kick_test.dart
@mikewillems mikewillems marked this pull request as ready for review February 20, 2026 02:46
@katherineqian katherineqian marked this pull request as draft March 5, 2026 21:01
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