extends Node var failures: Array[String] = [] func check(value: bool, message: String) -> void: if not value: failures.append(message) push_error(message) func _ready() -> void: run.call_deferred() func run() -> void: GameState.start_new_run() var game: Node = load("res://scenes/game/game.tscn").instantiate() get_tree().root.add_child(game) get_tree().current_scene = game await get_tree().process_frame await get_tree().process_frame get_tree().paused = true GameState.captain.credits = 111 check(GameState.save_named_game("Orion / próba α","slot_test_alpha") == OK,"Unicode display name saves independently of filename") GameState.captain.credits = 222 check(GameState.save_named_game("Druga wyprawa","slot_test_beta") == OK,"second named slot saves") var entries := GameState.SAVES.list_saves() check(entries.any(func(entry: Dictionary) -> bool: return entry.id == "slot_test_alpha" and entry.name == "Orion / próba α"),"named save appears in load list") check(entries[0].id == "slot_test_beta","newest named save comes first") check(GameState.continue_game() and GameState.captain.credits == 222,"continue loads newest named save") check(GameState.load_game("slot_test_alpha") and GameState.captain.credits == 111,"selected older save restores its own progress") GameState.captain.credits = 333 check(GameState.save_named_game("Nowa nazwa","slot_test_alpha") == OK,"existing slot can be renamed and overwritten") var path := GameState.SAVES.slot_path("slot_test_alpha") check(GameState.SAVES.read_save(path).captain.credits == 333,"overwrite updates selected slot") check(GameState.SAVES.read_save(path.trim_suffix(".res")+".backup.res").captain.credits == 111,"overwrite keeps previous slot backup") check(GameState.save_game() == OK,"autosave still works") check(GameState.SAVES.read_save(path).save_name == "Nowa nazwa","autosave does not overwrite named slots") check(GameState.save_named_game(" ") == ERR_INVALID_PARAMETER,"blank name rejected") check(GameState.save_named_game("Unsafe","../../outside") == ERR_INVALID_PARAMETER,"slot path traversal rejected") check(not GameState.load_game("slot_does_not_exist"),"unknown slot does not silently load another save") var browser := CanvasLayer.new() browser.set_script(load("res://scripts/ui/save_browser.gd")) browser.save_mode = true get_tree().root.add_child(browser) browser._name.text = "" browser._update_action() check(browser._action.disabled,"save button rejects blank UI name") browser._name.text = "Statek" browser._update_action() browser._activate() await get_tree().process_frame entries = GameState.SAVES.list_saves() check(entries.any(func(entry: Dictionary) -> bool: return entry.name == "Statek"),"name entered in dialog reaches disk") GameSettings.locale = "en" GameSettings.apply() browser = CanvasLayer.new() browser.set_script(load("res://scripts/ui/save_browser.gd")) var requested := [""] browser.connect("load_requested",func(id: String) -> void: requested[0] = id) get_tree().root.add_child(browser) var alpha: Dictionary = entries.filter(func(entry: Dictionary) -> bool: return entry.id == "slot_test_alpha")[0] browser._select(alpha) browser._activate() check(requested[0] == "slot_test_alpha","load button emits selected slot") var named_entry: Dictionary = entries.filter(func(entry: Dictionary) -> bool: return entry.name == "Statek")[0] var card: Node = browser._list.get_node(str(named_entry.id)) var name_label: Label = card.get_child(0).get_child(1).get_child(0) check(name_label.auto_translate_mode == Node.AUTO_TRANSLATE_MODE_DISABLED,"player save names are never translated") browser._close() await get_tree().process_frame get_tree().paused = false var session: Node = game.get_node("SessionMenu") session._open() var completed := [false] session._open_save_browser(func() -> void: completed[0] = true) session._options._close() await get_tree().process_frame check(not completed[0] and session._dialog.visible and get_tree().paused,"cancel named save returns to pause without running exit action") session._open_save_browser(func() -> void: completed[0] = true) session._options._name.text = "Zapis przed wyjściem" session._options._update_action() session._options._activate() await get_tree().process_frame check(completed[0] and session._dialog.visible,"successful named save runs continuation action") session._close() # Corruption affects only this slot; the chooser exposes its verified backup. var file := FileAccess.open(path,FileAccess.WRITE) file.store_string("corrupt named save") file.close() entries = GameState.SAVES.list_saves() alpha = entries.filter(func(entry: Dictionary) -> bool: return entry.id == "slot_test_alpha")[0] check(alpha.recovered,"named backup recovery shown in list") check(GameState.load_game("slot_test_alpha") and GameState.captain.credits == 111,"selected named backup restores previous progress") get_tree().paused = false game.queue_free() await get_tree().process_frame print("NAMED_SAVE_TEST: ","PASS" if failures.is_empty() else "FAIL"," (",failures.size()," failures)") get_tree().quit(0 if failures.is_empty() else 1)