224 lines
6.2 KiB
Python
224 lines
6.2 KiB
Python
from uuid import uuid4
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from tests.conftest import TEST_ADMIN_TOKEN
|
|
|
|
BEARER_HEADERS = {"Authorization": f"Bearer {TEST_ADMIN_TOKEN}"}
|
|
|
|
|
|
def _create_segment(
|
|
client: TestClient,
|
|
title: str = "Test",
|
|
seg_type: str = "markdown",
|
|
) -> dict[str, object]:
|
|
resp = client.post(
|
|
"/api/segments",
|
|
json={"type": seg_type, "title": title},
|
|
headers=BEARER_HEADERS,
|
|
)
|
|
assert resp.status_code == 201
|
|
data: dict[str, object] = resp.json()
|
|
return data
|
|
|
|
|
|
# --- Segment route tests ---
|
|
|
|
|
|
def test_list_segments_empty(client: TestClient) -> None:
|
|
resp = client.get("/api/segments")
|
|
assert resp.status_code == 200
|
|
assert resp.json() == []
|
|
|
|
|
|
def test_create_segment(client: TestClient) -> None:
|
|
data = _create_segment(client, title="Intro")
|
|
assert "id" in data
|
|
assert data["title"] == "Intro"
|
|
assert data["type"] == "markdown"
|
|
assert data["sort_order"] == 0
|
|
|
|
|
|
def test_create_segment_unauthorized(client: TestClient) -> None:
|
|
resp = client.post("/api/segments", json={"type": "markdown", "title": "X"})
|
|
assert resp.status_code == 401
|
|
|
|
|
|
def test_create_segment_wrong_token(client: TestClient) -> None:
|
|
resp = client.post(
|
|
"/api/segments",
|
|
json={"type": "markdown", "title": "X"},
|
|
headers={"Authorization": "Bearer wrong-token"},
|
|
)
|
|
assert resp.status_code == 401
|
|
|
|
|
|
def test_create_segment_via_query_param(client: TestClient) -> None:
|
|
resp = client.post(
|
|
f"/api/segments?token={TEST_ADMIN_TOKEN}",
|
|
json={"type": "markdown", "title": "Query Auth"},
|
|
)
|
|
assert resp.status_code == 201
|
|
|
|
|
|
def test_get_segment(client: TestClient) -> None:
|
|
created = _create_segment(client, title="Fetch Me")
|
|
seg_id = created["id"]
|
|
resp = client.get(f"/api/segments/{seg_id}")
|
|
assert resp.status_code == 200
|
|
assert resp.json()["title"] == "Fetch Me"
|
|
|
|
|
|
def test_get_segment_not_found(client: TestClient) -> None:
|
|
resp = client.get(f"/api/segments/{uuid4()}")
|
|
assert resp.status_code == 404
|
|
|
|
|
|
def test_update_segment(client: TestClient) -> None:
|
|
created = _create_segment(client, title="Original")
|
|
seg_id = created["id"]
|
|
resp = client.patch(
|
|
f"/api/segments/{seg_id}",
|
|
json={"title": "Updated"},
|
|
headers=BEARER_HEADERS,
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["title"] == "Updated"
|
|
|
|
|
|
def test_update_segment_not_found(client: TestClient) -> None:
|
|
resp = client.patch(
|
|
f"/api/segments/{uuid4()}",
|
|
json={"title": "Nope"},
|
|
headers=BEARER_HEADERS,
|
|
)
|
|
assert resp.status_code == 404
|
|
|
|
|
|
def test_update_segment_unauthorized(client: TestClient) -> None:
|
|
created = _create_segment(client, title="NoAuth")
|
|
seg_id = created["id"]
|
|
resp = client.patch(
|
|
f"/api/segments/{seg_id}",
|
|
json={"title": "Hacked"},
|
|
)
|
|
assert resp.status_code == 401
|
|
|
|
|
|
def test_delete_segment(client: TestClient) -> None:
|
|
created = _create_segment(client, title="Delete Me")
|
|
seg_id = created["id"]
|
|
resp = client.delete(f"/api/segments/{seg_id}", headers=BEARER_HEADERS)
|
|
assert resp.status_code == 204
|
|
resp2 = client.get(f"/api/segments/{seg_id}")
|
|
assert resp2.status_code == 404
|
|
|
|
|
|
def test_delete_segment_not_found(client: TestClient) -> None:
|
|
resp = client.delete(f"/api/segments/{uuid4()}", headers=BEARER_HEADERS)
|
|
assert resp.status_code == 404
|
|
|
|
|
|
def test_delete_segment_unauthorized(client: TestClient) -> None:
|
|
created = _create_segment(client, title="NoAuthDel")
|
|
seg_id = created["id"]
|
|
resp = client.delete(f"/api/segments/{seg_id}")
|
|
assert resp.status_code == 401
|
|
|
|
|
|
def test_reorder_segments(client: TestClient) -> None:
|
|
a = _create_segment(client, title="A")
|
|
b = _create_segment(client, title="B")
|
|
c = _create_segment(client, title="C")
|
|
|
|
resp = client.put(
|
|
"/api/segments/reorder",
|
|
json={"segment_ids": [c["id"], a["id"], b["id"]]},
|
|
headers=BEARER_HEADERS,
|
|
)
|
|
assert resp.status_code == 200
|
|
|
|
listing = client.get("/api/segments").json()
|
|
titles = [s["title"] for s in listing]
|
|
assert titles == ["C", "A", "B"]
|
|
|
|
|
|
def test_reorder_segments_invalid_ids(client: TestClient) -> None:
|
|
resp = client.put(
|
|
"/api/segments/reorder",
|
|
json={"segment_ids": [str(uuid4())]},
|
|
headers=BEARER_HEADERS,
|
|
)
|
|
assert resp.status_code == 400
|
|
|
|
|
|
def test_reorder_segments_unauthorized(client: TestClient) -> None:
|
|
resp = client.put(
|
|
"/api/segments/reorder",
|
|
json={"segment_ids": []},
|
|
)
|
|
assert resp.status_code == 401
|
|
|
|
|
|
# --- Site route tests ---
|
|
|
|
|
|
def test_get_site_title_default(client: TestClient) -> None:
|
|
resp = client.get("/api/site")
|
|
assert resp.status_code == 200
|
|
assert resp.json()["title"] == "Untitled Site"
|
|
|
|
|
|
def test_update_site_title(client: TestClient) -> None:
|
|
resp = client.put(
|
|
"/api/site",
|
|
json={"title": "My Course"},
|
|
headers=BEARER_HEADERS,
|
|
)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["title"] == "My Course"
|
|
|
|
resp2 = client.get("/api/site")
|
|
assert resp2.json()["title"] == "My Course"
|
|
|
|
|
|
def test_update_site_title_unauthorized(client: TestClient) -> None:
|
|
resp = client.put("/api/site", json={"title": "Hacked"})
|
|
assert resp.status_code == 401
|
|
|
|
|
|
# --- Auth route tests ---
|
|
|
|
|
|
def test_auth_verify_valid_bearer(client: TestClient) -> None:
|
|
resp = client.get("/api/auth/verify", headers=BEARER_HEADERS)
|
|
assert resp.status_code == 200
|
|
assert resp.json() == {"valid": True}
|
|
|
|
|
|
def test_auth_verify_valid_query_param(client: TestClient) -> None:
|
|
resp = client.get(f"/api/auth/verify?token={TEST_ADMIN_TOKEN}")
|
|
assert resp.status_code == 200
|
|
assert resp.json() == {"valid": True}
|
|
|
|
|
|
def test_auth_verify_invalid(client: TestClient) -> None:
|
|
resp = client.get(
|
|
"/api/auth/verify",
|
|
headers={"Authorization": "Bearer wrong-token"},
|
|
)
|
|
assert resp.status_code == 401
|
|
|
|
|
|
def test_auth_verify_no_token(client: TestClient) -> None:
|
|
resp = client.get("/api/auth/verify")
|
|
assert resp.status_code == 401
|
|
|
|
|
|
# --- Health test ---
|
|
|
|
|
|
def test_health(client: TestClient) -> None:
|
|
resp = client.get("/api/health")
|
|
assert resp.status_code == 200
|
|
assert resp.json()["status"] == "ok"
|