118 lines
4.5 KiB
GDScript
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)
|