slop game oder so
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
"""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 == []
|
||||
Reference in New Issue
Block a user