import pytest from fastapi.testclient import TestClient from sqlalchemy import create_engine, event from sqlalchemy.orm import Session from sqlalchemy.pool import StaticPool from app.db import Base, get_session import app.models # noqa: F401 ensures all ORM tables are registered on Base.metadata @pytest.fixture def db(): engine = create_engine( "sqlite://", poolclass=StaticPool, connect_args={"check_same_thread": False}, ) # SQLite does not enforce foreign keys unless told to per-connection. Turn # enforcement on so the tests catch FK violations (missing cascades) the # same way Postgres would in production. @event.listens_for(engine, "connect") def _fk_pragma(dbapi_conn, _): cur = dbapi_conn.cursor() cur.execute("PRAGMA foreign_keys=ON") cur.close() Base.metadata.create_all(engine) with Session(engine) as session: yield session @pytest.fixture def client(db, monkeypatch): monkeypatch.setenv("FB_API_KEY", "test-key") from app.config import get_settings get_settings.cache_clear() from app.auth import hash_password monkeypatch.setenv("FB_GUI_PASSWORD_HASH", hash_password("geheim")) get_settings.cache_clear() from app.main import app def _override_get_session(): yield db app.dependency_overrides[get_session] = _override_get_session with TestClient(app) as c: yield c app.dependency_overrides.clear() get_settings.cache_clear() @pytest.fixture def env_file(tmp_path): """Erzeugt eine .env-Datei im create_pod_finance.sh-Format (single-quoted KEY='value') mit einem initialen Passwort+Hash. Liefert (Pfad, Passwort) fuer Tests der Admin-Passwortaenderung (Ausbaustufe 4 Task 2), die die Laufzeit-.env-Lesung/-Schreibung ueber FB_ENV_FILE gegen eine tmp_path statt der echten Container-.env pruefen.""" from app.auth import hash_password path = tmp_path / ".env" password = "geheim123" path.write_text( f"FB_PASSWORD='{password}'\n" f"FB_GUI_PASSWORD_HASH='{hash_password(password)}'\n" ) return path, password @pytest.fixture def client_with_env_file(db, env_file, monkeypatch): """Wie `client`, aber der GUI-Passwort-Hash kommt NICHT aus der FB_GUI_PASSWORD_HASH-Umgebungsvariable, sondern wird zur Laufzeit aus der ueber FB_ENV_FILE referenzierten Datei gelesen (der Pfad, den change_password() in-place ueberschreibt).""" path, _password = env_file monkeypatch.setenv("FB_API_KEY", "test-key") monkeypatch.delenv("FB_GUI_PASSWORD_HASH", raising=False) monkeypatch.setenv("FB_ENV_FILE", str(path)) from app.config import get_settings get_settings.cache_clear() from app.auth import _hash_cache _hash_cache.clear() from app.main import app def _override_get_session(): yield db app.dependency_overrides[get_session] = _override_get_session with TestClient(app) as c: yield c, env_file[1] app.dependency_overrides.clear() get_settings.cache_clear() _hash_cache.clear()