8380b1d2cc
serve/server.py is now 69 lines — app factory, middleware, and router
registration only.
New modules:
deps.py (168 lines) — module-level globals + auth dependency functions
models.py (85 lines) — all Pydantic request/response models
tasks.py (136 lines) — background workers and job tracker
routers/ — one file per domain (10 routers, ~2750 lines total)
auth.py, me.py, admin.py, activities.py, uploads.py,
segments.py, strava.py, garmin.py, ideas.py, feed.py
cli.py updated to set globals on deps instead of server.
88 new regression tests in tests/serve/ cover auth guards and key
behaviours for every router; 294 total passing after the split.
86 lines
3.2 KiB
Python
86 lines
3.2 KiB
Python
"""Pre-split regression tests for /api/activity/* routes."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
AID = "2024-01-01T080000Z-test-ride"
|
|
|
|
|
|
def _make_activity(tmp_data, activity_id: str = AID) -> None:
|
|
acts = tmp_data / "alice" / "activities"
|
|
acts.mkdir(parents=True, exist_ok=True)
|
|
detail = {
|
|
"id": activity_id,
|
|
"title": "Test Ride",
|
|
"sport": "cycling",
|
|
"started_at": "2024-01-01T08:00:00Z",
|
|
"distance_m": 10000.0,
|
|
"duration_s": 3600,
|
|
"elevation_gain_m": 100.0,
|
|
}
|
|
(acts / f"{activity_id}.json").write_text(json.dumps(detail))
|
|
|
|
|
|
class TestGetActivity:
|
|
def test_unauthenticated_returns_401(self, client: TestClient):
|
|
assert client.get(f"/api/activity/{AID}").status_code == 401
|
|
|
|
def test_missing_activity_returns_404(self, user_client: TestClient):
|
|
assert user_client.get(f"/api/activity/{AID}").status_code == 404
|
|
|
|
def test_returns_activity_data(self, user_client: TestClient, tmp_data):
|
|
_make_activity(tmp_data)
|
|
r = user_client.get(f"/api/activity/{AID}")
|
|
assert r.status_code == 200
|
|
assert r.json()["id"] == AID
|
|
|
|
def test_invalid_id_returns_400(self, user_client: TestClient):
|
|
assert user_client.get("/api/activity/../../evil").status_code in (400, 404, 422)
|
|
|
|
|
|
class TestEditActivity:
|
|
def test_unauthenticated_returns_401(self, client: TestClient):
|
|
assert client.post(f"/api/activity/{AID}", json={}).status_code == 401
|
|
|
|
def test_missing_activity_returns_404(self, user_client: TestClient):
|
|
assert user_client.post(f"/api/activity/{AID}", json={}).status_code == 404
|
|
|
|
def test_edit_title(self, user_client: TestClient, tmp_data):
|
|
_make_activity(tmp_data)
|
|
r = user_client.post(f"/api/activity/{AID}", json={"title": "New Title"})
|
|
assert r.status_code == 200
|
|
|
|
|
|
class TestDeleteActivity:
|
|
def test_unauthenticated_returns_401(self, client: TestClient):
|
|
assert client.delete(f"/api/activity/{AID}").status_code == 401
|
|
|
|
|
|
class TestActivityImages:
|
|
def test_unauthenticated_returns_401(self, client: TestClient):
|
|
assert client.get(f"/api/activity/{AID}/images").status_code == 401
|
|
assert client.delete(f"/api/activity/{AID}/images/photo.jpg").status_code == 401
|
|
|
|
def test_get_images_empty(self, user_client: TestClient, tmp_data):
|
|
_make_activity(tmp_data)
|
|
r = user_client.get(f"/api/activity/{AID}/images")
|
|
assert r.status_code == 200
|
|
assert r.json() == {"images": []}
|
|
|
|
|
|
class TestGeojsonTimeseries:
|
|
def test_geojson_unauthenticated_returns_401(self, client: TestClient):
|
|
assert client.get(f"/api/activity/{AID}/geojson").status_code == 401
|
|
|
|
def test_timeseries_unauthenticated_returns_401(self, client: TestClient):
|
|
assert client.get(f"/api/activity/{AID}/timeseries").status_code == 401
|
|
|
|
def test_geojson_missing_returns_404(self, user_client: TestClient):
|
|
assert user_client.get(f"/api/activity/{AID}/geojson").status_code == 404
|
|
|
|
def test_timeseries_missing_returns_404(self, user_client: TestClient):
|
|
assert user_client.get(f"/api/activity/{AID}/timeseries").status_code == 404
|