martian7777
feat: implement backend core with ORM models, authentication, and AI-driven telemetry diagnostics
e5be436
Raw
History Blame Contribute Delete
3.02 kB
"""Pytest fixtures: in-memory async SQLite DB, app override, HTTP client.
Tests run fully offline — no PostgreSQL, no OpenRouter — using an in-memory
SQLite database and the built-in mock AI explainer.
"""
from __future__ import annotations
import os
from collections.abc import AsyncGenerator
import pytest_asyncio
# Force a deterministic, secret-free test configuration before app import.
os.environ.setdefault("ENVIRONMENT", "testing")
os.environ.setdefault("JWT_SECRET_KEY", "test-secret-key-please-ignore")
os.environ.setdefault("OPENROUTER_API_KEY", "") # ensure mock explainer
os.environ.setdefault("DATABASE_URL", "sqlite+aiosqlite:///:memory:")
from httpx import ASGITransport, AsyncClient # noqa: E402
from sqlalchemy.ext.asyncio import ( # noqa: E402
AsyncSession,
async_sessionmaker,
create_async_engine,
)
from sqlalchemy.pool import StaticPool # noqa: E402
from app.core.database import get_db # noqa: E402
from app.main import app # noqa: E402
from app.models import Base # noqa: E402
@pytest_asyncio.fixture
async def engine() -> AsyncGenerator:
eng = create_async_engine(
"sqlite+aiosqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
async with eng.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield eng
await eng.dispose()
@pytest_asyncio.fixture
async def session_factory(engine):
return async_sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False)
@pytest_asyncio.fixture
async def client(session_factory) -> AsyncGenerator[AsyncClient, None]:
async def override_get_db() -> AsyncGenerator[AsyncSession, None]:
async with session_factory() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
app.dependency_overrides[get_db] = override_get_db
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
yield ac
app.dependency_overrides.clear()
@pytest_asyncio.fixture
async def auth_client(client: AsyncClient) -> AsyncClient:
"""An AsyncClient with a registered+logged-in user's bearer token set."""
email = "tester@example.com"
password = "supersecret123"
await client.post(
"/api/v1/auth/register",
json={"email": email, "password": password, "full_name": "Tester"},
)
resp = await client.post(
"/api/v1/auth/login",
data={"username": email, "password": password},
)
token = resp.json()["access_token"]
client.headers.update({"Authorization": f"Bearer {token}"})
return client
@pytest_asyncio.fixture
async def machine_id(auth_client: AsyncClient) -> str:
resp = await auth_client.post(
"/api/v1/machines",
json={"name": "Pump-1", "type": "pump", "location": "Plant A"},
)
return resp.json()["id"]