extends SceneTree const EntryShell = preload("res://entry/entry_shell.gd") const SettingsStore = preload("res://entry/settings_store.gd") const SETTINGS_PATH := "user://dev1_settings_credits_test.json" var failures: Array[String] = [] func _initialize() -> void: call_deferred("run_test") func run_test() -> void: _cleanup() var shell = EntryShell.new() shell.auto_start = false shell.settings_store.path = SETTINGS_PATH root.add_child(shell) await process_frame shell.settings = shell.settings_store.defaults() shell.settings.setup_completed = true shell.settings.locale = "en" shell.show_title() shell.show_settings() await process_frame verify_categories(shell) verify_apply_discard_and_runtime(shell) verify_credits(shell) shell.queue_free() await process_frame _cleanup() if failures.is_empty(): print("ABG_DEV1_SETTINGS_OK set=001,002,003,004,005,006 sys=008 persisted=true apply_discard=true caller=title unavailable_reasons=true audio_bus=true") quit(0) else: for failure in failures: push_error(failure) quit(1) func verify_categories(shell) -> void: expect(shell.get_node_or_null("SettingsSafeArea/SettingsFrame") != null, "Settings uses the enamel workspace frame") for category in ["display", "motion", "audio", "controls", "language", "credits"]: shell.open_settings_category(category) expect(shell.find_child("SettingsContent", true, false) != null, "category %s opens" % category) var selected: Button = shell.find_child("SettingsCategory_%s" % category, true, false) expect(selected != null and selected.disabled and bool(selected.get_meta("selected_entry_tab", false)), "category %s has an explicit selected segment" % category) shell.open_settings_category("audio") var content = shell.find_child("SettingsContent", true, false) expect(content.get_node("SettingAmbienceUnavailable").disabled and not content.get_node("SettingAmbienceUnavailable").tooltip_text.is_empty(), "absent ambience has a precise reason") expect(content.get_node("SettingVoiceUnavailable").disabled and not content.get_node("SettingVoiceUnavailable").tooltip_text.is_empty(), "absent voice has a precise reason") shell.open_settings_category("controls") content = shell.find_child("SettingsContent", true, false) expect(content.get_node("SettingRemapUnavailable").disabled and "later" in content.get_node("SettingRemapUnavailable").tooltip_text, "remapping names its later-page boundary") func verify_apply_discard_and_runtime(shell) -> void: shell.settings_category = "display" shell.show_settings() expect(shell.find_child("SettingSafeArea", true, false).get_node_or_null("Chrome") != null, "settings choices keep the value-plate chrome") expect(shell.find_child("SettingHighContrast", true, false).get_node_or_null("Chrome") != null, "settings toggles keep the authored state chrome") shell.settings_draft.safe_area = 48 shell.settings_draft.text_scale = 1.3 shell.settings_draft.brightness = 0.9 shell.settings_draft.high_contrast = true shell.settings_draft.color_cues = false shell.settings_draft.reduced_motion = true shell.settings_draft.reduced_flashes = true shell.settings_draft.low_power = true shell.settings_draft.master_muted = true shell.settings_draft.music_volume = 0.4 shell.settings_draft.sfx_volume = 0.5 shell.settings_draft.captions = false shell.settings_draft.caption_detail = "full" shell.settings_draft.dynamic_range = "night" shell.settings_draft.hold_duration = 1.0 shell.settings_draft.vibration = false shell.apply_settings() var loaded: Dictionary = shell.settings_store.load_settings() expect(loaded.ok and int(loaded.settings.safe_area) == 48 and is_equal_approx(float(loaded.settings.text_scale), 1.3), "display settings persist") expect(loaded.settings.reduced_motion and loaded.settings.reduced_flashes and loaded.settings.low_power, "motion settings persist") expect(loaded.settings.master_muted and not loaded.settings.captions and loaded.settings.dynamic_range == "night", "audio/caption settings persist") expect(is_equal_approx(float(loaded.settings.hold_duration), 1.0) and not loaded.settings.vibration, "control settings persist") expect(AudioServer.is_bus_mute(AudioServer.get_bus_index(&"Master")), "Master mute applies to the real audio bus") shell.settings_draft.safe_area = 0 shell.request_settings_back() expect("Unsaved" in shell.settings_notice, "Back with changes requires Apply or Discard") shell.discard_settings() expect(shell.current_screen == "title" and int(shell.settings.safe_area) == 48, "Discard returns to exact caller without applying") shell.show_settings() func verify_credits(shell) -> void: shell.show_credits() var content = shell.find_child("SettingsContent", true, false) var combined := "" for child in content.get_children(): if child is Label: combined += child.text expect("SIL Open Font License" in combined and "offline" in combined and "no analytics" in combined, "Credits states authorship, license, offline and privacy facts") shell.discard_settings() expect(shell.current_screen == "title", "Credits returns to Title") func _cleanup() -> void: for path in [SETTINGS_PATH, "%s.bak" % SETTINGS_PATH, "%s.candidate" % SETTINGS_PATH]: if FileAccess.file_exists(path): DirAccess.remove_absolute(path) func expect(condition: bool, message: String) -> void: if not condition: failures.append("DEV-1 Settings: %s" % message)