import pytest from datetime import datetime, timedelta, timezone from httpx import AsyncClient, ASGITransport from app.main import app from app.database import engine from app.models import SQLModel @pytest.fixture async def setup_db(): async with engine.begin() as conn: await conn.run_sync(SQLModel.metadata.drop_all) await conn.run_sync(SQLModel.metadata.create_all) @pytest.mark.asyncio async def test_list_sessions_date_only_filter(setup_db): # Test that passing a date (midnight) also works and includes the whole day target_date = datetime(2023, 10, 1, tzinfo=timezone.utc) other_date = datetime(2023, 10, 2, tzinfo=timezone.utc) async with AsyncClient( transport=ASGITransport(app=app), base_url="http://test" ) as ac: # 1. Create a session that starts LATER in the day on OTHER date (should be excluded) # We end it immediately to avoid 409s in the test start_time_other = other_date.replace(hour=20, minute=0) resp_other = await ac.post("/api/sessions", json={"start_time": start_time_other.isoformat()}) assert resp_other.status_code == 201 session_id_other = resp_other.json()["id"] await ac.patch(f"/api/sessions/{session_id_other}/end", json={"end_time": (start_time_other + timedelta(minutes=30)).isoformat()}) # 2. Create a session that starts ON the target_date (should be included) start_time_target = target_date.replace(hour=20, minute=0) resp_target = await ac.post("/api/sessions", json={"start_time": start_time_target.isoformat()}) assert resp_target.status_code == 201 session_id_target = resp_target.json()["id"] await ac.patch(f"/api/sessions/{session_id_target}/end", json={"end_time": (start_time_target + timedelta(minutes=30)).isoformat()}) # 3. Create a session that starts EARLIER on the target_date (should be included) start_time_early = target_date.replace(hour=2, minute=0) resp_early = await ac.post("/api/sessions", json={"start_time": start_time_early.isoformat()}) assert resp_early.status_code == 201 session_id_early = resp_early.json()["id"] await ac.patch(f"/api/sessions/{session_id_early}/end", json={"end_time": (start_time_early + timedelta(minutes=30)).isoformat()}) # 4. Create a session that is on the OTHER date (should be excluded) start_time_other2 = other_date.replace(hour=2, minute=0) resp_other2 = await ac.post("/api/sessions", json={"start_time": start_time_other2.isoformat()}) assert resp_other2.status_code == 201 session_id_other2 = resp_other2.json()["id"] await ac.patch(f"/api/sessions/{session_id_other2}/end", json={"end_time": (start_time_other2 + timedelta(minutes=30)).isoformat()}) # Query with to_date = target_date (midnight) # This should be expanded to 23:59:59 on target_date. # Should include the 2 sessions on target_date (target and early). # Should exclude the 2 sessions on other_date. to_date_str = target_date.strftime("%Y-%m-%d") # "2023-10-01" print(f"\nGET: to_date={to_date_str}") response = await ac.get(f"/api/sessions?to_date={to_date_str}") print(f"GET RESPONSE: {response.status_code}, body={response.json()}") assert response.status_code == 200 sessions = response.json()["sessions"] # We expect exactly 2 sessions (the ones on target_date) assert len(sessions) == 2, f"Expected 2 sessions (the ones on {to_date_str}), but got {len(sessions)}. (Body: {response.json()})" for s in sessions: # Verify that the sessions returned are indeed from the target_date assert target_date.strftime("%Y-%m-%d") in s["start_time"]