Phase 6: Admin appointments view and cancellation with UI and backend tests
This commit is contained in:
parent
5108a620e7
commit
b3e00b0745
12 changed files with 814 additions and 548 deletions
|
|
@ -656,3 +656,153 @@ class TestCancelAppointment:
|
|||
)
|
||||
assert len(slots_response.json()["slots"]) == 2
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Admin Appointments Tests
|
||||
# =============================================================================
|
||||
|
||||
class TestAdminViewAppointments:
|
||||
"""Test admin viewing all appointments."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_admin_can_view_all_appointments(self, client_factory, regular_user, admin_user):
|
||||
"""Admin can view all appointments."""
|
||||
# Admin sets availability
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as admin_client:
|
||||
await admin_client.put(
|
||||
"/api/admin/availability",
|
||||
json={
|
||||
"date": str(tomorrow()),
|
||||
"slots": [{"start_time": "09:00:00", "end_time": "12:00:00"}],
|
||||
},
|
||||
)
|
||||
|
||||
# User books
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
await client.post(
|
||||
"/api/booking",
|
||||
json={"slot_start": f"{tomorrow()}T09:00:00Z", "note": "Test"},
|
||||
)
|
||||
|
||||
# Admin views all appointments
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as admin_client:
|
||||
response = await admin_client.get("/api/admin/appointments")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data) >= 1
|
||||
assert any(apt["note"] == "Test" for apt in data)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_regular_user_cannot_view_all_appointments(self, client_factory, regular_user):
|
||||
"""Regular user cannot access admin appointments endpoint."""
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
response = await client.get("/api/admin/appointments")
|
||||
|
||||
assert response.status_code == 403
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unauthenticated_cannot_view_all_appointments(self, client):
|
||||
"""Unauthenticated user cannot view appointments."""
|
||||
response = await client.get("/api/admin/appointments")
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
class TestAdminCancelAppointment:
|
||||
"""Test admin cancelling appointments."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_admin_can_cancel_any_appointment(self, client_factory, regular_user, admin_user):
|
||||
"""Admin can cancel any user's appointment."""
|
||||
# Admin sets availability
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as admin_client:
|
||||
await admin_client.put(
|
||||
"/api/admin/availability",
|
||||
json={
|
||||
"date": str(tomorrow()),
|
||||
"slots": [{"start_time": "09:00:00", "end_time": "12:00:00"}],
|
||||
},
|
||||
)
|
||||
|
||||
# User books
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
book_response = await client.post(
|
||||
"/api/booking",
|
||||
json={"slot_start": f"{tomorrow()}T09:00:00Z"},
|
||||
)
|
||||
apt_id = book_response.json()["id"]
|
||||
|
||||
# Admin cancels
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as admin_client:
|
||||
response = await admin_client.post(f"/api/admin/appointments/{apt_id}/cancel")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "cancelled_by_admin"
|
||||
assert data["cancelled_at"] is not None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_regular_user_cannot_use_admin_cancel(self, client_factory, regular_user, admin_user):
|
||||
"""Regular user cannot use admin cancel endpoint."""
|
||||
# Admin sets availability
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as admin_client:
|
||||
await admin_client.put(
|
||||
"/api/admin/availability",
|
||||
json={
|
||||
"date": str(tomorrow()),
|
||||
"slots": [{"start_time": "09:00:00", "end_time": "12:00:00"}],
|
||||
},
|
||||
)
|
||||
|
||||
# User books
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
book_response = await client.post(
|
||||
"/api/booking",
|
||||
json={"slot_start": f"{tomorrow()}T09:00:00Z"},
|
||||
)
|
||||
apt_id = book_response.json()["id"]
|
||||
|
||||
# User tries to use admin cancel endpoint
|
||||
response = await client.post(f"/api/admin/appointments/{apt_id}/cancel")
|
||||
|
||||
assert response.status_code == 403
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_admin_cancel_nonexistent_appointment(self, client_factory, admin_user):
|
||||
"""Returns 404 for non-existent appointment."""
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as client:
|
||||
response = await client.post("/api/admin/appointments/99999/cancel")
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_admin_cannot_cancel_already_cancelled(self, client_factory, regular_user, admin_user):
|
||||
"""Admin cannot cancel an already cancelled appointment."""
|
||||
# Admin sets availability
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as admin_client:
|
||||
await admin_client.put(
|
||||
"/api/admin/availability",
|
||||
json={
|
||||
"date": str(tomorrow()),
|
||||
"slots": [{"start_time": "09:00:00", "end_time": "12:00:00"}],
|
||||
},
|
||||
)
|
||||
|
||||
# User books
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
book_response = await client.post(
|
||||
"/api/booking",
|
||||
json={"slot_start": f"{tomorrow()}T09:00:00Z"},
|
||||
)
|
||||
apt_id = book_response.json()["id"]
|
||||
|
||||
# User cancels their own appointment
|
||||
await client.post(f"/api/appointments/{apt_id}/cancel")
|
||||
|
||||
# Admin tries to cancel again
|
||||
async with client_factory.create(cookies=admin_user["cookies"]) as admin_client:
|
||||
response = await admin_client.post(f"/api/admin/appointments/{apt_id}/cancel")
|
||||
|
||||
assert response.status_code == 400
|
||||
assert "cancelled_by_user" in response.json()["detail"]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue