"""Unit tests for decision API routes.""" import pytest from httpx import ASGITransport, AsyncClient from sqlalchemy import Engine from sqlmodel import SQLModel, Session, create_engine from models.user import User from models.decision import ListingDecision # noqa: F401 - needed for table creation from api.auth import get_current_user, User as AuthUser @pytest.fixture def decision_engine() -> Engine: engine = create_engine( "sqlite:///:memory:", echo=False, connect_args={"check_same_thread": False}, ) SQLModel.metadata.create_all(engine) with Session(engine) as session: session.add(User(id=1, email="test@example.com")) session.commit() yield engine # type: ignore[misc] SQLModel.metadata.drop_all(engine) @pytest.fixture async def client(decision_engine: Engine) -> AsyncClient: import database import api.app as api_app import api.decision_routes as decision_routes_mod import api.poi_routes as poi_routes_mod app = api_app.app mock_user = AuthUser( sub="test-user-id", email="test@example.com", name="Test User" ) app.dependency_overrides[get_current_user] = lambda: mock_user original_db = database.engine original_app = api_app.engine original_decision = decision_routes_mod.engine original_poi = poi_routes_mod.engine database.engine = decision_engine api_app.engine = decision_engine decision_routes_mod.engine = decision_engine poi_routes_mod.engine = decision_engine transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as c: yield c # type: ignore[misc] database.engine = original_db api_app.engine = original_app decision_routes_mod.engine = original_decision poi_routes_mod.engine = original_poi app.dependency_overrides.clear() class TestDecisionRoutes: @pytest.mark.asyncio async def test_set_decision(self, client: AsyncClient) -> None: resp = await client.put( "/api/decisions/100", json={"decision": "liked", "listing_type": "RENT"}, ) assert resp.status_code == 200 data = resp.json() assert data["decision"] == "liked" assert data["listing_id"] == 100 @pytest.mark.asyncio async def test_get_decisions(self, client: AsyncClient) -> None: await client.put( "/api/decisions/100", json={"decision": "liked", "listing_type": "RENT"}, ) resp = await client.get("/api/decisions") assert resp.status_code == 200 data = resp.json() assert len(data) == 1 @pytest.mark.asyncio async def test_delete_decision(self, client: AsyncClient) -> None: await client.put( "/api/decisions/100", json={"decision": "liked", "listing_type": "RENT"}, ) resp = await client.delete( "/api/decisions/100", params={"listing_type": "RENT"} ) assert resp.status_code == 200 assert resp.json()["success"] is True @pytest.mark.asyncio async def test_delete_nonexistent_returns_404( self, client: AsyncClient ) -> None: resp = await client.delete( "/api/decisions/999", params={"listing_type": "RENT"} ) assert resp.status_code == 404 @pytest.mark.asyncio async def test_invalid_decision_returns_400( self, client: AsyncClient ) -> None: resp = await client.put( "/api/decisions/100", json={"decision": "maybe", "listing_type": "RENT"}, ) assert resp.status_code == 400 @pytest.mark.asyncio async def test_update_decision(self, client: AsyncClient) -> None: await client.put( "/api/decisions/100", json={"decision": "liked", "listing_type": "RENT"}, ) resp = await client.put( "/api/decisions/100", json={"decision": "disliked", "listing_type": "RENT"}, ) assert resp.status_code == 200 assert resp.json()["decision"] == "disliked" # Still only one decision resp2 = await client.get("/api/decisions") assert len(resp2.json()) == 1