"""Статистика профиля: цифры сходятся с лидербордом, а главная не грузит историю лишний раз.""" from __future__ import annotations from fastapi.testclient import TestClient from app.services import stats_service from tests.conftest import add_group_member, create_finished_match, csrf_headers, login def _group_with_matches(client: TestClient, engine, games: int = 3) -> tuple[dict, int, int]: me = login(client, "Статист") exps = [e["id"] for e in client.get("/api/expansions").json()] gid = client.post( "/api/groups", json={"name": "Группа", "expansion_ids": exps}, headers=csrf_headers(client) ).json()["id"] p2 = add_group_member(engine, gid, "Соперник") fids = [f["id"] for f in client.get(f"/api/groups/{gid}/factions").json()] for i in range(games): # Чередуем победителя и берём разные фракции: средние и разбивка по фракциям # должны получиться нетривиальными, а фракции в партии не повторяться. winner_first = i % 2 == 0 mine, theirs = fids[(2 * i) % len(fids)], fids[(2 * i + 1) % len(fids)] create_finished_match( client, gid, [ {"user_id": me["id"], "faction_id": mine, "place": 1 if winner_first else 2}, {"user_id": p2, "faction_id": theirs, "place": 2 if winner_first else 1}, ], ) return me, gid, p2 def test_profile_numbers_match_leaderboard(client: TestClient, engine): """Профиль и лидерборд собирают итог разными путями: цифры обязаны совпадать.""" me, gid, p2 = _group_with_matches(client, engine, games=4) profile = client.get("/api/users/me/stats").json()["overall"] board = client.get("/api/stats/leaderboard").json() entry = next( e for e in board["entries"] + board["provisional"] if e["user_id"] == me["id"] ) for field in ("games", "wins", "win_rate", "avg_place", "score"): assert profile[field] == entry[field], field def test_home_loads_history_once(client: TestClient, engine, monkeypatch): """Главная грузит историю партий один раз: топ, профиль и итог активной группы считаются из неё. Без этой проверки лишняя загрузка тихо вернётся при правке витрин.""" me, gid, p2 = _group_with_matches(client, engine, games=2) client.put( "/api/users/me/active-group", json={"group_id": gid}, headers=csrf_headers(client) ) calls: list[int] = [] original = stats_service.load_history def spy(session): calls.append(1) return original(session) monkeypatch.setattr(stats_service, "load_history", spy) r = client.get("/api/home") assert r.status_code == 200, r.text assert len(calls) == 1 # Главная всё ещё показывает и профиль, и блок активной группы. body = r.json() assert body["profile"]["overall"]["games"] == 2 assert body["active_group"]["games"] == 2