Files
TheTree_mock/tests/ui/test_main_audio_feedback.gd
Takeshi b84bade045 Save The Tree implementation and acceptance work in progress
Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
2026-10-11 15:58:00 +09:00

106 lines
4.5 KiB
GDScript

extends SceneTree
const FixtureCleanup := preload("res://tests/helpers/ui_audio_fixture_cleanup.gd")
var _checks := 0
var _failures := 0
var _main: Control
var _runtime: Variant
var _audio: Variant
var _cues: Array[StringName] = []
func _initialize() -> void:
call_deferred(&"_run")
func _run() -> void:
_runtime = root.get_node("SimulationRuntime")
var clock: Variant = root.get_node("GameClock")
var state: Variant = root.get_node("GameState")
clock.reset(1, 6, 0)
state.reset()
_runtime.initialize(clock, state, 822252)
clock.set_paused(true)
root.size = Vector2i(1440, 810)
_main = load("res://scenes/main/main.tscn").instantiate() as Control
_main.set("audio_settings_path", "user://tests/main_audio_%d/settings.cfg" % OS.get_process_id())
_main.set("manual_save_path", "user://tests/main_audio_%d/manual" % OS.get_process_id())
root.add_child(_main)
_runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
await process_frame
await process_frame
_audio = _main.get("_audio_feedback")
_expect(_audio != null, "normal Main owns one presentation audio service")
_audio.playback_enabled = false
_audio.cue_requested.connect(_record_cue)
var button := _main.call("_button", "audio binding test", _noop) as Button
_main.call("_apply_button_style", button)
_main.call("_apply_button_style", button)
button.pressed.emit()
_expect(_cues == [&"click"], "normal styled button plays one click after repeated style registration")
_cues.clear()
button.disabled = true
button.pressed.emit()
_expect(_cues.is_empty(), "disabled button never requests audio even through emitted signal")
button.set_pressed_no_signal(true)
_expect(_cues.is_empty(), "programmatic selection is silent")
button.free()
_main.call("_set_status", "queued text", true)
_main.call("_set_status", "rejected text", false)
_main.call("_set_status", "quiet text", true, true)
_main.call("_refresh_dashboard")
_expect(_cues.is_empty(), "status and repeated dashboard refresh are not sound dispatchers")
var key := InputEventKey.new()
key.keycode = KEY_I
key.pressed = true
_main.call("_unhandled_key_input", key)
_expect(_cues == [&"click"], "normal keyboard shortcut requests one click")
_cues.clear()
key.echo = true
_main.call("_unhandled_key_input", key)
_expect(_cues.is_empty(), "keyboard repeat echo is silent")
var hire := (_main.get("staff_candidate_buttons") as Dictionary).get(&"staff_akane") as Button
_expect(hire != null and not hire.disabled, "normal hiring button is actionable")
if hire != null and not hire.disabled:
hire.pressed.emit()
_expect(_cues.count(&"success") == 1 and _cues.count(&"click") == 1, "real paused hire button has one completion and one click")
_expect(_runtime.staff_service.get_staff(&"staff_akane") != null, "normal hire command reaches actual Runtime state")
_cues.clear()
(_main.find_child("AudioSettingsButton", true, false) as Button).pressed.emit()
var dialog: Variant = _main.get("_audio_settings_dialog")
_expect(dialog.visible and _cues == [&"click"], "normal audio settings button opens actual controls")
_cues.clear()
dialog.ui_slider.value = 25
_expect(is_equal_approx(float(_audio.settings[&"ui_volume"]), 0.25), "normal slider changes AudioServer-linked UI volume")
dialog.mute_button.button_pressed = true
_expect(_audio.settings[&"muted"] and AudioServer.is_bus_mute(AudioServer.get_bus_index(&"Master")), "normal mute control reaches Master bus")
dialog.call("_save_settings")
_expect(FileAccess.file_exists(_main.get("audio_settings_path")), "normal settings save writes isolated presentation preference")
_audio.update_settings(UIAudioFeedback.DEFAULT_SETTINGS)
var before: Dictionary = _runtime.create_snapshot()
_main.call("_on_save_operation_completed", {&"ok": false, &"operation": &"load"})
_expect(var_to_bytes(before) == var_to_bytes(_runtime.create_snapshot()), "failed load audio hook leaves Runtime exact bytes")
_expect(_cues.is_empty(), "settings save and failed load do not fabricate command sounds")
var final_cleanup: Dictionary = await FixtureCleanup.free_owner_and_wait(self, _main)
if not bool(final_cleanup.get(&"passed", false)):
_failures += 1
push_error("ordinary Main audio cleanup failed")
print("Main audio feedback: %d checks, %d failures" % [_checks, _failures])
quit(_failures)
func _noop() -> void:
pass
func _record_cue(role: StringName, _correlation: Dictionary) -> void:
_cues.append(role)
func _expect(condition: bool, label: String) -> void:
_checks += 1
if not condition:
_failures += 1
push_error(label)