109 lines
3.3 KiB
Python
109 lines
3.3 KiB
Python
|
|
"""GET /api/training-units: Keyset-Parameter-Validierung (ohne DB-Zwang)."""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import os
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from fastapi.testclient import TestClient
|
||
|
|
|
||
|
|
os.environ.setdefault("SKIP_DB_MIGRATE", "1")
|
||
|
|
|
||
|
|
from auth import require_auth
|
||
|
|
from main import app
|
||
|
|
from tenant_context import TenantContext, get_tenant_context
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.fixture
|
||
|
|
def client() -> TestClient:
|
||
|
|
return TestClient(app)
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.fixture(autouse=True)
|
||
|
|
def _clear_overrides() -> None:
|
||
|
|
yield
|
||
|
|
app.dependency_overrides.pop(require_auth, None)
|
||
|
|
app.dependency_overrides.pop(get_tenant_context, None)
|
||
|
|
|
||
|
|
|
||
|
|
def _tenant() -> TenantContext:
|
||
|
|
return TenantContext(
|
||
|
|
profile_id=1,
|
||
|
|
global_role="trainer",
|
||
|
|
effective_club_id=None,
|
||
|
|
club_ids=frozenset(),
|
||
|
|
memberships=[],
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def test_list_training_units_keyset_incomplete_returns_400(client: TestClient) -> None:
|
||
|
|
app.dependency_overrides[require_auth] = lambda: {"profile_id": 1, "role": "trainer"}
|
||
|
|
app.dependency_overrides[get_tenant_context] = _tenant
|
||
|
|
r = client.get(
|
||
|
|
"/api/training-units",
|
||
|
|
params={"cursor_id": "42"},
|
||
|
|
headers={"X-Auth-Token": "test"},
|
||
|
|
)
|
||
|
|
assert r.status_code == 400
|
||
|
|
assert "cursor_planned_date" in r.json().get("detail", "").lower()
|
||
|
|
|
||
|
|
|
||
|
|
def test_list_training_units_keyset_without_limit_returns_400(client: TestClient) -> None:
|
||
|
|
app.dependency_overrides[require_auth] = lambda: {"profile_id": 1, "role": "trainer"}
|
||
|
|
app.dependency_overrides[get_tenant_context] = _tenant
|
||
|
|
r = client.get(
|
||
|
|
"/api/training-units",
|
||
|
|
params={
|
||
|
|
"cursor_id": "1",
|
||
|
|
"cursor_planned_date": "2026-05-10",
|
||
|
|
},
|
||
|
|
headers={"X-Auth-Token": "test"},
|
||
|
|
)
|
||
|
|
assert r.status_code == 400
|
||
|
|
assert "limit" in r.json().get("detail", "").lower()
|
||
|
|
|
||
|
|
|
||
|
|
def test_list_training_units_keyset_bad_date_returns_400(client: TestClient) -> None:
|
||
|
|
app.dependency_overrides[require_auth] = lambda: {"profile_id": 1, "role": "trainer"}
|
||
|
|
app.dependency_overrides[get_tenant_context] = _tenant
|
||
|
|
r = client.get(
|
||
|
|
"/api/training-units",
|
||
|
|
params={
|
||
|
|
"cursor_id": "1",
|
||
|
|
"cursor_planned_date": "not-a-date",
|
||
|
|
"limit": "10",
|
||
|
|
},
|
||
|
|
headers={"X-Auth-Token": "test"},
|
||
|
|
)
|
||
|
|
assert r.status_code == 400
|
||
|
|
|
||
|
|
|
||
|
|
def test_list_training_units_keyset_bad_time_returns_400(client: TestClient) -> None:
|
||
|
|
app.dependency_overrides[require_auth] = lambda: {"profile_id": 1, "role": "trainer"}
|
||
|
|
app.dependency_overrides[get_tenant_context] = _tenant
|
||
|
|
r = client.get(
|
||
|
|
"/api/training-units",
|
||
|
|
params={
|
||
|
|
"cursor_id": "1",
|
||
|
|
"cursor_planned_date": "2026-05-10",
|
||
|
|
"cursor_planned_time": "25:99",
|
||
|
|
"limit": "10",
|
||
|
|
},
|
||
|
|
headers={"X-Auth-Token": "test"},
|
||
|
|
)
|
||
|
|
assert r.status_code == 400
|
||
|
|
assert "cursor_planned_time" in r.json().get("detail", "").lower()
|
||
|
|
|
||
|
|
|
||
|
|
def test_list_training_units_keyset_time_without_id_returns_400(client: TestClient) -> None:
|
||
|
|
app.dependency_overrides[require_auth] = lambda: {"profile_id": 1, "role": "trainer"}
|
||
|
|
app.dependency_overrides[get_tenant_context] = _tenant
|
||
|
|
r = client.get(
|
||
|
|
"/api/training-units",
|
||
|
|
params={
|
||
|
|
"cursor_planned_time": "18:00",
|
||
|
|
"limit": "10",
|
||
|
|
},
|
||
|
|
headers={"X-Auth-Token": "test"},
|
||
|
|
)
|
||
|
|
assert r.status_code == 400
|