58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
import os
|
|
import secrets
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
os.environ.setdefault("JUMPHOST_ENV", "development")
|
|
os.environ.setdefault("JUMPHOST_DEV_KEK", secrets.token_hex(32))
|
|
os.environ.setdefault("JUMPHOST_DEV_SESSION_SECRET", secrets.token_hex(32))
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
import pytest # noqa: E402
|
|
from httpx import ASGITransport, AsyncClient # noqa: E402
|
|
|
|
|
|
@pytest.fixture()
|
|
def tmp_data_dir(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("JUMPHOST_DATA_DIR", str(tmp_path))
|
|
return tmp_path
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _reset_rate_limiter():
|
|
"""login_rate_limiter (app/security/rate_limit.py) ist bewusst ein
|
|
Prozess-weiter In-Memory-Singleton (siehe Konzept/Docstring dort) --
|
|
genau das wird hier durch die Tests bestaetigt (test_source_ip_rate_limit_*).
|
|
Damit sich einzelne Tests nicht gegenseitig ueber ihr Kontingent
|
|
beeinflussen, wird der Zustand vor JEDEM Test zurueckgesetzt."""
|
|
from app.security.rate_limit import login_rate_limiter
|
|
|
|
login_rate_limiter._events.clear()
|
|
yield
|
|
login_rate_limiter._events.clear()
|
|
|
|
|
|
@pytest.fixture()
|
|
async def client(tmp_data_dir):
|
|
# app.config.settings ist ein Modul-Singleton, der beim ERSTEN Import des
|
|
# Prozesses einmalig aus der Umgebung gelesen wird (siehe app/config.py) --
|
|
# spaetere Aenderungen von JUMPHOST_DATA_DIR je Test wirken sich darauf
|
|
# nicht mehr aus. Fuer Testisolation wird daher die (immer gleiche)
|
|
# DB-Datei vor jedem Test explizit zurueckgesetzt statt sich auf einen
|
|
# neuen Datenpfad pro Test zu verlassen.
|
|
from app.main import app
|
|
from app.config import settings
|
|
|
|
for suffix in ("", "-wal", "-shm"):
|
|
p = settings.data_dir / f"jumphost.db{suffix}"
|
|
if p.exists():
|
|
p.unlink()
|
|
|
|
transport = ASGITransport(app=app)
|
|
# https:// Base-URL, da unsere Session-Cookies "Secure" gesetzt haben
|
|
# (Konzept 6.2) und httpx' Cookie-Jar dies wie ein Browser respektiert.
|
|
async with AsyncClient(transport=transport, base_url="https://testserver") as ac:
|
|
async with app.router.lifespan_context(app):
|
|
yield ac
|