71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
"""Tests for the places API (spec 2026-08-21)."""
|
|||
|
|
|
||
|
|
import numpy as np
|
||
|
|
import pandas as pd
|
||
|
|
import pytest
|
||
|
|
from fastapi.testclient import TestClient
|
||
|
|
|
||
|
|
|
||
|
|
def _schools_df() -> pd.DataFrame:
|
||
|
|
base = {
|
||
|
|
"local_authority": "Essex", "school_type": "Academy",
|
||
|
|
"phase": "Primary", "year": 202425, "ofsted_grade": 2.0,
|
||
|
|
"ofsted_date": None, "attainment_8_score": np.nan,
|
||
|
|
"town": "Brentwood", "postcode": "CM13 1AA", "status": "Open",
|
||
|
|
"address": "1 Test Street", "latitude": 51.6, "longitude": 0.3,
|
||
|
|
}
|
||
|
|
return pd.DataFrame([
|
||
|
|
{**base, "urn": 100000 + i, "school_name": f"Brentwood School {i}",
|
||
|
|
"rwm_expected_pct": 50.0 + i}
|
||
|
|
for i in range(6)
|
||
|
|
])
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.fixture()
|
||
|
|
def client(monkeypatch):
|
||
|
|
from backend import app as app_module
|
||
|
|
|
||
|
|
monkeypatch.setattr(app_module, "load_school_data", _schools_df)
|
||
|
|
monkeypatch.setattr(app_module, "load_latest_school_data", _schools_df)
|
||
|
|
monkeypatch.setattr(app_module, "_place_registry", None)
|
||
|
|
return TestClient(app_module.app, raise_server_exceptions=False)
|
||
|
|
|
||
|
|
|
||
|
|
def test_registry_lists_each_published_place(client):
|
||
|
|
body = client.get("/api/places").json()
|
||
|
|
slugs = {(p["kind"], p["slug"]) for p in body["places"]}
|
||
|
|
assert ("town", "brentwood") in slugs
|
||
|
|
assert ("authority", "essex") in slugs
|
||
|
|
assert ("outcode", "cm13") in slugs
|
||
|
|
|
||
|
|
|
||
|
|
def test_registry_carries_a_count_per_place(client):
|
||
|
|
body = client.get("/api/places").json()
|
||
|
|
town = next(p for p in body["places"] if p["slug"] == "brentwood")
|
||
|
|
assert town["count"] == 6
|
||
|
|
|
||
|
|
|
||
|
|
def test_place_detail_returns_its_schools_ranked(client):
|
||
|
|
body = client.get("/api/places/town/brentwood").json()
|
||
|
|
assert body["place"]["name"] == "Brentwood"
|
||
|
|
scores = [s["rwm_expected_pct"] for s in body["schools"]]
|
||
|
|
assert scores == sorted(scores, reverse=True)
|
||
|
|
|
||
|
|
|
||
|
|
def test_place_detail_carries_the_local_average(client):
|
||
|
|
body = client.get("/api/places/town/brentwood").json()
|
||
|
|
# 50..55 inclusive
|
||
|
|
assert body["averages"]["rwm_expected_pct"] == pytest.approx(52.5)
|
||
|
|
|
||
|
|
|
||
|
|
def test_phase_filter_narrows_the_school_list(client):
|
||
|
|
body = client.get("/api/places/town/brentwood?phase=secondary").json()
|
||
|
|
assert body["schools"] == []
|
||
|
|
|
||
|
|
|
||
|
|
def test_unknown_place_404s(client):
|
||
|
|
assert client.get("/api/places/town/atlantis").status_code == 404
|
||
|
|
|
||
|
|
|
||
|
|
def test_unknown_kind_404s(client):
|
||
|
|
assert client.get("/api/places/planet/mars").status_code == 404
|