""" Shared pytest fixtures for Paper Dynasty web app testing. Provides database sessions, test data factories, and common testing utilities following the transaction rollback pattern for test isolation. """ import pytest from sqlmodel import Session, SQLModel, create_engine from uuid import uuid4 # Test Database Configuration TEST_DATABASE_URL = "postgresql://paper_dynasty_user:paper_dynasty_test_password@localhost:5434/paper_dynasty_test" @pytest.fixture(scope="session") def test_engine(): """Create test database engine for the entire test session.""" engine = create_engine(TEST_DATABASE_URL, echo=False) # Create all tables SQLModel.metadata.create_all(engine) yield engine # Optional: Drop all tables after test session # SQLModel.metadata.drop_all(engine) @pytest.fixture def db_session(test_engine): """ Create database session with transaction rollback for test isolation. This is the primary fixture for database tests. Each test runs in a transaction that is rolled back after the test completes, ensuring complete isolation between tests. """ # Create a connection and start a transaction connection = test_engine.connect() transaction = connection.begin() # Create session bound to the connection session = Session(bind=connection) try: yield session finally: # Close session and rollback transaction session.close() transaction.rollback() connection.close() @pytest.fixture def fresh_db_session(test_engine): """ Create database session for integration tests that need real commits. Use this fixture for tests that specifically need to test commit behavior or cross-transaction functionality. Use sparingly as these tests are slower and require manual cleanup. """ with Session(test_engine) as session: yield session # Manual cleanup would go here if needed def generate_unique_id(): """Generate unique integer ID for test data.""" # Use last 6 digits of uuid4 as integer to avoid PostgreSQL integer overflow # This gives us numbers up to ~16 million, well under PostgreSQL's 2.1 billion limit return int(str(uuid4()).replace('-', '')[-6:], 16) def generate_unique_name(prefix="Test"): """Generate unique name for test data.""" return f"{prefix} {uuid4().hex[:8]}"