Files
slop-game-opus5.5/tests/test_deploy_zip.py
T
2026-09-24 17:57:54 +02:00

87 lines
3.0 KiB
Python

"""Tests für das Upload-Paket (scripts/build_deploy_zip.py).
Prüft, dass das Paket vollständig ist, keine Geheimnisse oder Caches enthält, nur
„/“ als Pfadtrenner nutzt und nach dem Entpacken wie auf cPanel startet.
"""
from __future__ import annotations
import importlib.util
import os
import subprocess
import sys
import zipfile
from pathlib import Path
from types import ModuleType
from app.config import PROJECT_ROOT
def _load_builder() -> ModuleType:
spec = importlib.util.spec_from_file_location(
"build_deploy_zip", PROJECT_ROOT / "scripts" / "build_deploy_zip.py"
)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def test_zip_contains_everything_the_server_needs(tmp_path: Path) -> None:
target = tmp_path / "paket.zip"
names = _load_builder().build_zip(target)
with zipfile.ZipFile(target) as archive:
archived = set(archive.namelist())
assert archived == set(names)
for required in (
"passenger_wsgi.py",
"requirements.txt",
"app/__init__.py",
"app/templates/index.html",
"app/static/js/main.js",
"app/static/js/lib/phaser.min.js",
"app/static/assets/sprites/president.svg",
):
assert required in archived, required
def test_zip_has_no_secrets_caches_or_backslashes(tmp_path: Path) -> None:
target = tmp_path / "paket.zip"
names = _load_builder().build_zip(target)
assert all("\\" not in name for name in names)
assert not any(name == ".env" or name.startswith("instance/") for name in names)
assert not any("__pycache__" in name or name.endswith(".pyc") for name in names)
assert not any(name.startswith(("tests/", "node_modules/", ".venv/")) for name in names)
def test_unpacked_zip_starts_like_on_cpanel(tmp_path: Path) -> None:
"""Das entpackte Paket allein reicht: passenger_wsgi importiert die App und liefert Seiten."""
target = tmp_path / "paket.zip"
_load_builder().build_zip(target)
deploy_root = tmp_path / "glory_defense"
with zipfile.ZipFile(target) as archive:
archive.extractall(deploy_root)
env = {k: v for k, v in os.environ.items() if not k.startswith(("GLORY_", "SECRET_KEY"))}
env["SECRET_KEY"] = "deploy-test"
script = (
"import runpy\n"
f"app = runpy.run_path({str(deploy_root / 'passenger_wsgi.py')!r})['application']\n"
"c = app.test_client()\n"
"print(c.get('/').status_code, c.get('/static/js/lib/phaser.min.js').status_code,"
" c.get('/api/highscores').status_code)\n"
)
result = subprocess.run(
[sys.executable, "-c", script],
cwd=tmp_path,
env=env,
capture_output=True,
text=True,
timeout=60,
check=False,
)
assert result.returncode == 0, result.stderr
assert result.stdout.strip() == "200 200 200"
# Datenbank entsteht im entpackten Projekt, nicht im Arbeitsverzeichnis.
assert (deploy_root / "instance" / "glory_defense.sqlite3").exists()