left4me/l4d2web/tests/test_alembic_migrations.py
mwiegand 43dc9b0ccf
feat(l4d2-web): script overlay schema — add overlay.script + last_build_status, drop globals tables
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:33:04 +02:00

96 lines
3.1 KiB
Python

"""Tests for the alembic migration history.
The 0005 migration adds `script` and `last_build_status` columns to `overlays`,
drops the global_overlay_* tables, and wipes legacy l4d2center_maps/cedapug_maps
overlay rows. This module pins those behaviors.
"""
from pathlib import Path
import pytest
from alembic import command
from alembic.config import Config
from sqlalchemy import create_engine, inspect, text
_ALEMBIC_DIR = Path(__file__).resolve().parents[1] / "alembic"
def _alembic_config(db_url: str) -> Config:
cfg = Config()
cfg.set_main_option("script_location", str(_ALEMBIC_DIR))
cfg.set_main_option("sqlalchemy.url", db_url)
return cfg
@pytest.fixture
def db_url(tmp_path, monkeypatch):
path = tmp_path / "alembic.db"
url = f"sqlite:///{path}"
monkeypatch.setenv("DATABASE_URL", url)
yield url
def test_upgrade_0005_adds_script_columns(db_url) -> None:
cfg = _alembic_config(db_url)
command.upgrade(cfg, "0004_drop_legacy_external_overlay_type")
engine = create_engine(db_url)
with engine.begin() as conn:
# Seed legacy global-type overlay rows that the migration must wipe.
conn.execute(
text(
"INSERT INTO overlays (name, path, type, created_at, updated_at) "
"VALUES ('legacy-l4d2center', '1', 'l4d2center_maps', "
"'2026-01-01', '2026-01-01')"
)
)
conn.execute(
text(
"INSERT INTO overlays (name, path, type, created_at, updated_at) "
"VALUES ('legacy-cedapug', '2', 'cedapug_maps', "
"'2026-01-01', '2026-01-01')"
)
)
conn.execute(
text(
"INSERT INTO overlays (name, path, type, created_at, updated_at) "
"VALUES ('keep-workshop', '3', 'workshop', "
"'2026-01-01', '2026-01-01')"
)
)
command.upgrade(cfg, "0005_script_overlays")
inspector = inspect(engine)
overlay_cols = {c["name"]: c for c in inspector.get_columns("overlays")}
assert "script" in overlay_cols
assert "last_build_status" in overlay_cols
assert overlay_cols["script"]["nullable"] is False
assert overlay_cols["last_build_status"]["nullable"] is False
table_names = set(inspector.get_table_names())
assert "global_overlay_sources" not in table_names
assert "global_overlay_items" not in table_names
assert "global_overlay_item_files" not in table_names
with engine.connect() as conn:
rows = conn.execute(
text("SELECT name, type FROM overlays ORDER BY name")
).all()
assert rows == [("keep-workshop", "workshop")]
defaults = conn.execute(
text(
"SELECT script, last_build_status FROM overlays "
"WHERE name = 'keep-workshop'"
)
).one()
assert defaults == ("", "")
def test_downgrade_0005_skipped() -> None:
"""Per the project convention (see 0004) destructive migrations are
intentionally one-way; do not test or maintain a downgrade."""
pytest.skip("0005 is one-way: globals data is gone after upgrade")