from __future__ import annotations import pytest from tests.api.conftest import assert_meta, assert_provenance, value def test_rankings_list(get): body = get("/rankings").json() assert_meta(body) assert body["items"][0]["featured"] is True assert {"gdp", "life-expectancy"} <= {i["id"] for i in body["items"]} assert all(i["ranking_eligible"] for i in body["items"]) def test_ranking_table(get): body = get("/rankings/gdp-per-capita?limit=3").json() assert body["year_used"] == 2024 and body["years_available"][0] == 1990 and body["n"] == 8 and body["sort"] == "desc" rows = body["rows"] assert [r["rank"] for r in rows] == [1, 2, 3] and rows[0]["country"]["id"] == "JPN" and rows[0]["rank_world"] == 1 assert rows[0]["value"] == pytest.approx(value("JPN", "gdp-per-capita", 2024)) assert rows[0]["change_1y"]["pct"] == pytest.approx(3.0) and rows[0]["change_10y"]["pct"] == pytest.approx(34.39, abs=0.01) assert len(rows[0]["sparkline"]) == 30 and rows[0]["sparkline"][-1][0] == 2024 assert_provenance(rows[0]["provenance"]) page2 = get("/rankings/gdp-per-capita?limit=3&offset=3").json() assert page2["rows"][0]["rank"] == 4 asc = get("/rankings/gdp-per-capita?sort=asc&limit=1").json() assert asc["rows"][0]["country"]["id"] == "IND" # lower-is-better default sort ascending infl = get("/rankings/inflation?limit=8").json() assert infl["sort"] == "asc" and infl["rows"][0]["value"] <= infl["rows"][-1]["value"] # nearest year fallback assert get("/rankings/gdp-per-capita?year=2030").json()["year_used"] == 2024 y2000 = get("/rankings/gdp-per-capita?year=2000&limit=1").json() assert y2000["year_used"] == 2000 and y2000["rows"][0]["year"] == 2000 get("/rankings/nothing", status=404) def test_ranking_group(get): body = get("/rankings/unemployment-rate?group=g7&limit=10").json() assert body["group"]["id"] == "g7" and body["n"] == 5 and [r["rank"] for r in body["rows"]] == [1, 2, 3, 4, 5] assert body["rows"][0]["country"]["id"] == "JPN" # lowest unemployment in fixture assert body["rows"][0]["rank_world"] >= 1 and body["rows"][0]["n_world"] == 8 def test_ranking_history(get): body = get("/rankings/gdp-per-capita/history?countries=CAN,usa&from=2020").json() assert [c["id"] for c in body["countries"]] == ["CAN", "USA"] and body["years"] == [2020, 2021, 2022, 2023, 2024] assert body["series"]["CAN"][-1]["year"] == 2024 and 1 <= body["series"]["CAN"][-1]["rank"] <= 8 get("/rankings/gdp-per-capita/history?countries=XXX", status=404) def test_series_bundle(get): body = get("/series?country=CAN,FRA&indicator=gdp,inflation&from=2020&to=2024").json() assert_meta(body) assert body["n"] == 4 s = body["series"][0] assert s["indicator"]["id"] == "gdp" and s["country"]["id"] == "CAN" and [v["year"] for v in s["values"]] == list(range(2020, 2025)) assert_provenance(s["values"][0]["provenance"]) get("/series?country=CAN&indicator=nope", status=404) get("/series?country=CAN", status=422) def test_compare_modes(get): body = get("/compare?countries=CAN,USA,FRA&indicators=gdp,gdp-per-capita&from=2000&to=2024").json() assert_meta(body) assert body["mode"] == "absolute" and len(body["series"]) == 6 and [c["id"] for c in body["countries"]] == ["CAN", "USA", "FRA"] idx = get("/compare?countries=CAN,USA&indicators=gdp&mode=index100&from=2000").json() s = idx["series"][0] assert s["transform"]["applied"] and s["transform"]["base_year"] == 2000 and s["values"][0]["value"] == pytest.approx(100.0) assert s["values"][1]["value"] == pytest.approx(value("CAN", "gdp", 2001) / value("CAN", "gdp", 2000) * 100) assert s["unit"].startswith("index") pc = get("/compare?countries=CAN&indicators=gdp,gdp-per-capita&mode=per-capita&from=2024&to=2024").json() gdp_pc, gpc = pc["series"] assert gdp_pc["transform"]["applied"] and gdp_pc["values"][0]["value"] == pytest.approx(value("CAN", "gdp-per-capita", 2024)) assert gpc["transform"]["applied"] is False # already per-capita pct = get("/compare?countries=CAN&indicators=gdp&mode=pct&from=2020&to=2022").json()["series"][0] assert pct["values"][0]["value"] is None and pct["values"][1]["value"] == pytest.approx( (value("CAN", "gdp", 2021) / value("CAN", "gdp", 2020) - 1) * 100) get("/compare?countries=CAN&indicators=gdp&mode=weird", status=422) get("/compare?countries=CAN,XXX&indicators=gdp", status=404) def test_compare_snapshot(get): body = get("/compare/snapshot?countries=CAN,USA&topic=economy").json() assert body["topic"]["id"] == "economy" and [c["id"] for c in body["countries"]] == ["CAN", "USA"] row = next(r for r in body["rows"] if r["indicator"]["id"] == "gdp-per-capita") assert row["values"]["CAN"]["has_data"] and row["best"] == "USA" assert_provenance(row["values"]["CAN"]["provenance"]) missing = next(r for r in body["rows"] if r["indicator"]["id"] == "gdp-growth") assert missing["values"]["CAN"]["has_data"] default = get("/compare/snapshot?countries=CAN").json() assert default["topic"] is None and default["rows"][0]["indicator"]["id"] == "population" def test_compare_download(client): r = client.get("/api/v1/compare/download.csv?countries=CAN,USA&indicators=gdp&from=2023&include_forecast=false") assert r.status_code == 200 lines = [l for l in r.text.splitlines() if l and not l.startswith("#")] assert len(lines) - 1 == 4 and "series_code" in lines[0] j = client.get("/api/v1/compare/download.json?countries=CAN&indicators=gdp&from=2024&to=2024&include_forecast=false").json() assert j["n"] == 1 and j["rows"][0]["value"] == pytest.approx(value("CAN", "gdp", 2024))