"""Unit tests for passkey route error handling.""" from unittest.mock import patch, MagicMock import pytest from starlette.testclient import TestClient # We need to test through the FastAPI app or build a minimal test client from api.passkey_routes import passkey_router from fastapi import FastAPI def _build_app() -> FastAPI: app = FastAPI() app.include_router(passkey_router) return app class TestPasskeyErrorHandling: """Tests that passkey routes return generic error messages for internal exceptions.""" @patch("api.passkey_routes.passkey_service") @patch("api.passkey_routes.UserRepository") def test_register_begin_internal_error_returns_generic_message( self, mock_user_repo: MagicMock, mock_service: MagicMock ) -> None: mock_service.begin_registration.side_effect = RuntimeError("DB connection lost") client = TestClient(_build_app()) resp = client.post("/api/passkey/register/begin", json={"email": "test@example.com"}) assert resp.status_code == 400 assert resp.json()["detail"] == "Registration failed. Please try again." assert "DB connection lost" not in resp.json()["detail"] @patch("api.passkey_routes.passkey_service") @patch("api.passkey_routes.UserRepository") def test_register_begin_value_error_returns_user_message( self, mock_user_repo: MagicMock, mock_service: MagicMock ) -> None: mock_service.begin_registration.side_effect = ValueError("Email already registered") client = TestClient(_build_app()) resp = client.post("/api/passkey/register/begin", json={"email": "test@example.com"}) assert resp.status_code == 400 assert resp.json()["detail"] == "Email already registered" @patch("api.passkey_routes.passkey_service") @patch("api.passkey_routes.UserRepository") def test_login_complete_internal_error_returns_generic_message( self, mock_user_repo: MagicMock, mock_service: MagicMock ) -> None: mock_service.complete_authentication.side_effect = RuntimeError("Crypto failure") client = TestClient(_build_app()) resp = client.post( "/api/passkey/login/complete", json={"session_id": "abc", "credential": {"id": "x"}}, ) assert resp.status_code == 400 assert resp.json()["detail"] == "Login could not be completed." assert "Crypto failure" not in resp.json()["detail"] @patch("api.passkey_routes.passkey_service") @patch("api.passkey_routes.UserRepository") def test_login_complete_value_error_returns_user_message( self, mock_user_repo: MagicMock, mock_service: MagicMock ) -> None: mock_service.complete_authentication.side_effect = ValueError("Invalid credential") client = TestClient(_build_app()) resp = client.post( "/api/passkey/login/complete", json={"session_id": "abc", "credential": {"id": "x"}}, ) assert resp.status_code == 400 assert resp.json()["detail"] == "Invalid credential"