Add comprehensive test suite for image processing and related services
- Implement tests for database generator to ensure proper session handling. - Create tests for EXIF extraction and conversion functions. - Add tests for image-related endpoints, ensuring proper data retrieval and isolation between clients. - Develop tests for OCR functionality, including language detection and text extraction. - Introduce tests for the image processing pipeline, covering success and failure scenarios. - Validate rate limiting functionality and ensure independent counters for different clients. - Implement scraper tests to verify HTML content fetching and error handling. - Add unit tests for various services, including storage and filename generation. - Establish worker entry point for ARQ to handle background image processing tasks.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
Configuration SQLAlchemy — session async
|
||||
"""
|
||||
import logging
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
from app.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
engine = create_async_engine(
|
||||
settings.DATABASE_URL,
|
||||
echo=settings.DEBUG,
|
||||
future=True,
|
||||
)
|
||||
|
||||
AsyncSessionLocal = async_sessionmaker(
|
||||
bind=engine,
|
||||
class_=AsyncSession,
|
||||
expire_on_commit=False,
|
||||
autoflush=False,
|
||||
autocommit=False,
|
||||
)
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
|
||||
async def get_db() -> AsyncSession:
|
||||
"""Dependency FastAPI — injecte une session DB dans chaque requête."""
|
||||
async with AsyncSessionLocal() as session:
|
||||
try:
|
||||
yield session
|
||||
await session.commit()
|
||||
except Exception:
|
||||
await session.rollback()
|
||||
raise
|
||||
finally:
|
||||
await session.close()
|
||||
|
||||
|
||||
async def init_db():
|
||||
"""Crée toutes les tables et initialise un client par défaut si nécessaire."""
|
||||
import secrets
|
||||
import hashlib
|
||||
from sqlalchemy import select
|
||||
from app.models.client import APIClient, ClientPlan
|
||||
|
||||
async with engine.begin() as conn:
|
||||
from app.models import image # noqa: F401
|
||||
from app.models import client # noqa: F401
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
|
||||
# Vérifier s'il y a déjà des clients
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(select(APIClient).limit(1))
|
||||
if result.scalar_one_or_none() is None:
|
||||
# Table vide -> Création du client bootstrap
|
||||
raw_key = secrets.token_urlsafe(32)
|
||||
key_hash = hashlib.sha256(raw_key.encode("utf-8")).hexdigest()
|
||||
|
||||
bootstrap_client = APIClient(
|
||||
name="Default Admin",
|
||||
api_key_hash=key_hash,
|
||||
scopes=["images:read", "images:write", "images:delete", "ai:use", "admin"],
|
||||
plan=ClientPlan.PREMIUM,
|
||||
)
|
||||
session.add(bootstrap_client)
|
||||
await session.commit()
|
||||
|
||||
logger.info("bootstrap.client_created", extra={
|
||||
"client_id": bootstrap_client.id,
|
||||
"api_key": raw_key,
|
||||
"warning": "Notez cette clé ! Elle ne sera plus affichée.",
|
||||
})
|
||||
Reference in New Issue
Block a user