fix: Admin notification api for camp volunteers
Merge Request
Overview
Adds dedicated test coverage for the Broadcast functionality across 5 frontend files and achieves 100% branch coverage on the backend broadcast endpoint. Also includes a bug fix in ProtectedRoute.tsx that was discovered during test authoring.
What does this MR do and why?
The broadcast feature was previously untested. This MR adds comprehensive test coverage across the full stack — from the React Router route guard to the API client wrapper to the backend endpoint — to ensure correctness, prevent regressions, and validate RBAC enforcement at every layer.
A routing bug in ProtectedRoute.tsx was discovered and fixed in the process: Coordinators were incorrectly being redirected away from /admin/broadcast despite having the required role.
Issue :#111 (closed)
Changes Made
-
src/pages/admin/BroadcastPage.test.tsx— new test file -
src/components/AppLayout.test.tsx— new test file -
src/lib/api.test.ts— new test file -
src/pages/DashboardPage.test.tsx— new test file -
src/App.test.tsx— new test file -
src/components/ProtectedRoute.tsx— bug fix (Coordinator redirect on/admin/broadcast) -
tests/test_api/test_broadcast.py— 2 new edge-case tests added
Technical Details
Bug fix — ProtectedRoute.tsx:
Coordinators were being redirected away from /admin/broadcast due to an incorrect role check. The fix ensures that both Admin and Coordinator roles are recognized as authorized for that route.
Frontend test design:
Each test file maps 1:1 to a source file modified for the broadcast feature. RBAC assertions use a mocked useAuth context to simulate different roles without requiring a real auth backend.
Backend coverage:
Two previously missing edge cases were identified via a coverage report and added to tests/test_api/test_broadcast.py.
Type of Change
-
🐛 Bug fix (non-breaking change that fixes an issue) -
✨ New feature (non-breaking change that adds functionality) -
💥 Breaking change (fix or feature that would cause existing functionality to change) -
📝 Documentation update -
♻ ️ Refactor (no functional changes) -
⚡ Performance improvement -
🧪 Test update -
🔧 Configuration change -
🚨 Security fix -
🗑 ️ Deprecation (removing deprecated code)
Also includes a
🐛 bug fix inProtectedRoute.tsxdiscovered during test authoring.
Related Issues / References
Screenshots or Screen Recordings
How to Validate Locally
Previous behaviour:
- No tests existed for the broadcast feature.
- Coordinators navigating to
/admin/broadcastwere incorrectly redirected.
Changes made:
- 5 frontend test files added covering routing, RBAC, API client, and UI behaviour.
- 2 backend edge-case tests added to achieve 100% branch coverage.
-
ProtectedRoute.tsxupdated to correctly permit Coordinators on/admin/broadcast.
New behaviour:
- All broadcast-related tests pass under
vitestandpytest. - Coordinators can successfully access
/admin/broadcast.
Testing Done
-
Unit tests added/updated -
API endpoint tests passing
Test Cases Covered:
| Scenario | Expected Result | Status |
|---|---|---|
Volunteer accesses /admin/broadcast
|
"Access Denied" screen rendered | |
Authorized role accesses /admin/broadcast
|
Broadcast form renders correctly | |
| Submit button with no delivery channel selected | Button remains disabled | |
| Submit button with all fields filled and channel toggled | Broadcast API invoked on submit | |
| Admin/Coordinator sidebar | "Broadcasts" link is visible | |
| Volunteer sidebar | "Broadcasts" link is hidden | |
broadcastMessage API wrapper |
POSTs to /api/v1/medical-camps/broadcast with correct payload |
|
| Dashboard — Admin/Coordinator | "Broadcasts" quick-action button renders | |
| Dashboard — Volunteer | "Broadcasts" quick-action button is hidden | |
Authorized user navigates to /admin/broadcast
|
BroadcastPage renders | |
Unauthorized user navigates to /admin/broadcast
|
Page does not render | |
| Broadcast attempted with no active camp |
404 Not Found returned |
|
| Broadcast attempted with no signed-up volunteers |
202 response with count of 0 |
Test Commands Run:
# Frontend — run broadcast-related tests
npx vitest run src/pages/admin/BroadcastPage.test.tsx \
src/components/AppLayout.test.tsx \
src/lib/api.test.ts \
src/pages/DashboardPage.test.tsx \
src/App.test.tsx
# Backend — run broadcast tests with coverage
pytest tests/test_api/test_broadcast.py -v
# Backend — verify 100% branch coverage
pytest tests/test_api/test_broadcast.py --cov=app --cov-report=term-missing
Code Quality Checklist
Code Standards
-
Code follows project conventions (naming, structure, formatting) -
No debug statements or commented-out code left -
No unused imports, variables, or functions -
No duplicate code (DRY principle followed) -
Type hints are properly defined -
Ruff checks pass (run before merge)
Python & FastAPI Best Practices
-
Functions follow single-responsibility principle -
Error handling is comprehensive (try/except with proper logging)
API Design
-
Authentication/authorization enforced -
Role-based access control validated via tests
Security
-
No sensitive data logged -
SQL injection prevention verified (ORM used)
Error Handling
-
Errors are caught and handled gracefully -
HTTP error responses follow API standards
Documentation
-
README.md updated (if setup steps changed) -
.env.exampleupdated (if new env vars added) -
Code comments explain complex logic -
CHANGELOG.md will be updated (if applicable)
Known Limitations / Technical Debt
None introduced. The ProtectedRoute.tsx fix resolves a pre-existing bug rather than introducing new debt.
Additional Notes
The ProtectedRoute.tsx bug was found organically while writing the App-level routing tests — it would not have surfaced without this test coverage, which validates the value of the testing effort.
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