Files
aetherbound-guild/runtime/tests/dev1/first_launch_test.gd
T

118 lines
4.5 KiB
GDScript

extends SceneTree
const SettingsStore = preload("res://entry/settings_store.gd")
const EntryShell = preload("res://entry/entry_shell.gd")
const SETTINGS_PATH := "user://dev1_first_launch_test.json"
var failures: Array[String] = []
func _initialize() -> void:
call_deferred("run_test")
func run_test() -> void:
_cleanup()
verify_defaults_validation_and_atomic_roundtrip()
await verify_first_launch_once_and_restart()
_cleanup()
if failures.is_empty():
print("ABG_DEV1_FIRST_LAUNCH_OK language=true safe_area=true text=100,115,130 reduced_motion=true reduced_flashes=true captions=true persisted=true once=true")
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func verify_defaults_validation_and_atomic_roundtrip() -> void:
var store: RefCounted = SettingsStore.new()
store.path = SETTINGS_PATH
var loaded: Dictionary = store.load_settings()
expect(loaded.ok and not loaded.settings.setup_completed, "clean install supplies incomplete defaults")
var value: Dictionary = loaded.settings
value.locale = "en"
value.safe_area = 48
value.text_scale = 1.3
value.reduced_motion = true
value.reduced_flashes = true
value.captions = false
value.setup_completed = true
var saved: Dictionary = store.save_settings(value)
expect(saved.ok, "valid first-launch settings save atomically")
var reloaded: Dictionary = store.load_settings()
expect(
reloaded.ok
and reloaded.settings.locale == "en"
and int(reloaded.settings.safe_area) == 48
and is_equal_approx(float(reloaded.settings.text_scale), 1.3)
and reloaded.settings.reduced_motion
and reloaded.settings.reduced_flashes
and not reloaded.settings.captions
and reloaded.settings.setup_completed,
"saved settings survive reload with the same semantics"
)
value.text_scale = 1.2
expect(not store.save_settings(value).ok, "unsupported text scale is rejected")
func verify_first_launch_once_and_restart() -> void:
_cleanup()
var first = EntryShell.new()
first.auto_start = false
first.settings_store.path = SETTINGS_PATH
root.add_child(first)
await process_frame
first.settings = first.settings_store.defaults()
first.show_first_launch()
await process_frame
expect(first.find_child("SetupApply", true, false) != null and first.find_child("FirstLaunchReturn", true, false) == null, "first launch exposes Apply and no Back")
expect(first.find_child("FirstLaunchPreviewFrame", true, false) != null, "first launch uses the approved preview frame")
expect(first.find_child("SetupLanguage", true, false).get_node_or_null("ValuePlate") != null, "first-launch choices use authored value plates")
expect(first.find_child("SetupReducedMotion", true, false).get_node_or_null("ValuePlate") != null, "first-launch toggles use authored state plates")
expect(first.find_child("SetupApply", true, false).get_node_or_null("CommandFrame") != null, "first-launch Apply uses the primary command treatment")
first.toggle_setup_reduced_motion()
await process_frame
expect(bool(first.setup_draft.reduced_motion), "reduced-motion row toggles through the real button callback")
first.toggle_setup_reduced_flashes()
await process_frame
expect(bool(first.setup_draft.reduced_flashes), "reduced-flashes row toggles through the real button callback")
first.toggle_setup_captions()
await process_frame
expect(not bool(first.setup_draft.captions), "captions row toggles through the real button callback")
first.setup_draft.locale = "en"
first.setup_draft.safe_area = 48
first.setup_draft.text_scale = 1.3
first.setup_draft.reduced_motion = true
first.setup_draft.reduced_flashes = true
first.setup_draft.captions = true
first.apply_first_launch()
await process_frame
expect(first.settings.setup_completed, "Apply completes setup")
first.queue_free()
await process_frame
var restarted = EntryShell.new()
restarted.auto_start = false
restarted.settings_store.path = SETTINGS_PATH
root.add_child(restarted)
await process_frame
restarted._open_after_boot()
await process_frame
expect(restarted.get_node_or_null("FirstLaunchResponsiveLayout") == null, "completed setup is not forced after restart")
expect(restarted.get_node_or_null("TitleSafeArea") != null, "restart advances to Title boundary")
restarted.queue_free()
await process_frame
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 first launch: %s" % message)