80 lines
2.2 KiB
Python
80 lines
2.2 KiB
Python
"""Gemeinsame pytest-Fixtures: App mit temporärer Datenbank, Test-Client, Run-Tokens."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
from collections.abc import Callable, Iterator
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from flask import Flask
|
|
from flask.testing import FlaskClient
|
|
from itsdangerous.timed import TimestampSigner
|
|
|
|
from app import create_app
|
|
|
|
|
|
@pytest.fixture()
|
|
def db_path(tmp_path: Path) -> Path:
|
|
return tmp_path / "data" / "test.sqlite3"
|
|
|
|
|
|
@pytest.fixture()
|
|
def app(db_path: Path) -> Iterator[Flask]:
|
|
app = create_app(
|
|
{
|
|
"TESTING": True,
|
|
"SECRET_KEY": "test-secret-key",
|
|
"DATABASE_PATH": str(db_path),
|
|
"RATE_LIMIT_MAX_SUBMISSIONS": 5,
|
|
"RATE_LIMIT_WINDOW_SECONDS": 600,
|
|
}
|
|
)
|
|
yield app
|
|
|
|
|
|
@pytest.fixture()
|
|
def client(app: Flask) -> FlaskClient:
|
|
return app.test_client()
|
|
|
|
|
|
@pytest.fixture()
|
|
def issue_token(client: FlaskClient, monkeypatch: pytest.MonkeyPatch) -> Callable[..., str]:
|
|
"""Holt ein Run-Token über die API; ``started_ago`` simuliert eine bereits laufende Runde.
|
|
|
|
Die Signatur enthält den Ausgabezeitpunkt. Um eine lange Runde zu simulieren, ohne
|
|
wirklich zu warten, wird der Zeitstempel beim Signieren zurückdatiert.
|
|
"""
|
|
|
|
def _issue(started_ago: int = 0) -> str:
|
|
original = TimestampSigner.get_timestamp
|
|
monkeypatch.setattr(
|
|
TimestampSigner, "get_timestamp", lambda _self: int(time.time()) - started_ago
|
|
)
|
|
try:
|
|
response = client.post("/api/runs")
|
|
finally:
|
|
monkeypatch.setattr(TimestampSigner, "get_timestamp", original)
|
|
assert response.status_code == 201
|
|
return response.get_json()["run_token"]
|
|
|
|
return _issue
|
|
|
|
|
|
@pytest.fixture()
|
|
def valid_payload(issue_token: Callable[..., str]) -> Callable[..., dict]:
|
|
"""Erzeugt eine gültige Einreichung; einzelne Felder lassen sich überschreiben."""
|
|
|
|
def _payload(**overrides: object) -> dict:
|
|
payload: dict = {
|
|
"name": "Kadettin Ada",
|
|
"score": 1234,
|
|
"wave": 3,
|
|
"duration_s": 95,
|
|
"run_token": issue_token(started_ago=120),
|
|
}
|
|
payload.update(overrides)
|
|
return payload
|
|
|
|
return _payload
|