""" Unit tests for authentication functionality. """ import pytest from unittest.mock import patch, MagicMock, AsyncMock from fastapi.testclient import TestClient from jose import jwt pytestmark = pytest.mark.asyncio class TestAdminRoleDetection: """Tests for admin role detection.""" def test_admin_email_gets_admin_role(self): """Test that admin email is correctly identified.""" from app.config import settings admin_email = settings.ADMIN_EMAIL test_email = "regular@example.com" # Admin email should be set (either from env or default) assert admin_email is not None assert len(admin_email) > 0 assert test_email != admin_email @patch("app.routers.auth.settings") def test_create_token_includes_role(self, mock_settings): """Test that created tokens include the role.""" mock_settings.JWT_SECRET = "test-secret" mock_settings.ADMIN_EMAIL = "admin@test.com" from app.routers.auth import create_token # Test admin token admin_token = create_token("admin@test.com", "admin") admin_payload = jwt.decode(admin_token, "test-secret", algorithms=["HS256"]) assert admin_payload["role"] == "admin" # Test user token user_token = create_token("user@test.com", "user") user_payload = jwt.decode(user_token, "test-secret", algorithms=["HS256"]) assert user_payload["role"] == "user" class TestTokenValidation: """Tests for JWT token validation.""" @patch("app.routers.auth.settings") def test_decode_valid_token(self, mock_settings): """Test decoding a valid token.""" mock_settings.JWT_SECRET = "test-secret" from app.routers.auth import create_token, decode_token token = create_token("test@example.com", "user") payload = decode_token(token) assert payload.email == "test@example.com" assert payload.role == "user" @patch("app.routers.auth.settings") def test_decode_invalid_token_raises_error(self, mock_settings): """Test that invalid tokens raise an error.""" mock_settings.JWT_SECRET = "test-secret" from app.routers.auth import decode_token from fastapi import HTTPException with pytest.raises(HTTPException) as exc_info: decode_token("invalid-token") assert exc_info.value.status_code == 401 class TestLoginEndpoint: """Tests for the login endpoint.""" @pytest.fixture def client(self): """Create test client.""" from app.main import app # Skip lifespan for tests app.router.lifespan_context = None return TestClient(app, raise_server_exceptions=False) @patch("app.routers.auth.httpx.AsyncClient") @patch("app.routers.auth.settings") async def test_login_success(self, mock_settings, mock_client_class): """Test successful login.""" mock_settings.AUTH_API_URL = "https://auth.test.com/login" mock_settings.ADMIN_EMAIL = "admin@test.com" mock_settings.JWT_SECRET = "test-secret" mock_response = MagicMock() mock_response.status_code = 200 mock_response.json.return_value = {"token": "external-token"} mock_client = AsyncMock() mock_client.post.return_value = mock_response mock_client.__aenter__.return_value = mock_client mock_client.__aexit__.return_value = None mock_client_class.return_value = mock_client from app.routers.auth import login from app.models import LoginRequest result = await login(LoginRequest(email="user@test.com", password="password")) assert result.email == "user@test.com" assert result.role == "user" assert result.token is not None @patch("app.routers.auth.httpx.AsyncClient") @patch("app.routers.auth.settings") async def test_login_admin_gets_admin_role(self, mock_settings, mock_client_class): """Test that admin email gets admin role.""" mock_settings.AUTH_API_URL = "https://auth.test.com/login" mock_settings.ADMIN_EMAIL = "admin@test.com" mock_settings.JWT_SECRET = "test-secret" mock_response = MagicMock() mock_response.status_code = 200 mock_client = AsyncMock() mock_client.post.return_value = mock_response mock_client.__aenter__.return_value = mock_client mock_client.__aexit__.return_value = None mock_client_class.return_value = mock_client from app.routers.auth import login from app.models import LoginRequest result = await login(LoginRequest(email="admin@test.com", password="password")) assert result.role == "admin"