"""Integration tests for the auth routes. Uses FastAPI TestClient with a mocked user store. Does not require a running PostgreSQL. """ import pytest from fastapi.testclient import TestClient from unittest.mock import MagicMock, patch from app.infrastructure.auth.user_store import UserRecord @pytest.fixture def client(): """Return a TestClient with a mocked user store.""" mock_store = MagicMock() alice = UserRecord(id="uuid-1", username="alice", hashed_pw="hashed", role="admin", is_active=True) mock_store.authenticate.side_effect = lambda u, p: alice if (u == "alice" and p == "correct") else None with patch("app.shared.bootstrap.get_user_store", return_value=mock_store): # Import after patch so the mock is active when routes import bootstrap. from app.api.main import app with TestClient(app, raise_server_exceptions=False) as c: yield c def test_login_returns_token_for_valid_credentials(client): """POST /auth/token must return an access_token for valid credentials.""" resp = client.post("/api/v1/auth/token", data={"username": "alice", "password": "correct"}) assert resp.status_code == 200 body = resp.json() assert "access_token" in body assert body["token_type"] == "bearer" def test_login_returns_401_for_wrong_password(client): """POST /auth/token must return 401 for wrong password.""" resp = client.post("/api/v1/auth/token", data={"username": "alice", "password": "wrong"}) assert resp.status_code == 401 def test_me_returns_user_when_authenticated(client): """GET /auth/me must return user identity when a valid token is provided.""" login_resp = client.post("/api/v1/auth/token", data={"username": "alice", "password": "correct"}) assert login_resp.status_code == 200, login_resp.text token = login_resp.json()["access_token"] me_resp = client.get("/api/v1/auth/me", headers={"Authorization": f"Bearer {token}"}) assert me_resp.status_code == 200 assert me_resp.json()["username"] == "alice" assert me_resp.json()["role"] == "admin" def test_me_returns_401_without_token(client): """GET /auth/me must return 401 when no token is provided.""" resp = client.get("/api/v1/auth/me") assert resp.status_code == 401