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.
116 lines
5.1 KiB
GDScript
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)
|