Files
aetherbound-guild/runtime/tests/dev1/title_state_test.gd
T
wushenghua 9ec4995b4d feat: restore Title from approved AI design
Add the approved SYS-003 design authority and responsive background support, rebuild the Title as a 16:9 coordinate-master scene with engine-owned localized actions, and cover behavior, touch, resize, and normal-render evidence.
2026-08-19 13:37:11 +08:00

116 lines
5.1 KiB
GDScript

extends SceneTree
const EntryShell = preload("res://entry/entry_shell.gd")
const SettingsStore = preload("res://entry/settings_store.gd")
const SAVE_PATH := "user://aetherbound_guild_p10_3.json"
const SETTINGS_PATH := "user://dev1_title_settings_test.json"
const DRAFT_PATH := "user://dev1_title_initial_company_test.json"
const COMPANY_PATH := "user://dev1_title_company_test.json"
var failures: Array[String] = []
func _initialize() -> void:
call_deferred("run_test")
func run_test() -> void:
_cleanup()
await verify_no_save_and_return_paths()
await verify_resumable_state()
_cleanup()
if failures.is_empty():
print("ABG_DEV1_TITLE_OK new_game=initial_company continue_missing=disabled continue_valid=enabled settings_return=true credits_return=true exit_review=true")
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func verify_no_save_and_return_paths() -> void:
var shell = await _shell()
var continue_button: Button = shell.get_node("TitleSafeArea/TitleLayout/TitleCopy/TitleActions/TitleContinue")
var new_game: Button = shell.get_node("TitleSafeArea/TitleLayout/TitleCopy/TitleActions/TitleNewGame")
expect(continue_button.disabled, "Continue is disabled when no save exists")
expect(new_game.has_focus(), "New Game owns the initial keyboard/controller focus")
expect(shell.get_node_or_null("TitleMasterWorldExtension") != null and shell.get_node_or_null("TitleSafeArea/TitleMasterComposite") != null, "Title uses the approved v001 world and coordinate master")
expect(shell.get_node_or_null("TitleSafeArea/TitleLayout/TitleHeader/TitleIdentity") != null, "Title uses engine-rendered identity copy")
expect(shell.get_node_or_null("TitleSafeArea/TitleLayout/TitleCommandDock") != null, "Title actions align to the physical command prop")
expect(new_game.get_node_or_null("ButtonLabel") != null and continue_button.get_node_or_null("ButtonLabel") != null, "Title actions use engine-rendered labels")
expect(shell.get_node_or_null("TitleSafeArea/TitleLayout/TitleTools/TitleSettings") != null and shell.get_node_or_null("TitleSafeArea/TitleLayout/TitleTools/TitleCredits") != null, "Title utility controls map to the lower command sign")
expect(not continue_button.get_node("TitleContinueReason").text.is_empty(), "disabled Continue has a visible reason")
shell.open_new_game_boundary()
await process_frame
expect(shell.current_screen == "initial_company" and shell.get_node_or_null("InitialCompanyPage/InitialCompanySafeArea") != null, "New Game reaches the real Initial Company page")
shell.initial_company_page.request_back()
await process_frame
expect(shell.current_screen == "title", "Initial Company Back returns to Title without losing the draft")
shell.show_settings_placeholder()
await process_frame
expect(shell.current_screen == "settings", "Settings opens from Title")
shell.back_to_title()
await process_frame
expect(shell.current_screen == "title", "Settings returns exactly to Title")
shell.show_credits_placeholder()
await process_frame
shell.back_to_title()
await process_frame
expect(shell.current_screen == "title", "Credits returns exactly to Title")
shell.request_exit()
await process_frame
expect(shell.current_screen == "exit_review" and shell.get_node_or_null("ChildSafeArea/ChildLayout/ExitConfirm") != null, "Back boundary uses an exit review")
shell.queue_free()
await process_frame
func verify_resumable_state() -> void:
_write(SAVE_PATH, JSON.stringify({"save_kind": "aetherbound_guild_p10_3", "save_version": 9}))
var shell = await _shell()
var continue_button: Button = shell.get_node("TitleSafeArea/TitleLayout/TitleCopy/TitleActions/TitleContinue")
expect(not continue_button.disabled, "Continue enables for a structurally valid local save")
shell.open_continue_boundary()
await process_frame
expect("unchanged" in shell.get_node("TitleSafeArea/TitleLayout/TitleCopy/TitleActions/TitleContinue/TitleNotice").text, "Continue preserves the save and explains the later resume review")
shell.queue_free()
await process_frame
func _shell():
var shell = EntryShell.new()
shell.auto_start = false
shell.initial_company_service.path = DRAFT_PATH
shell.initial_company_service.company_path = COMPANY_PATH
root.add_child(shell)
await process_frame
shell.settings = SettingsStore.new().defaults()
shell.settings.setup_completed = true
shell.settings.locale = "en"
shell.show_title()
await process_frame
return shell
func _write(path: String, text: String) -> void:
var file := FileAccess.open(path, FileAccess.WRITE)
file.store_string(text)
file.close()
func _cleanup() -> void:
for path in [SAVE_PATH, SETTINGS_PATH]:
if FileAccess.file_exists(path):
DirAccess.remove_absolute(path)
for suffix in ["", ".bak", ".candidate", ".bak.candidate", ".corrupt"]:
var draft_path := "%s%s" % [DRAFT_PATH, suffix]
if FileAccess.file_exists(draft_path):
DirAccess.remove_absolute(draft_path)
var company_path := "%s%s" % [COMPANY_PATH, suffix]
if FileAccess.file_exists(company_path):
DirAccess.remove_absolute(company_path)
func expect(condition: bool, message: String) -> void:
if not condition:
failures.append("DEV-1 Title: %s" % message)