import pytest from fastapi.testclient import TestClient from sqlmodel import Session, SQLModel, create_engine from sqlmodel.pool import StaticPool from app.main import app from app.core.db import get_session from app.schemas.models import User, Partner, Product, Transaction from app.schemas.base import UserRole, PartnerType, TransactionType, TransactionStatus from app.core.auth import get_password_hash @pytest.fixture(name="session") def session_fixture(): """Create a test database session.""" engine = create_engine( "sqlite:///:memory:", # Use in-memory database for each test connect_args={"check_same_thread": False}, poolclass=StaticPool, ) SQLModel.metadata.create_all(engine) with Session(engine) as session: yield session @pytest.fixture(name="client") def client_fixture(session: Session): """Create a test client with dependency override.""" def get_session_override(): return session app.dependency_overrides[get_session] = get_session_override client = TestClient(app) yield client app.dependency_overrides.clear() @pytest.fixture(name="admin_user") def admin_user_fixture(session: Session): """Create an admin user for testing.""" admin_user = User( username="testadmin", password_hash=get_password_hash("adminpassword"), role=UserRole.ADMIN ) session.add(admin_user) session.commit() session.refresh(admin_user) return admin_user @pytest.fixture(name="write_user") def write_user_fixture(session: Session): """Create a write user for testing.""" write_user = User( username="writeuser", password_hash=get_password_hash("writepassword"), role=UserRole.WRITE ) session.add(write_user) session.commit() session.refresh(write_user) return write_user @pytest.fixture(name="read_only_user") def read_only_user_fixture(session: Session): """Create a read-only user for testing.""" read_only_user = User( username="readuser", password_hash=get_password_hash("readpassword"), role=UserRole.READ_ONLY ) session.add(read_only_user) session.commit() session.refresh(read_only_user) return read_only_user @pytest.fixture(name="admin_token") def admin_token_fixture(client: TestClient, admin_user: User): """Get admin authentication token.""" response = client.post("/api/v1/users/login", json={ "username": "testadmin", "password": "adminpassword" }) return response.json()["access_token"] @pytest.fixture(name="write_token") def write_token_fixture(client: TestClient, write_user: User): """Get write user authentication token.""" response = client.post("/api/v1/users/login", json={ "username": "writeuser", "password": "writepassword" }) return response.json()["access_token"] @pytest.fixture(name="read_only_token") def read_only_token_fixture(client: TestClient, read_only_user: User): """Get read-only user authentication token.""" response = client.post("/api/v1/users/login", json={ "username": "readuser", "password": "readpassword" }) return response.json()["access_token"] @pytest.fixture(name="sample_partner") def sample_partner_fixture(session: Session): """Create a sample partner for testing.""" partner = Partner( tin_number=123456789, names="Test Partner Ltd", type=PartnerType.CLIENT, phone_number="0123456789" ) session.add(partner) session.commit() session.refresh(partner) return partner @pytest.fixture(name="sample_product") def sample_product_fixture(session: Session): """Create a sample product for testing.""" product = Product( product_code="PROD001", product_name="Test Product", purchase_price=100, selling_price=150 ) session.add(product) session.commit() session.refresh(product) return product @pytest.fixture(name="sample_transaction") def sample_transaction_fixture(session: Session, sample_partner, admin_user): """Create a sample transaction for testing.""" transaction = Transaction( partner_id=sample_partner.id, transcation_type=TransactionType.SALE, transaction_status=TransactionStatus.UNPAID, total_amount=1000, created_by=admin_user.id, updated_by=admin_user.id ) session.add(transaction) session.commit() session.refresh(transaction) return transaction @pytest.fixture(name="multiple_partners") def multiple_partners_fixture(session: Session): """Create multiple partners for testing.""" partners = [ Partner( tin_number=100000001, names="Client Partner One", type=PartnerType.CLIENT, phone_number="0111111111" ), Partner( tin_number=200000002, names="Supplier Partner Two", type=PartnerType.SUPPLIER, phone_number="0222222222" ), Partner( tin_number=300000003, names="Client Partner Three", type=PartnerType.CLIENT, phone_number="0333333333" ) ] for partner in partners: session.add(partner) session.commit() for partner in partners: session.refresh(partner) return partners @pytest.fixture(name="multiple_products") def multiple_products_fixture(session: Session): """Create multiple products for testing.""" products = [ Product( product_code="ITEM001", product_name="Product One", purchase_price=50, selling_price=75 ), Product( product_code="ITEM002", product_name="Product Two", purchase_price=200, selling_price=250 ), Product( product_code="ITEM003", product_name="Product Three", purchase_price=1000, selling_price=1200 ) ] for product in products: session.add(product) session.commit() for product in products: session.refresh(product) return products