Files
2026-09-24 17:57:54 +02:00

120 lines
4.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Prüft Assets und Inhalte: Lizenzdokumentation vollständig, Verweise gültig,
SVGs harmlos, keine Namen aus anderen Spielen oder Filmen."""
from __future__ import annotations
import re
import xml.etree.ElementTree as ET
from pathlib import Path
import pytest
from app.config import PROJECT_ROOT
STATIC = PROJECT_ROOT / "app" / "static"
ASSETS = STATIC / "assets"
ASSETS_DOC = PROJECT_ROOT / "docs" / "ASSETS.md"
JS_ROOT = STATIC / "js"
#: Begriffe aus Helldivers bzw. Starship Troopers, die im Spiel nicht vorkommen dürfen
#: (Groß-/Kleinschreibung egal). Der allgemeine Tonfall darf inspiriert sein, Namen nicht.
FORBIDDEN_TERMS = [
"helldiver",
"super earth",
"super-erde",
"supererde",
"stratagem",
"hellpod",
"terminid",
"automaton",
"illuminate",
"managed democracy",
"gelenkte demokratie",
"liber-tea",
"would you like to know more",
"möchten sie mehr erfahren",
"mobile infantry",
"arachnid",
"federation",
"föderation",
"service guarantees citizenship",
"rico",
"klendathu",
]
def _asset_files() -> list[Path]:
return sorted(p for p in ASSETS.rglob("*") if p.is_file())
def test_asset_folder_is_not_empty() -> None:
assert _asset_files(), "Keine Assets gefunden"
@pytest.mark.parametrize("path", _asset_files(), ids=lambda p: p.relative_to(ASSETS).as_posix())
def test_every_asset_is_documented(path: Path) -> None:
documented = ASSETS_DOC.read_text(encoding="utf-8")
relative = path.relative_to(ASSETS).as_posix()
assert relative in documented, f"{relative} fehlt in docs/ASSETS.md"
def test_referenced_asset_files_exist() -> None:
manifest = (JS_ROOT / "systems" / "Assets.js").read_text(encoding="utf-8")
referenced = re.findall(r"file: '([^']+)'", manifest)
assert len(referenced) >= 15
missing = [f for f in referenced if not (ASSETS / f).is_file()]
assert missing == []
@pytest.mark.parametrize("path", sorted(ASSETS.rglob("*.svg")), ids=lambda p: p.name)
def test_svgs_are_well_formed_and_self_contained(path: Path) -> None:
source = path.read_text(encoding="utf-8")
root = ET.fromstring(source) # noqa: S314 – eigene, versionierte Dateien
assert root.tag.endswith("svg")
lowered = source.lower()
# Keine Skripte, keine externen Verweise: SVGs sollen reine Grafik sein.
assert "<script" not in lowered
assert "http://" not in lowered.replace("http://www.w3.org/2000/svg", "")
assert "https://" not in lowered
assert "<image" not in lowered
def test_phaser_is_vendored_locally() -> None:
phaser = JS_ROOT / "lib" / "phaser.min.js"
assert phaser.is_file()
assert phaser.stat().st_size > 500_000
head = phaser.read_text(encoding="utf-8", errors="ignore")[:100_000]
assert '"3.90.0"' in head or "3.90.0" in head
assert (JS_ROOT / "lib" / "PHASER_LICENSE.md").is_file()
def test_no_external_urls_in_page_or_scripts() -> None:
"""Das Spiel lädt nichts von fremden Servern (kein CDN, kein Tracking)."""
offenders = []
for path in [*JS_ROOT.rglob("*.js"), *(PROJECT_ROOT / "app" / "templates").rglob("*.html")]:
if "lib" in path.relative_to(STATIC if path.is_relative_to(STATIC) else PROJECT_ROOT).parts:
continue
text = path.read_text(encoding="utf-8")
for match in re.findall(r"""(?:src|href)=["'](https?://[^"']+)""", text):
offenders.append(f"{path.name}: {match}")
if re.search(r"""\b(?:import|fetch)\s*\(?\s*["']https?://""", text):
offenders.append(f"{path.name}: externer Import/Fetch")
assert offenders == []
def test_no_names_from_other_games_or_films() -> None:
sources = [
*JS_ROOT.rglob("*.js"),
*(PROJECT_ROOT / "app" / "templates").rglob("*.html"),
*ASSETS.rglob("*.svg"),
]
hits = []
for path in sources:
if "lib" in path.parts:
continue
text = path.read_text(encoding="utf-8").lower()
for term in FORBIDDEN_TERMS:
if re.search(rf"\b{re.escape(term)}\b", text):
hits.append(f"{path.relative_to(PROJECT_ROOT).as_posix()}: {term}")
assert hits == []