diff --git a/backend/app/seed/reference_data.py b/backend/app/seed/reference_data.py index 48c72a0..89d4611 100644 --- a/backend/app/seed/reference_data.py +++ b/backend/app/seed/reference_data.py @@ -33,7 +33,13 @@ FACTIONS: list[tuple[str, str, str, int]] = [ def seed_reference_data(session: Session) -> None: - """Создаёт/обновляет дополнения и фракции. Безопасно вызывать многократно.""" + """Создаёт/обновляет дополнения и фракции. Безопасно вызывать многократно. + + Идёт при каждом старте (entrypoint.sh, lifespan dev), поэтому не перетирает то, что + правят руками: имя существующей фракции меняет админка (admin_service.rename_faction), + и после создания записи источник правды для него — БД (#72). Имя из кода получает + только новая фракция; поправить имя существующей — админкой или миграцией. + Служебные поля (дополнение, порядок) и всё у дополнений синхронизируются с кодом.""" code_to_expansion: dict[str, Expansion] = {} for code, name_ru, is_base, order in EXPANSIONS: @@ -61,7 +67,6 @@ def seed_reference_data(session: Session) -> None: ) session.add(fac) else: - fac.name_ru = name_ru fac.expansion_id = expansion.id # type: ignore[assignment] fac.sort_order = order diff --git a/backend/tests/test_admin_extra.py b/backend/tests/test_admin_extra.py index 9d603f0..53f7997 100644 --- a/backend/tests/test_admin_extra.py +++ b/backend/tests/test_admin_extra.py @@ -2,7 +2,11 @@ from __future__ import annotations from fastapi.testclient import TestClient +from sqlalchemy.pool import StaticPool +from sqlmodel import Session, SQLModel, create_engine, select +from app.models import Faction +from app.seed.reference_data import FACTIONS, seed_reference_data from tests.conftest import add_group_member, create_finished_match, csrf_headers, login, start_match @@ -205,6 +209,37 @@ def test_admin_rename_faction_system_wide(client: TestClient, make_admin, engine assert ap["faction_name"] == "Орки WAAAGH" +def test_faction_rename_survives_restart_seeding(client: TestClient, make_admin, engine): + """Сидинг идёт при каждом старте (entrypoint.sh, lifespan) и не должен откатывать + имя, заданное админом (#72).""" + login(client, "Кто-то") + orks = next(f for f in client.get("/api/factions").json() if f["code"] == "orks") + _admin_login(client, make_admin) + r = client.patch( + f"/api/admin/factions/{orks['id']}", + json={"name_ru": "Орки WAAAGH"}, + headers=csrf_headers(client), + ) + assert r.status_code == 200, r.text + + with Session(engine) as s: + seed_reference_data(s) # то же, что делает рестарт + assert s.get(Faction, orks["id"]).name_ru == "Орки WAAAGH" + + +def test_seeding_is_complete_and_idempotent(): + """Пустая БД: фракции из кода создаются со своими именами, повтор ничего не ломает.""" + engine = create_engine( + "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool + ) + SQLModel.metadata.create_all(engine) + with Session(engine) as s: + seed_reference_data(s) + seed_reference_data(s) + names = {f.code: f.name_ru for f in s.exec(select(Faction)).all()} + assert names == {code: name for code, name, _exp, _order in FACTIONS} + + def test_admin_delete_group_with_matches_is_conflict(client: TestClient, make_admin, engine): """Группу с партиями удалять нельзя — но ответ должен быть внятным 409.