Anleitung mit Hervorhebungen, Rückgängig, Kapitel 2, Herausforderungen, Fallen, Wiederverbinden, CI
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QPgKvy5W9WRNFHjkm5QsHx
This commit is contained in:
136
tests/ui_test.gd
136
tests/ui_test.gd
@@ -154,8 +154,8 @@ func _ready() -> void:
|
||||
add_child(main)
|
||||
await frames(3)
|
||||
for t in [test_menu_und_regeln, test_booster, test_deckbau, test_gegnerauswahl, test_einstellungen,
|
||||
test_erfolge, test_kampagne, test_werkstatt, test_sprache, test_anleitung, test_hotseat,
|
||||
test_netzwerk, test_kampf.bind(2, 3), test_kampf_abbrechen]:
|
||||
test_erfolge, test_kampagne, test_werkstatt, test_sprache, test_anleitung, test_herausforderung,
|
||||
test_hotseat, test_netzwerk, test_kampf.bind(2, 3), test_kampf_abbrechen]:
|
||||
await ensure_menu()
|
||||
await t.call()
|
||||
for suffix in ["", ".bak", ".corrupt"]:
|
||||
@@ -358,6 +358,17 @@ func test_gegnerauswahl() -> void:
|
||||
await give_up()
|
||||
|
||||
|
||||
## Kampf verlassen: nach Spielende über den Ergebnisdialog, sonst per Aufgeben.
|
||||
func leave_battle() -> void:
|
||||
var scr = screen()
|
||||
if scr is BattleScreen and scr.game != null and scr.game.winner != "":
|
||||
await frames(2)
|
||||
await click(find_button("Zurück zum Menü"))
|
||||
check(screen() is MenuScreen, "Ergebnisdialog führt ins Menü")
|
||||
else:
|
||||
await give_up()
|
||||
|
||||
|
||||
func give_up() -> void:
|
||||
var scr = screen()
|
||||
await clear_mulligan(scr)
|
||||
@@ -390,6 +401,11 @@ func test_einstellungen() -> void:
|
||||
func test_erfolge() -> void:
|
||||
await click(find_button("Erfolge"))
|
||||
check(screen() is AchievementsScreen, "Erfolge geöffnet")
|
||||
var csv := "user://statistik.csv"
|
||||
if FileAccess.file_exists(csv):
|
||||
DirAccess.remove_absolute(ProjectSettings.globalize_path(csv))
|
||||
await click(find_button("Statistik exportieren"))
|
||||
check(FileAccess.file_exists(csv) and "Gespeichert" in screen().export_label.text, "Statistik exportiert")
|
||||
await shot("14_erfolge")
|
||||
await click(find_button("Zurück"))
|
||||
check(screen() is MenuScreen, "zurück im Menü")
|
||||
@@ -427,6 +443,26 @@ func test_werkstatt() -> void:
|
||||
check(screen() is MenuScreen, "zurück im Menü")
|
||||
|
||||
|
||||
func test_herausforderung() -> void:
|
||||
await click(find_button("Herausforderung"))
|
||||
var scr = screen()
|
||||
check(scr is ChallengeScreen, "Herausforderung geöffnet")
|
||||
var ch := Challenge.current()
|
||||
var allowed := Challenge.deck_allowed(ch, main.profile.deck_cards()) == ""
|
||||
check(find_button("Antreten").disabled == not allowed, "Antreten je nach Deck")
|
||||
await shot("28_herausforderung")
|
||||
if allowed:
|
||||
await click(find_button("Antreten"))
|
||||
var b = screen()
|
||||
check(b is BattleScreen and b.challenge == ch and b.game.opponents.size() == ch.n_opp, "Herausforderungskampf")
|
||||
var everyone: String = ch.rules.get("everyone_perk", "")
|
||||
check(everyone == "" or b.game.players.all(func(p): return everyone in p.perks), "Regel gilt für alle")
|
||||
await give_up()
|
||||
else:
|
||||
await click(find_button("Zurück"))
|
||||
check(screen() is MenuScreen, "zurück im Menü")
|
||||
|
||||
|
||||
func test_hotseat() -> void:
|
||||
await click(find_button("Lokal zu mehreren"))
|
||||
var scr = screen()
|
||||
@@ -458,7 +494,7 @@ func test_hotseat() -> void:
|
||||
await clear_mulligan(b)
|
||||
check(b.hero_panels.size() == 3 and not b.hero_panels.has(cur), "drei andere am Tisch")
|
||||
await shot("19_hotseat_kampf")
|
||||
await give_up()
|
||||
await leave_battle()
|
||||
|
||||
|
||||
func test_sprache() -> void:
|
||||
@@ -469,10 +505,12 @@ func test_sprache() -> void:
|
||||
await frames(2)
|
||||
check(TranslationServer.get_locale().begins_with("en") and main.profile.settings.language == "en", "Sprache auf Englisch")
|
||||
check(TranslationServer.translate("Zurück") == "Back" and TranslationServer.translate("Einzelspieler") == "Single player", "Übersetzung geladen")
|
||||
check(TranslationServer.translate("Zug %d · Du bist dran") == "Turn %d · Your turn" and TranslationServer.translate("Nicht genug Energie") == "Not enough energy", "dynamische Texte übersetzt")
|
||||
check(find_button("Back") != null, "Knöpfe übersetzt")
|
||||
await shot("26_englisch")
|
||||
await click(find_button("Back"))
|
||||
check(find_button("Single player") != null and find_button("Settings") != null, "Menü auf Englisch")
|
||||
check(screen().coins_label.text.begins_with("Coins:"), "zusammengesetzte Texte übersetzt")
|
||||
await click(find_button("Settings"))
|
||||
var scr2 = screen()
|
||||
scr2.language.select(0)
|
||||
@@ -506,14 +544,36 @@ func test_anleitung() -> void:
|
||||
if g.human.hand[i].is_creature() and g.human.hand[i].cost == 1:
|
||||
idx = i
|
||||
break
|
||||
check(idx < 0 or scr.highlight_layer.get_child_count() >= 1, "spielbare Wesen hervorgehoben")
|
||||
if idx >= 0:
|
||||
var played_id: String = g.human.hand[idx].id
|
||||
await key(KEY_1 + idx)
|
||||
check(g.human.board.size() == 1, "Wesen per Taste gespielt")
|
||||
check(scr.tutorial_step == 1, "Schritt 2 nach dem Ausspielen")
|
||||
check(scr.highlight_layer.get_child_count() == 1 and scr.highlight_layer.get_child(0).get_rect().intersects(scr.b_end.get_rect()), "Zug-beenden-Knopf hervorgehoben")
|
||||
# Rückgängig: Wesen zurück auf die Hand
|
||||
check(scr.b_undo.visible, "Rückgängig angeboten")
|
||||
var energy: int = g.human.energy
|
||||
await click(scr.b_undo)
|
||||
g = scr.game
|
||||
check(g.human.board.is_empty() and g.human.hand.any(func(c): return c.id == played_id) and g.human.energy == energy + 1, "Rückgängig stellt Hand und Energie her")
|
||||
check(not scr.b_undo.visible and g.log.back() == "Rückgängig.", "Rückgängig verbraucht")
|
||||
await key(KEY_1 + idx)
|
||||
check(g.human.board.size() == 1, "erneut gespielt")
|
||||
await shot("22_anleitung")
|
||||
scr.ai_delay = 0.75
|
||||
await key(KEY_SPACE)
|
||||
check(g.current() != g.human or g.turn >= 2, "Zug per Leertaste beendet")
|
||||
await wait_for_human(scr)
|
||||
await frames(2)
|
||||
check(scr.b_skip.visible and not scr.b_end.visible, "Überspringen-Knopf während des Gegnerzugs")
|
||||
await click(scr.b_skip)
|
||||
var w := 0
|
||||
while g.current() != g.human and g.winner == "" and w < 120:
|
||||
await frames(1)
|
||||
w += 1
|
||||
check(g.current() == g.human and w < 60, "Gegnerzug übersprungen (%d Bilder)" % w)
|
||||
scr.ai_delay = 0.0
|
||||
await clear_mulligan(scr)
|
||||
check(scr.tutorial_step >= 2 or idx < 0, "Schritt 3 im zweiten Zug")
|
||||
var step_before: int = scr.tutorial_step
|
||||
await click(scr.b_tut_next)
|
||||
@@ -532,6 +592,8 @@ func test_netzwerk() -> void:
|
||||
check(scr is LobbyScreen, "Lobby geöffnet")
|
||||
await click(find_button("Spiel eröffnen"))
|
||||
check(main.net.is_host and main.net.connected, "Spiel eröffnet")
|
||||
if FileAccess.file_exists("user://bot_quit"):
|
||||
DirAccess.remove_absolute(ProjectSettings.globalize_path("user://bot_quit"))
|
||||
var args := ["--headless", "--path", ProjectSettings.globalize_path("res://"), "tests/net_bot.tscn", "--", "--ip=127.0.0.1", "--name=Bot"]
|
||||
var pid := OS.create_process(OS.get_executable_path(), args)
|
||||
check(pid > 0, "Bot-Prozess gestartet")
|
||||
@@ -559,19 +621,46 @@ func test_netzwerk() -> void:
|
||||
check(b.game.turn >= 3 and b.game.winner == "", "mehrere Runden gespielt, Partie läuft (Zug %d)" % b.game.turn)
|
||||
check(b.game.log.any(func(l): return l.begins_with("Bot spielt") or l.begins_with("Bot behält") or l.begins_with("Bot tauscht")), "Bot hat gehandelt")
|
||||
await shot("24_netzwerk_kampf")
|
||||
OS.kill(pid)
|
||||
# Bot verlässt geordnet: Platz bleibt frei, Züge werden übersprungen
|
||||
var quit_file := "user://bot_quit"
|
||||
var f := FileAccess.open(quit_file, FileAccess.WRITE)
|
||||
f.store_string("x")
|
||||
f.close()
|
||||
var w3 := 0
|
||||
while b.game.winner == "" and w3 < 1500:
|
||||
while main.net.waiting.is_empty() and w3 < 600:
|
||||
await frames(1)
|
||||
w3 += 1
|
||||
if b.game.winner != "":
|
||||
check(b.game.winner == "human" and b.game.log.any(func(l): return "verlassen" in l), "Trennung des Bots zählt als Aufgabe")
|
||||
await frames(2)
|
||||
check(b.overlay.visible, "Spielende angezeigt")
|
||||
await click(find_button("Zurück zum Menü"))
|
||||
else:
|
||||
print("HINWEIS: Bot-Trennung nach 25 s noch nicht erkannt, Aufgeben stattdessen")
|
||||
await give_up()
|
||||
check(main.net.waiting.has("Bot") and b.game.log.any(func(l): return "Verbindung verloren" in l), "Platz wird freigehalten")
|
||||
var turn_before: int = b.game.turn
|
||||
for i in 2:
|
||||
await clear_mulligan(b)
|
||||
if b.game.current() == b.perspective and b.game.winner == "":
|
||||
await click(b.b_end)
|
||||
var w4 := 0
|
||||
while b.game.current() != b.perspective and b.game.winner == "" and w4 < 300:
|
||||
await frames(1)
|
||||
w4 += 1
|
||||
check(b.game.turn >= turn_before + 1 and b.game.log.any(func(l): return "übersprungen" in l), "Züge des fehlenden Spielers werden übersprungen")
|
||||
DirAccess.remove_absolute(ProjectSettings.globalize_path(quit_file))
|
||||
await frames(5)
|
||||
var pid2 := OS.create_process(OS.get_executable_path(), args)
|
||||
var w5 := 0
|
||||
while not main.net.waiting.is_empty() and w5 < 900:
|
||||
await frames(1)
|
||||
w5 += 1
|
||||
check(main.net.waiting.is_empty() and main.net.seats.size() == 2 and b.game.log.any(func(l): return l == "Bot ist zurück."), "Bot wieder verbunden, Platz zurück")
|
||||
var turn2: int = b.game.turn
|
||||
for i in 2:
|
||||
await clear_mulligan(b)
|
||||
if b.game.current() == b.perspective and b.game.winner == "":
|
||||
await click(b.b_end)
|
||||
var w6 := 0
|
||||
while b.game.current() != b.perspective and b.game.winner == "" and w6 < 900:
|
||||
await frames(1)
|
||||
w6 += 1
|
||||
check(b.game.turn >= turn2 + 1, "Partie läuft nach der Rückkehr weiter")
|
||||
OS.kill(pid2)
|
||||
await leave_battle()
|
||||
check(screen() is MenuScreen and not main.net.connected, "Netzwerk getrennt, zurück im Menü")
|
||||
|
||||
|
||||
@@ -581,12 +670,31 @@ func test_kampagne() -> void:
|
||||
check(scr is CampaignScreen, "Kampagne geöffnet")
|
||||
await shot("15_kampagne")
|
||||
check(find_button("Gesperrt") != null and find_button("Kämpfen") != null, "Stufen gesperrt und offen")
|
||||
check(find_button("Kapitel 2").disabled and scr.perk_box == null, "Kapitel 2 und Merkmal noch gesperrt")
|
||||
await click(find_button("Kämpfen"))
|
||||
var battle = screen()
|
||||
check(battle is BattleScreen and battle.stage == 0, "Kampagnenkampf gestartet")
|
||||
check(battle.game.opponents.size() == 1 and battle.game.opponents[0].name == "Fenn", "Fenn ist der Gegner")
|
||||
check(battle.game.opponents[0].perks == ["feuer_angriff"] and battle.game.log.any(func(l): return l.begins_with("Fenn: Feuerwesen")), "Boss-Merkmal aktiv")
|
||||
await shot("16_kampagne_kampf")
|
||||
await give_up()
|
||||
# Kapitel 1 als abgeschlossen setzen: Kapitel 2 und Merkmalwahl
|
||||
main.profile.campaign_stage = Campaign.STAGES.size()
|
||||
await click(find_button("Kampagne"))
|
||||
var scr2 = screen()
|
||||
check(scr2.chapter == 2 and scr2.perk_box != null, "Kapitel 2 offen, Merkmal wählbar")
|
||||
scr2.perk_box.select(1)
|
||||
scr2.perk_box.item_selected.emit(1)
|
||||
check(main.profile.perk == Game.PERKS.keys()[0], "Merkmal gewählt")
|
||||
await shot("27_kampagne_kapitel2")
|
||||
await click(find_button("Kämpfen"))
|
||||
var b2 = screen()
|
||||
check(b2 is BattleScreen and b2.stage == 10 and b2.game.opponents[0].perks.size() == 2, "Kapitel-2-Boss mit zwei Merkmalen")
|
||||
check(b2.game.human.perks == [main.profile.perk], "eigenes Merkmal im Kampf")
|
||||
await give_up()
|
||||
main.profile.campaign_stage = 0
|
||||
main.profile.perk = ""
|
||||
main.save()
|
||||
|
||||
|
||||
func test_kampf(n_opp: int, shot_turn: int) -> void:
|
||||
|
||||
Reference in New Issue
Block a user