deer-flow/backend/tests/unittest/test_auth_dependencies.py
rayhpeng 2fe0856e33 refactor(tests): reorganize tests into unittest/ and e2e/ directories
- Move all unit tests from tests/ to tests/unittest/
- Add tests/e2e/ directory for end-to-end tests
- Update conftest.py for new test structure
- Add new tests for auth dependencies, policies, route injection
- Add new tests for run callbacks, create store, execution artifacts
- Remove obsolete tests for deleted persistence layer

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-22 11:24:53 +08:00

158 lines
5.3 KiB
Python

from __future__ import annotations
from datetime import UTC, datetime
from types import SimpleNamespace
import pytest
from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from app.plugins.auth.domain.config import AuthConfig
from app.plugins.auth.security.dependencies import (
get_current_user_from_request,
get_current_user_id,
get_optional_user_from_request,
)
from app.plugins.auth.domain.jwt import create_access_token
from app.plugins.auth.runtime.config_state import set_auth_config
from app.plugins.auth.storage import DbUserRepository, UserCreate
from store.persistence import MappedBase
from app.plugins.auth.storage.models import User as UserModel # noqa: F401
_TEST_SECRET = "test-secret-auth-dependencies-min-32"
@pytest.fixture(autouse=True)
def _setup_auth_config():
set_auth_config(AuthConfig(jwt_secret=_TEST_SECRET))
yield
set_auth_config(AuthConfig(jwt_secret=_TEST_SECRET))
async def _make_request(tmp_path, *, cookie: str | None = None, users: list[UserCreate] | None = None):
engine = create_async_engine(
f"sqlite+aiosqlite:///{tmp_path / 'auth-deps.db'}",
future=True,
)
async with engine.begin() as conn:
await conn.run_sync(MappedBase.metadata.create_all)
session_factory = async_sessionmaker(
bind=engine,
class_=AsyncSession,
expire_on_commit=False,
autoflush=False,
)
session = session_factory()
if users:
repo = DbUserRepository(session)
for user in users:
await repo.create_user(user)
await session.commit()
request = SimpleNamespace(
cookies={"access_token": cookie} if cookie is not None else {},
state=SimpleNamespace(_auth_session=session),
)
return request, session, engine
class TestAuthDependencies:
@pytest.mark.anyio
async def test_no_cookie_returns_401(self, tmp_path):
request, session, engine = await _make_request(tmp_path)
try:
with pytest.raises(HTTPException) as exc_info:
await get_current_user_from_request(request)
finally:
await session.close()
await engine.dispose()
assert exc_info.value.status_code == 401
assert exc_info.value.detail["code"] == "not_authenticated"
@pytest.mark.anyio
async def test_invalid_token_returns_401(self, tmp_path):
request, session, engine = await _make_request(tmp_path, cookie="garbage")
try:
with pytest.raises(HTTPException) as exc_info:
await get_current_user_from_request(request)
finally:
await session.close()
await engine.dispose()
assert exc_info.value.status_code == 401
assert exc_info.value.detail["code"] == "token_invalid"
@pytest.mark.anyio
async def test_missing_user_returns_401(self, tmp_path):
token = create_access_token("missing-user", token_version=0)
request, session, engine = await _make_request(tmp_path, cookie=token)
try:
with pytest.raises(HTTPException) as exc_info:
await get_current_user_from_request(request)
finally:
await session.close()
await engine.dispose()
assert exc_info.value.status_code == 401
assert exc_info.value.detail["code"] == "user_not_found"
@pytest.mark.anyio
async def test_token_version_mismatch_returns_401(self, tmp_path):
token = create_access_token("user-1", token_version=0)
request, session, engine = await _make_request(
tmp_path,
cookie=token,
users=[
UserCreate(
id="user-1",
email="user1@example.com",
token_version=2,
)
],
)
try:
with pytest.raises(HTTPException) as exc_info:
await get_current_user_from_request(request)
finally:
await session.close()
await engine.dispose()
assert exc_info.value.status_code == 401
assert exc_info.value.detail["code"] == "token_invalid"
@pytest.mark.anyio
async def test_valid_token_returns_user(self, tmp_path):
token = create_access_token("user-2", token_version=3)
request, session, engine = await _make_request(
tmp_path,
cookie=token,
users=[
UserCreate(
id="user-2",
email="user2@example.com",
token_version=3,
)
],
)
try:
user = await get_current_user_from_request(request)
user_id = await get_current_user_id(request)
finally:
await session.close()
await engine.dispose()
assert user.id == "user-2"
assert user.email == "user2@example.com"
assert user_id == "user-2"
@pytest.mark.anyio
async def test_optional_user_returns_none_on_failure(self, tmp_path):
request, session, engine = await _make_request(tmp_path, cookie="bad-token")
try:
user = await get_optional_user_from_request(request)
finally:
await session.close()
await engine.dispose()
assert user is None