Initial commit: backend API, data models, and test suite
FastAPI backend for personal health and skincare data with MCP export. Includes SQLModel models for products, inventory, medications, lab results, routines, and skin condition snapshots. Pytest suite with 111 tests running on SQLite in-memory (no PostgreSQL required). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
8f7d893a63
32 changed files with 6282 additions and 0 deletions
87
backend/tests/conftest.py
Normal file
87
backend/tests/conftest.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import os
|
||||
|
||||
# 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 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 client(session):
|
||||
"""TestClient using the per-test session for every request."""
|
||||
|
||||
def _override():
|
||||
yield session
|
||||
|
||||
app.dependency_overrides[get_session] = _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",
|
||||
"routine_role": "seal",
|
||||
"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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue