c.execute(text(f'DROP DATABASE IF EXISTS "{TEST_DB_NAME}"')) admin.dispose() # Tables to truncate between API tests (order-independent via TRUNCATE CASCADE) _TRUNCATE = [ "audit_logs", "email_events", "send_attempts", "send_jobs", "campaign_recipients", "campaigns", "recipients", "recipient_lists", "subject_lines", "html_templates", "attachments", "company_phone_numbers", "suppression_list", "oauth_tokens", "oauth_client_configs", "gmail_accounts", "application_settings", "users", ] @pytest.fixture() def api(test_app): """Fresh TestClient with a clean database and one registered+logged-in user.""" from fastapi.testclient import TestClient from sqlalchemy import create_engine, text # wipe all data (keep schema) eng = create_engine(TEST_DATABASE_URL) with eng.connect() as c: for t in _TRUNCATE: try: c.execute(text(f'TRUNCATE TABLE "{t}" RESTART IDENTITY CASCADE')) except Exception: pass c.commit() eng.dispose() with TestClient(test_app) as client: em = f"t_{uuid.uuid4().hex[:10]}@example.com" pw = "TestPass#12345" r = client.post("/auth/register", json={"email": em, "password": pw, "full_name": "Tester"}) assert r.status_code in (200, 201), f"register failed: {r.status_code} {r.text[:300]}" r = client.post("/auth/login", json={"email": em, "password": pw}) assert r.status_code == 200, f"login failed: {r.status_code} {r.text[:300]}" client.email, client.password = em, pw yield client