"""Правка завершённой партии игроком: история чинится после изменений в группе.""" from __future__ import annotations from fastapi.testclient import TestClient from tests.conftest import add_group_member, create_finished_match, csrf_headers, login def _exp_id(client: TestClient, code: str) -> int: return next(e["id"] for e in client.get("/api/expansions").json() if e["code"] == code) def _played(client: TestClient, engine) -> tuple[dict, int, int, int, dict]: """Партия «Аня против Бори» в группе с обоими дополнениями.""" me = login(client, "Аня") fw, fv = _exp_id(client, "forgotten_worlds"), _exp_id(client, "forsaken_voids") gid = client.post( "/api/groups", json={"name": "Группа", "expansion_ids": [fw, fv]}, headers=csrf_headers(client), ).json()["id"] b = add_group_member(engine, gid, "Боря") factions = {f["code"]: f["id"] for f in client.get(f"/api/groups/{gid}/factions").json()} mid = create_finished_match( client, gid, [ {"user_id": me["id"], "faction_id": factions["orks"], "place": 1}, {"user_id": b, "faction_id": factions["tau"], "place": 2}, ], )["id"] return me, gid, b, mid, factions def _swap_places(client: TestClient, mid: int, me_id: int, b: int, factions: dict) -> dict: detail = client.get(f"/api/matches/{mid}").json() fid = {p["user_id"]: p["faction_id"] for p in detail["participants"]} return { "participants": [ {"user_id": me_id, "faction_id": fid[me_id], "place": 2}, {"user_id": b, "faction_id": fid[b], "place": 1}, ], "expected_version": detail["version"], } def test_edit_after_expansion_disabled(client: TestClient, engine): """Дополнение выключили — партия на Тау всё равно правится. Регрессия: правка проверяла фракции по ТЕКУЩЕМУ набору группы, и партия, сыгранная на фракции из отключённого дополнения, становилась неисправимой.""" me, gid, b, mid, factions = _played(client, engine) off = client.put( f"/api/groups/{gid}/expansions", json={"expansion_ids": [_exp_id(client, "forsaken_voids")]}, headers=csrf_headers(client), ) assert off.status_code == 200, off.text r = client.patch( f"/api/matches/{mid}", json=_swap_places(client, mid, me["id"], b, factions), headers=csrf_headers(client), ) assert r.status_code == 200, r.text places = {p["user_id"]: p["place"] for p in client.get(f"/api/matches/{mid}").json()["participants"]} assert places[b] == 1 and places[me["id"]] == 2 def test_edit_after_player_left_group(client: TestClient, engine): """Игрока убрали из группы — партия с ним всё равно правится.""" me, gid, b, mid, factions = _played(client, engine) out = client.delete(f"/api/groups/{gid}/members/{b}", headers=csrf_headers(client)) assert out.status_code == 200, out.text r = client.patch( f"/api/matches/{mid}", json=_swap_places(client, mid, me["id"], b, factions), headers=csrf_headers(client), ) assert r.status_code == 200, r.text def test_edit_rejects_new_outsider_and_unavailable_faction(client: TestClient, engine): """Послабление — только для того, что уже в партии. Вписать нового игрока не из группы или фракцию, которой в партии не было и у группы нет, по-прежнему нельзя: иначе в историю можно занести что угодно.""" me, gid, b, mid, factions = _played(client, engine) stranger = client.post( "/api/auth/dev/users", json={"nickname": "Чужак"}, headers=csrf_headers(client) ).json() detail = client.get(f"/api/matches/{mid}").json() fid = {p["user_id"]: p["faction_id"] for p in detail["participants"]} bad_user = client.patch( f"/api/matches/{mid}", json={ "participants": [ {"user_id": me["id"], "faction_id": fid[me["id"]], "place": 1}, {"user_id": stranger["id"], "faction_id": fid[b], "place": 2}, ] }, headers=csrf_headers(client), ) assert bad_user.status_code == 422, bad_user.text # Выключаем дополнение и пробуем поставить ЕГО фракцию, которой в партии не было. assert client.put( f"/api/groups/{gid}/expansions", json={"expansion_ids": [_exp_id(client, "forsaken_voids")]}, headers=csrf_headers(client), ).status_code == 200 bad_faction = client.patch( f"/api/matches/{mid}", json={ "participants": [ {"user_id": me["id"], "faction_id": factions["necrons"], "place": 1}, {"user_id": b, "faction_id": fid[b], "place": 2}, ] }, headers=csrf_headers(client), ) assert bad_faction.status_code == 422, bad_faction.text def test_create_match_still_validated(client: TestClient, engine): """Создание партии не ослабло: посторонний игрок по-прежнему отклоняется.""" me, gid, b, mid, factions = _played(client, engine) stranger = client.post( "/api/auth/dev/users", json={"nickname": "Чужак2"}, headers=csrf_headers(client) ).json() r = client.post( "/api/matches", json={ "group_id": gid, "participants": [ {"user_id": me["id"], "faction_id": factions["orks"]}, {"user_id": stranger["id"], "faction_id": factions["eldar"]}, ], }, headers=csrf_headers(client), ) assert r.status_code == 422, r.text