import pytest from sqlalchemy.types import TypeDecorator, TEXT import json import sqlalchemy import sqlalchemy.dialects.postgresql class SQLiteCompatibleARRAY(TypeDecorator): impl = TEXT cache_ok = True def __init__(self, item_type, *args, **kwargs): self.item_type = item_type super().__init__() def load_dialect_impl(self, dialect): if dialect.name == "postgresql": from sqlalchemy.dialects.postgresql import ARRAY as pg_ARRAY return dialect.type_descriptor(pg_ARRAY(self.item_type)) else: return dialect.type_descriptor(TEXT()) def process_bind_param(self, value, dialect): if dialect.name == "sqlite": if value is not None: from uuid import UUID clean_value = [str(x) if isinstance(x, UUID) else x for x in value] return json.dumps(clean_value) return None return value def process_result_value(self, value, dialect): if dialect.name == "sqlite": if value is not None: try: return json.loads(value) except Exception: return [] return None return value # Monkeypatch both sqlalchemy.ARRAY and postgresql.ARRAY before models are loaded sqlalchemy.ARRAY = SQLiteCompatibleARRAY sqlalchemy.dialects.postgresql.ARRAY = SQLiteCompatibleARRAY from sqlalchemy import create_engine, event, Engine from sqlalchemy.orm import sessionmaker, mapper from app.core.database import Base from app.core.config import settings # Import models for SQLAlchemy class registry resolution from app.models.user import User from app.models.body import BodyProfile from app.models.wardrobe import WardrobeItem from app.models.tryon import TryOnTask # In-memory SQLite for testing to avoid dependencies on running PG TEST_DATABASE_URL = "sqlite:///./test.db" @pytest.fixture(scope="session") def db_engine(): engine = create_engine(TEST_DATABASE_URL, connect_args={"check_same_thread": False}) Base.metadata.create_all(bind=engine) yield engine Base.metadata.drop_all(bind=engine) @pytest.fixture(scope="function") def db_session(db_engine): connection = db_engine.connect() transaction = connection.begin() Session = sessionmaker(bind=connection) session = Session() yield session session.close() transaction.rollback() connection.close()