186 lines
No EOL
8.5 KiB
GDScript
186 lines
No EOL
8.5 KiB
GDScript
extends SceneTree
|
|
## test_ui_layout (Karte t_eaccbfed, U1 UI-Fundament): prüft das Unity-artige
|
|
## Layout, das AUSSCHLIESSLICH aus der Registry (src/ui/panels/registry.gd)
|
|
## gebaut wird.
|
|
##
|
|
## Geprüft wird:
|
|
## 1. Alle Registry-Bereiche existieren GENAU EINMAL im Baum (kein Doppel,
|
|
## kein Verwaister) und als Tab mit dem Registry-Titel erreichbar sind.
|
|
## 2. Die Tab-Gruppen stimmen: rechts = 5 Tabs, links = 1, unten = 2.
|
|
## 3. Assets-Bereich unten vorhanden (Objekt-Bibliothek mit Suche + Kacheln).
|
|
## 4. Theme gesetzt (theme/editor_theme.tres als einzige Farbquelle).
|
|
## 5. Keine doppelten Node-Namen im UI-Subbaum.
|
|
## 6. main.gd hält die bekannten Werkzeug-/Test-Referenzen (Vertrag).
|
|
|
|
const UIScaleStepDefault := 0 # (Lesbarkeit; Stufen sind nicht Teil dieser Suite)
|
|
|
|
var _fails := 0
|
|
var _oks := 0
|
|
|
|
|
|
func _check(cond: bool, what: String) -> void:
|
|
if cond:
|
|
_oks += 1
|
|
print(" ok: ", what)
|
|
else:
|
|
_fails += 1
|
|
print(" FAIL: ", what)
|
|
|
|
|
|
func _init() -> void:
|
|
print("Testgruppe: Layout aus der Registry")
|
|
var scene: PackedScene = load("res://scenes/main.tscn")
|
|
var main: Control = scene.instantiate()
|
|
root.add_child(main)
|
|
await process_frame
|
|
await process_frame
|
|
await process_frame
|
|
|
|
# --- 1b. GRÖSSEN-GEGENPROBE (Operator-Nachbesserung 20.10.) ----------------
|
|
# Sly-Befund „Was ist das? Damit kann man nicht mehr arbeiten!" — Ursache war
|
|
# reine FLÄCHE, nicht Aufbau: die Werkzeugleiste erbte von EditorPanel
|
|
# (VBoxContainer) und wurde dadurch selbst senkrecht → ~11 Knöpfe untereinander,
|
|
# das 3D-Fenster auf einen Briefmarken-Streifen gedrückt. Aufbau-Tests sagen
|
|
# dazu nichts — deshalb hier echte Größen.
|
|
# WICHTIG (Lektion 20.10.): im headless-Testlauf ist das Wurzelfenster nur
|
|
# 64 px hoch — Prozentwerte gegen main.size.y sind deshalb Unsinn. Geprüft
|
|
# wird ABSOLUT, und zwar die Größe, die den Fehler ausmachte.
|
|
# main ist als Control typisiert — Skript-Eigenschaften über get() lesen
|
|
# (sonst Parse-Fehler „Invalid access to property"). Namen mit probe_*,
|
|
# damit sie nicht mit Variablen der übrigen Suite kollidieren.
|
|
var probe_top: Control = main.get("ui_top_bar")
|
|
_check(probe_top != null, "Größenprobe: Top-Bar vorhanden")
|
|
if probe_top != null:
|
|
_check(probe_top.size.y <= 80.0,
|
|
"Leiste ist EINE Zeile (Höhe %.0f px, Grenze 80)" % probe_top.size.y)
|
|
var probe_center: Control = main.find_child("MainSplit", true, false)
|
|
_check(probe_center != null, "Größenprobe: Mittelbereich (MainSplit) vorhanden")
|
|
if probe_center != null:
|
|
_check(probe_center.size.y >= 120.0,
|
|
"Mittelbereich hat echte Höhe (%.0f px, min 120)" % probe_center.size.y)
|
|
|
|
# --- 1. Registry-Tabelle ist die Autorität --------------------------------
|
|
var registry_script: GDScript = load("res://src/ui/panels/registry.gd")
|
|
var ids: Array = []
|
|
for entry in registry_script.PANELS:
|
|
ids.append(str(entry["id"]))
|
|
_check(ids.size() == registry_script.PANELS.size(), "Registry: IDs eindeutig (keine Duplikate in der Tabelle)")
|
|
_check(not ids.is_empty(), "Registry: mindestens ein Bereich angemeldet")
|
|
|
|
# --- 2. Jeder Bereich GENAU EINMAL im Baum, als Tab mit Titel --------------
|
|
var tabs_by_name: Dictionary = {} # gruppe → TabContainer
|
|
var stack: Array = [main]
|
|
var all_controls: Array = []
|
|
while not stack.is_empty():
|
|
var n: Node = stack.pop_back()
|
|
if n is TabContainer:
|
|
all_controls.append(n)
|
|
stack.append_array(n.get_children())
|
|
for tab in all_controls:
|
|
for c in (tab as TabContainer).get_children():
|
|
var cid := str(c.name)
|
|
if cid in ids:
|
|
_check(tabs_by_name.get(cid) == null, "Bereich '%s' GENAU EINMAL im Baum" % cid)
|
|
tabs_by_name[cid] = c
|
|
# Tab-Titel = Registry-Titel (erreichbar/erkennbar)
|
|
var title: String = ""
|
|
for entry in registry_script.PANELS:
|
|
if str(entry["id"]) == cid:
|
|
title = str(entry["titel"])
|
|
var idx: int = c.get_index()
|
|
_check(tab.get_tab_title(idx) == title,
|
|
"Tab '%s' trägt Registry-Titel '%s'" % [cid, title])
|
|
for wanted in ids:
|
|
_check(tabs_by_name.get(wanted) != null, "Bereich '%s' aus der Registry im Baum" % wanted)
|
|
|
|
# --- 3. Tab-Gruppen --------------------------------------------------------
|
|
var right: TabContainer = main.get("ui_right_panel")
|
|
var left: TabContainer = main.get("ui_left_panel")
|
|
var bottom: Node = main.get("ui_dock_bottom")
|
|
_check(right != null and right is TabContainer, "rechte Spalte ist ein TabContainer")
|
|
_check(left != null and left is TabContainer, "linke Spalte ist ein TabContainer (U2-vorbereitet)")
|
|
_check(bottom != null and bottom is VSplitContainer, "unten: VSplit (größenverstellbar)")
|
|
if right != null:
|
|
# Registry-getrieben (T3, Karte t_aaff5dcc): die erwartete Tab-Anzahl
|
|
# kommt aus der Registry-Tabelle (gruppe "rechts") statt hart kodiert —
|
|
# neue Panels melden sich dort an und der Check bleibt wahr.
|
|
var expected_right := 0
|
|
for entry in registry_script.PANELS:
|
|
if str(entry["gruppe"]) == "rechts":
|
|
expected_right += 1
|
|
_check(right.get_child_count() == expected_right,
|
|
"rechts: %d Tabs aus der Registry — hat %d" % [expected_right, right.get_child_count()])
|
|
_check(right.get_tab_count() == right.get_child_count(),
|
|
"rechts: alle Bereiche als Tab in der Leiste erreichbar (Titel je Bereich)")
|
|
for i in right.get_tab_count():
|
|
_check(not str(right.get_tab_title(i)).is_empty(),
|
|
"rechts: Tab %d hat sichtbaren Titel" % i)
|
|
if left != null:
|
|
_check(left.get_child_count() == 1, "links: 1 Tab (Map-Inhalt) — hat %d" % left.get_child_count())
|
|
if bottom is VSplitContainer and bottom.get_child_count() == 2:
|
|
var bchild: Node = bottom.get_child(1) # PanelContainer mit BottomTabs
|
|
var btab: TabContainer = null
|
|
for gc in bchild.get_children():
|
|
if gc is TabContainer:
|
|
btab = gc
|
|
_check(btab != null, "unten: TabContainer für Assets gefunden")
|
|
if btab != null:
|
|
_check(btab.get_child_count() == 2, "unten: 2 Tabs (Bibliothek/Werkzeuge) — hat %d" % btab.get_child_count())
|
|
|
|
# --- 4. Assets-Bereich unten vollständig -----------------------------------
|
|
var assets: Control = tabs_by_name.get("assets")
|
|
_check(assets != null, "Objekt-Bibliothek (Assets) unten vorhanden")
|
|
if assets != null:
|
|
_check(assets.get("library_search") != null, "Bibliothek: Suchfeld vorhanden")
|
|
_check(assets.get("library_open_all_btn") != null and assets.get("library_close_all_btn") != null,
|
|
"Bibliothek: „Alle auf/zu“ vorhanden")
|
|
var lib_box: Node = assets.get("library_box")
|
|
_check(lib_box != null and lib_box.get_child_count() > 0, "Bibliothek: Kachel-/Gruppen-Liste gefüllt")
|
|
var tools: Control = tabs_by_name.get("werkzeuge")
|
|
_check(tools != null and tools.get("grid_check") != null, "Objekt-Werkzeuge: Raster-Snap erhalten (nichts verschwindet)")
|
|
|
|
# --- 5. Theme als einzige Farbquelle ----------------------------------------
|
|
var theme_res: Theme = main.get("theme")
|
|
_check(theme_res != null, "Theme gesetzt (main.theme)")
|
|
if theme_res != null:
|
|
_check(int(theme_res.default_font_size) >= 14, "Theme: Grundschrift ≥ 14 px (Lesbarkeits-Grundsatz)")
|
|
var theme_file: Theme = load("res://theme/editor_theme.tres")
|
|
_check(theme_res == theme_file, "Theme: main nutzt theme/editor_theme.tres (eine Quelle)")
|
|
|
|
# --- 6. Keine doppelten Node-Namen unter main -------------------------------
|
|
var names: Dictionary = {}
|
|
var dupes: Array = []
|
|
var stack2: Array = [main]
|
|
while not stack2.is_empty():
|
|
var n2: Node = stack2.pop_back()
|
|
var key := str(n2.name) + "#" + n2.get_class()
|
|
if key in names:
|
|
dupes.append(str(n2.name))
|
|
names[key] = true
|
|
stack2.append_array(n2.get_children())
|
|
_check(dupes.is_empty(), "keine doppelten Node-Namen im UI — %s" % str(dupes))
|
|
|
|
# --- 7. Koordinator-Vertrag (Werkzeuge/Tests greifen weiter auf main.*) ----
|
|
for ref_name in ["toolbar_mod", "status_mod", "selection_mod", "map_mod",
|
|
"terrain_mod", "check_mod", "tree_mod", "assets_mod",
|
|
"content_tree", "status_label", "prop_name", "library_search",
|
|
"terrain_radius_slider", "terrain_size_btn_medium"]:
|
|
_check(main.get(ref_name) != null, "main.%s vorhanden" % ref_name)
|
|
|
|
# --- 8. Lauf-Modus (T1) bleibt erreichbar: Toolbar-Aktion aus Registry ------
|
|
var tb: Control = main.get("toolbar_mod")
|
|
var found_test_btn := false
|
|
if tb != null:
|
|
for entry in registry_script.ACTIONS:
|
|
if str(entry["id"]) == "karte_testen":
|
|
var btn: Node = tb.find_child(str(entry["id"]), true, false)
|
|
found_test_btn = btn != null
|
|
_check(found_test_btn, "Lauf-Modus: „▶ Karte testen“ in der Toolbar (Registry-Aktion)")
|
|
|
|
print("CHECKS: %d FAILURES: %d" % [_oks + _fails, _fails])
|
|
if _fails > 0:
|
|
print("UI_LAYOUT_TEST_FAIL")
|
|
quit(1)
|
|
else:
|
|
print("ALL OK: %d checks" % (_oks + _fails))
|
|
quit(0) |