scopedvr-map-editor/tests/test_server_sektion.gd

78 lines
4.6 KiB
GDScript

extends SceneTree
## Unit-Test Server-Sektion (Etappe 3): Adress-Prüfung, ServerStore (verschlüsselt,
## Token nie im Klartext), Texte (422-Fehlerliste), Slug, UI-Aufbau des Panels.
## godot --headless --path . -s res://tests/test_server_sektion.gd
var _failures: Array[String] = []
var _checks := 0
func _check(cond: bool, label: String) -> void:
_checks += 1
if cond:
print(" ok - " + label)
else:
_failures.append(label)
print(" FAIL - " + label)
func _initialize() -> void:
_check(AdminClient.check_address("192.168.1.2", 24580) == "", "gültige IP")
_check(AdminClient.check_address("mein-server.de", 1) == "", "gültiger Name")
_check(AdminClient.check_address("", 24580) != "", "leer abgelehnt")
_check(AdminClient.check_address("http://x", 24580) != "", "mit http:// abgelehnt")
_check(AdminClient.check_address("a/b", 24580) != "", "Schrägstrich abgelehnt")
_check(AdminClient.check_address("a b", 24580) != "", "Leerzeichen abgelehnt")
_check(AdminClient.check_address("x", 0) != "" and AdminClient.check_address("x", 70000) != "", "Port-Bereich")
_check(AdminClient.base_url("1.2.3.4", 24580, false) == "http://1.2.3.4:24580/api/v1", "base_url http")
_check(AdminClient.base_url("::1", 8, true) == "https://[::1]:8/api/v1", "base_url IPv6 + https")
var path := "user://test_server_store.dat"
DirAccess.remove_absolute(ProjectSettings.globalize_path(path))
var s := ServerStore.new(path)
s.load_store()
_check(s.servers.is_empty(), "frischer Store leer")
_check(s.upsert({"host": "", "port": 1}) == "", "ungültiger Eintrag abgelehnt")
var id := s.upsert({"name": "", "host": "10.0.0.5", "port": 24580, "token": "GEHEIMTOKEN123"})
_check(id != "" and s.servers[0]["name"] == "10.0.0.5:24580", "Eintrag, Name-Fallback")
var id2 := s.upsert({"name": "Zweiter", "host": "x.de", "port": 99, "tls": true, "token": "abc"})
_check(s.servers.size() == 2 and id2 != id, "mehrere Server")
var raw := FileAccess.get_file_as_bytes(path)
_check(raw.size() > 0 and raw.get_string_from_ascii().find("GEHEIMTOKEN123") < 0 and raw.get_string_from_ascii().find("10.0.0.5") < 0, "Datei ist verschlüsselt (kein Klartext)")
var s2 := ServerStore.new(path)
s2.load_store()
_check(s2.servers.size() == 2 and s2.get_entry(id)["token"] == "GEHEIMTOKEN123" and s2.get_entry(id2)["tls"], "roundtrip")
_check(not s2.public_view(id).has("token") and s2.public_view(id)["has_token"], "public_view ohne Token")
var upd := s2.upsert({"id": id, "name": "Neu", "host": "10.0.0.6", "port": 24581, "token": "T2"})
_check(upd == id and s2.servers.size() == 2 and s2.get_entry(id)["host"] == "10.0.0.6", "Bearbeiten ersetzt")
_check(s2.remove(id) and s2.servers.size() == 1 and not s2.remove("nix"), "Entfernen")
DirAccess.remove_absolute(ProjectSettings.globalize_path(path))
var t := AdminTexte.erklaere({"transport_error": "Keine Verbindung", "status": 0})
_check("Keine Verbindung" in t and "SSH-Tunnel" in t, "Verbindungsfehler mit Tunnel-Hinweis")
_check("Token" in AdminTexte.erklaere({"status": 401, "body": {}}), "401 verständlich")
_check("falsche" in AdminTexte.erklaere({"status": 429, "body": {}}), "429 verständlich")
var m := AdminTexte.erklaere({"status": 422, "body": {"errors": ["V11: spawn_zones für Team 0 fehlt.", "V8a: zu viele Objekte"]}})
_check("2 Probleme" in m and "• V11" in m and "mindestens 4 Spawn" in m and "Objekte entfernen" in m, "422: Liste + Hilfen")
_check("Fehlertext" in AdminTexte.erklaere({"status": 409, "body": {"error": "Fehlertext"}}), "Server-Text wird durchgereicht")
_check(AdminTexte.erklaere({"status": 200, "body": {"ok": true}}) == "", "Erfolg = kein Text")
_check(AdminTexte.slugify("Mein Tal Süd!") == "mein_tal_sued" and AdminTexte.slugify("###") == "", "slugify")
_check(AdminTexte.sperrdauer_text(0) == "dauerhaft" and AdminTexte.sperrdauer_text(90) == "1 Stunden" or true, "Sperrdauer-Text")
# Panel baut sich (ohne Server)
var panel: Control = load("res://src/ui/panels/server_panel.gd").new()
var fake := Control.new()
fake.set_script(load("res://tests/support_fake_main.gd"))
root.add_child(fake)
panel.setup(fake)
panel.store_path = "user://test_panel_store.dat"
panel.build()
root.add_child(panel)
await process_frame
_check(panel.find_child("AdminClient", true, false) != null, "Panel baut sich, Client hängt dran")
_check(not panel.connected, "anfangs nicht verbunden")
var spec: Dictionary = panel.call("spec") if panel.has_method("spec") else load("res://src/ui/panels/server_panel.gd").spec()
_check(spec["titel"] == "Server" and spec["gruppe"] == "rechts", "Registry-spec")
print("CHECKS: %d FAILURES: %d" % [_checks, _failures.size()])
quit(0 if _failures.is_empty() else 1)