Files
sdb2-backend/tests/conftest.py
JSC e456d34897 Add tests for authentication and utilities, and update dependencies
- Created a new test package for services and added tests for AuthService.
- Implemented tests for user registration, login, and token creation.
- Added a new test package for utilities and included tests for password and JWT utilities.
- Updated `uv.lock` to include new dependencies: bcrypt, email-validator, pyjwt, and pytest-asyncio.
2025-07-25 17:48:43 +02:00

213 lines
5.6 KiB
Python

"""Test configuration and fixtures."""
import asyncio
from collections.abc import AsyncGenerator
from typing import Any
import pytest
import pytest_asyncio
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient
from sqlalchemy.ext.asyncio import create_async_engine
from sqlmodel import SQLModel, select
from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.database import get_db
from app.main import create_app
from app.models.plan import Plan
from app.models.user import User
from app.utils.auth import JWTUtils, PasswordUtils
@pytest.fixture(scope="session")
def event_loop() -> Any:
"""Create an instance of the default event loop for the test session."""
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
@pytest_asyncio.fixture(scope="session")
async def test_engine() -> Any:
"""Create a test database engine."""
# Use in-memory SQLite database for tests
engine = create_async_engine(
"sqlite+aiosqlite:///:memory:",
echo=False,
)
# Create all tables
async with engine.begin() as conn:
await conn.run_sync(SQLModel.metadata.create_all)
yield engine
await engine.dispose()
@pytest_asyncio.fixture
async def test_session(test_engine: Any) -> AsyncGenerator[AsyncSession, None]:
"""Create a test database session."""
connection = await test_engine.connect()
transaction = await connection.begin()
session = AsyncSession(bind=connection)
try:
yield session
finally:
await session.close()
await transaction.rollback()
await connection.close()
@pytest_asyncio.fixture
async def test_app(test_session: AsyncSession) -> FastAPI:
"""Create a test FastAPI application."""
app = create_app()
# Override the database dependency
async def override_get_db() -> AsyncGenerator[AsyncSession, None]:
yield test_session
app.dependency_overrides[get_db] = override_get_db
return app
@pytest_asyncio.fixture
async def test_client(test_app: FastAPI) -> AsyncGenerator[AsyncClient, None]:
"""Create a test HTTP client."""
async with AsyncClient(
transport=ASGITransport(app=test_app),
base_url="http://test",
) as client:
yield client
@pytest_asyncio.fixture
async def test_plan(test_session: AsyncSession) -> Plan:
"""Create a test plan."""
# Check if plan already exists in this session
existing_plan = await test_session.exec(select(Plan).where(Plan.code == "free"))
plan = existing_plan.first()
if not plan:
plan = Plan(
code="free",
name="Free Plan",
description="Test free plan",
credits=100,
max_credits=100,
)
test_session.add(plan)
await test_session.commit()
await test_session.refresh(plan)
return plan
@pytest_asyncio.fixture
async def test_pro_plan(test_session: AsyncSession) -> Plan:
"""Create a test pro plan."""
# Check if plan already exists in this session
existing_plan = await test_session.exec(select(Plan).where(Plan.code == "pro"))
plan = existing_plan.first()
if not plan:
plan = Plan(
code="pro",
name="Pro Plan",
description="Test pro plan",
credits=300,
max_credits=300,
)
test_session.add(plan)
await test_session.commit()
await test_session.refresh(plan)
return plan
@pytest_asyncio.fixture
async def test_user(test_session: AsyncSession, test_plan: Plan) -> User:
"""Create a test user."""
user = User(
email="test@example.com",
name="Test User",
password_hash=PasswordUtils.hash_password("testpassword123"),
role="user",
is_active=True,
plan_id=test_plan.id,
credits=100,
)
test_session.add(user)
await test_session.commit()
await test_session.refresh(user)
return user
@pytest_asyncio.fixture
async def admin_user(test_session: AsyncSession, test_plan: Plan) -> User:
"""Create a test admin user."""
user = User(
email="admin@example.com",
name="Admin User",
password_hash=PasswordUtils.hash_password("adminpassword123"),
role="admin",
is_active=True,
plan_id=test_plan.id,
credits=1000,
)
test_session.add(user)
await test_session.commit()
await test_session.refresh(user)
return user
@pytest.fixture
def test_user_data() -> dict[str, Any]:
"""Test user registration data."""
return {
"email": "newuser@example.com",
"password": "newpassword123",
"name": "New User",
}
@pytest.fixture
def test_login_data() -> dict[str, str]:
"""Test user login data."""
return {
"email": "test@example.com",
"password": "testpassword123",
}
@pytest_asyncio.fixture
async def auth_headers(test_user: User) -> dict[str, str]:
"""Create authentication headers with JWT token."""
token_data = {
"sub": str(test_user.id),
"email": test_user.email,
"role": test_user.role,
}
access_token = JWTUtils.create_access_token(token_data)
return {"Authorization": f"Bearer {access_token}"}
@pytest_asyncio.fixture
async def admin_headers(admin_user: User) -> dict[str, str]:
"""Create admin authentication headers with JWT token."""
token_data = {
"sub": str(admin_user.id),
"email": admin_user.email,
"role": admin_user.role,
}
access_token = JWTUtils.create_access_token(token_data)
return {"Authorization": f"Bearer {access_token}"}