innercontext/backend/tests/conftest.py

113 lines
3 KiB
Python

import os
from datetime import UTC, datetime, timedelta
from uuid import uuid4
# Must be set before importing db (which calls create_engine at module level)
os.environ.setdefault("DATABASE_URL", "sqlite://")
import pytest
from fastapi.testclient import TestClient
from sqlmodel import Session, SQLModel, create_engine
from sqlmodel.pool import StaticPool
import db as db_module
from db import get_session
from innercontext.api.auth_deps import get_current_user
from innercontext.auth import CurrentUser, IdentityData, TokenClaims
from innercontext.models import Role
from main import app
@pytest.fixture()
def session(monkeypatch):
"""Per-test fresh SQLite in-memory database with full isolation."""
engine = create_engine(
"sqlite://",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
# Patch before TestClient triggers lifespan (which calls create_db_and_tables)
monkeypatch.setattr(db_module, "engine", engine)
import innercontext.models # noqa: F401 — populate SQLModel.metadata
SQLModel.metadata.create_all(engine)
with Session(engine) as s:
yield s
# monkeypatch auto-restores db_module.engine after test
@pytest.fixture()
def current_user() -> CurrentUser:
claims = TokenClaims(
issuer="https://auth.test",
subject="test-user",
audience=("innercontext-web",),
expires_at=datetime.now(UTC) + timedelta(hours=1),
groups=("innercontext-admin",),
raw_claims={"iss": "https://auth.test", "sub": "test-user"},
)
return CurrentUser(
user_id=uuid4(),
role=Role.ADMIN,
identity=IdentityData.from_claims(claims),
claims=claims,
)
@pytest.fixture()
def client(session, monkeypatch, current_user):
"""TestClient using the per-test session for every request."""
def _override():
yield session
def _current_user_override():
return current_user
app.dependency_overrides[get_session] = _override
app.dependency_overrides[get_current_user] = _current_user_override
with TestClient(app) as c:
yield c
app.dependency_overrides.clear()
# ---- Shared data fixtures ----
@pytest.fixture()
def product_data():
return {
"name": "CeraVe Moisturising Cream",
"brand": "CeraVe",
"category": "moisturizer",
"recommended_time": "both",
"leave_on": True,
}
@pytest.fixture()
def created_product(client, product_data):
r = client.post("/products", json=product_data)
assert r.status_code == 201
return r.json()
@pytest.fixture()
def medication_data():
return {"kind": "prescription", "product_name": "Epiduo"}
@pytest.fixture()
def created_medication(client, medication_data):
r = client.post("/health/medications", json=medication_data)
assert r.status_code == 201
return r.json()
@pytest.fixture()
def created_routine(client):
r = client.post(
"/routines", json={"routine_date": "2026-02-26", "part_of_day": "am"}
)
assert r.status_code == 201
return r.json()