Merge pull request #98 from abhi1693/riya/backend-auth-bootstrap-tests
test(backend): cover /auth/bootstrap route handler
This commit is contained in:
87
backend/tests/test_auth_bootstrap_api.py
Normal file
87
backend/tests/test_auth_bootstrap_api.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# ruff: noqa: INP001
|
||||
"""Unit-level API tests for /auth bootstrap endpoint.
|
||||
|
||||
These tests intentionally override auth dependencies to avoid DB wiring and
|
||||
focus on route-handler behavior (response shape + auth gating).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from app.api.auth import router as auth_router
|
||||
from app.core.auth import AuthContext, get_auth_context
|
||||
from app.models.users import User
|
||||
|
||||
|
||||
def _build_test_app(*, auth_ctx: AuthContext) -> FastAPI:
|
||||
app = FastAPI()
|
||||
api_v1 = APIRouter(prefix="/api/v1")
|
||||
api_v1.include_router(auth_router)
|
||||
app.include_router(api_v1)
|
||||
|
||||
async def _override_get_auth_context() -> AuthContext:
|
||||
return auth_ctx
|
||||
|
||||
app.dependency_overrides[get_auth_context] = _override_get_auth_context
|
||||
return app
|
||||
|
||||
|
||||
async def _get(client: AsyncClient, path: str) -> tuple[int, dict]:
|
||||
resp = await client.post(path)
|
||||
payload = resp.json() if resp.content else {}
|
||||
return resp.status_code, payload
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_bootstrap_returns_user_profile_when_authenticated() -> None:
|
||||
user = User(clerk_user_id="user_123", email="user@example.com", name="User")
|
||||
app = _build_test_app(auth_ctx=AuthContext(actor_type="user", user=user))
|
||||
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=app),
|
||||
base_url="http://testserver",
|
||||
) as client:
|
||||
status, payload = await _get(client, "/api/v1/auth/bootstrap")
|
||||
|
||||
assert status == 200
|
||||
assert payload["clerk_user_id"] == "user_123"
|
||||
assert payload["email"] == "user@example.com"
|
||||
assert payload["name"] == "User"
|
||||
assert payload["id"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_bootstrap_rejects_requests_without_user_context() -> None:
|
||||
app = _build_test_app(auth_ctx=AuthContext(actor_type="user", user=None))
|
||||
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=app),
|
||||
base_url="http://testserver",
|
||||
) as client:
|
||||
status, payload = await _get(client, "/api/v1/auth/bootstrap")
|
||||
|
||||
assert status == 401
|
||||
assert payload == {"detail": "Unauthorized"}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_bootstrap_rejects_non_user_actor_type() -> None:
|
||||
# Runtime behavior: handler checks `auth.actor_type != "user"`.
|
||||
# Use a duck-typed object to simulate a non-user actor.
|
||||
from types import SimpleNamespace
|
||||
|
||||
app = _build_test_app(
|
||||
auth_ctx=SimpleNamespace(actor_type="agent", user=None), # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
async with AsyncClient(
|
||||
transport=ASGITransport(app=app),
|
||||
base_url="http://testserver",
|
||||
) as client:
|
||||
status, payload = await _get(client, "/api/v1/auth/bootstrap")
|
||||
|
||||
assert status == 401
|
||||
assert payload == {"detail": "Unauthorized"}
|
||||
Reference in New Issue
Block a user