wrongmove/tests/unit/test_decision_routes.py

129 lines
4.2 KiB
Python
Raw Normal View History

"""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