test: increase app/websockets module test coverage to 100%
Merge Request
Overview
Increase test coverage for all files in app/websockets/ from partial coverage (60-85%) to 100% with real, meaningful tests. No source code changes — only test files modified.
What does this MR do and why?
Two files in app/websockets/ had significant coverage gaps:
-
websocket_manager.pyat 60% — the entirewebsocket_endpoint()function (lines 36-82) was untested -
socketio_queue_manager.pyat 85% — event handlers, room-specific branches, and default parameter paths were untested
This MR adds targeted tests to cover every branch, edge case, and error path in both files, bringing the full module to 221/221 statements covered.
Changes Made
-
Added:
tests/test_websockets/test_consultation_queue_ws_manager.py— new file, +353 lines -
Modified:
tests/test_websockets/test_socketio_queue_manager.py— +211 / -84 lines -
Modified:
tests/test_websockets/test_websocket_manager.py— +172 / -80 lines - No source code changes
- No other files modified
Technical Details
test_consultation_queue_ws_manager.py (new):
-
connect/disconnect— accepts and stores, multiple clients, no-op when not connected -
send_personal_message— success, WebSocketDisconnect removes client -
broadcast— sends to all, cleans up disconnected, empty connections -
get_queue_data— full record, no patient, patient no user, patient user_name None, no doctor, doctor no user, doctor user_name None, doctor specialization None, no joined_at, empty results -
broadcast_queue_update— calls get_queue_data and broadcast
test_socketio_queue_manager.py:
-
connect/disconnecthandler bodies -
leave_queue_roomhandler with explicit and default room -
request_queue_updatehandler with explicit and default room -
get_queue_datawithqueue_publicandqueue_doctorsroom branches -
get_queue_dataedge cases — no patient, no doctor, null timestamps, doctor without user, null user names -
broadcast_queue_updatewithrooms=Nonedefault path -
notify_queue_changewithrooms=Nonedefault path
test_websocket_manager.py:
-
websocket_endpointroom joining —join:analytics,join:queue, genericjoinwith custom room, default room - Duplicate join prevention, multi-room sessions
- Disconnect cleanup from all rooms, immediate disconnect
-
ConnectionManageredge cases — disconnect no-op, broadcast to unknown room -
emit_queue_status_updatedefaultpatient_info=None
Type of Change
-
🧪 Test update
Related Issues / References
- Closes #68 (closed)
Screenshots or Screen Recordings
N/A — test-only changes, no API modifications.
How to Validate Locally
-
Run the websocket test suite with coverage:
uv run pytest tests/test_websockets/ --cov=app/websockets --cov-report=term-missing -v -
Verify all tests pass
-
Verify output shows 100% coverage for all 4 files (0 missing lines)
-
Previous behaviour: 46 lines uncovered across
websocket_manager.py(34 lines) andsocketio_queue_manager.py(12 lines) - Changes made: Added tests targeting all uncovered branches and paths
- New behaviour: 0 lines uncovered — 221/221 statements covered
Testing Done
-
Unit tests added/updated -
API endpoint tests passing
Test Cases Covered:
| Scenario | Expected Result | Status |
|---|---|---|
websocket_endpoint room joining (analytics, queue, generic, default) |
WebSocket added to correct room | |
websocket_endpoint duplicate join & multi-room |
No duplicates, all rooms tracked | |
websocket_endpoint disconnect & immediate disconnect |
Cleanup from all rooms, no errors | |
ConnectionManager edge cases (disconnect no-op, broadcast unknown room) |
No errors, graceful handling | |
emit_queue_status_update default patient_info |
patient_info is None | |
| SocketIO handlers (connect, disconnect, leave_queue_room, request_queue_update) | Correct room operations and emit calls | |
get_queue_data room branches (public, doctors, coordinators) |
Correct status filters and fields | |
broadcast_queue_update & notify_queue_change with rooms=None |
Defaults to all 3 rooms | |
ConsultationQueueWebSocketManager connect/disconnect/broadcast |
Correct client management | |
get_queue_data null patient/doctor/timestamp edge cases |
Fallback values (Unknown, Unassigned, N/A) |
Test Commands Run:
uv run pytest tests/test_websockets/ --cov=app/websockets --cov-report=term-missing -v
# Coverage: 221/221 statements, 100%
Code Quality Checklist
Code Standards
-
Code follows project conventions (naming, structure, formatting) -
No debug statements or commented-out code left (unless necessary and intended) -
No unused imports, variables, or functions -
No duplicate code (DRY principle followed) -
Type hints are properly defined (no Anyunless justified and no mypy type check errors) -
Ruff checks pass: ruff check . ruff format . --check
Python & FastAPI Best Practices
N/A — no source code changes, test-only MR.
API Design
N/A — no API changes.
Database & Migrations
N/A — no database or schema changes.
Security
-
No sensitive data logged (passwords, tokens, PII) -
SQL injection prevention verified (ORM used)
Error Handling
N/A — no source code changes.
Documentation
N/A — no setup, env, or API changes.
Known Limitations / Technical Debt
None introduced. The datetime.utcnow() deprecation warnings in websocket_manager.py are pre-existing and out of scope for this MR.
Additional Notes
- All tests use mocks — no database or network dependencies required
-
websocket_endpointtests use aclean_managerfixture to save/restore the global singleton state between tests - SocketIO handler tests access registered handlers via
sio.handlers["/"]to test the actual registered functions
MR Acceptance Checklist
Quality & Correctness
-
Code works as intended and solves the stated problem -
No bugs introduced (existing functionality not broken) -
Edge cases handled appropriately
Maintainability
-
Code is readable and well-organized -
Code is testable and well-tested -
Follows project patterns and conventions
Acceptance Review
-
Reviewed by at least 1 teammate -
Reviewed by product owner
Closes #68 (closed)