extends SceneTree const FixtureCleanup := preload("res://tests/helpers/ui_audio_fixture_cleanup.gd") var _checks := 0 var _failures := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: var runtime: Variant = 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() _expect(bool(runtime.initialize(clock, state, 230225).get(&"valid", false)), "normal Runtime initialization") clock.set_paused(true) runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false}) root.size = Vector2i(1280, 720) var main: Control = load("res://scenes/main/main.tscn").instantiate() main.set("manual_save_path", "user://tests/event_log_%d/manual" % OS.get_process_id()) root.add_child(main) await process_frame await process_frame var dialog: AcceptDialog = main.get("event_log_dialog") var button := main.find_child("EventLogButton", true, false) as Button _expect(button != null and button.is_visible_in_tree() and dialog != null, "event history has a normal UI entry") if button == null or dialog == null: var early_cleanup: Dictionary = await FixtureCleanup.free_owner_and_wait(self, main) _expect(bool(early_cleanup.get(&"passed", false)), "early ordinary Main release preserves whole typed Runtime and controls") _finish() return var baseline: Dictionary = runtime.create_snapshot() var baseline_bytes: PackedByteArray = var_to_bytes(baseline) button.pressed.emit() _expect(dialog.visible, "existing UI signal opens the log dialog") var expected_rows: Array[Dictionary] = _recent_rows(runtime) var rows: Array[Dictionary] = dialog.call("get_event_rows") _expect(var_to_bytes(rows) == var_to_bytes(expected_rows), "every retained row and full typed dictionary is returned in publication order") _expect(var_to_bytes(runtime.create_snapshot()) == baseline_bytes, "opening and reading preserve the whole Runtime snapshot") var changed: CommandResult = runtime.submit_command(&"change_resources", {&"deltas": {&"gold": 1}}, &"player", &"", 50, -1, &"event_log.fixture.paid_fact") _expect(changed.is_success(), "disclosed fixture uses a genuine Runtime command") expected_rows = _recent_rows(runtime) _expect(not expected_rows.is_empty(), "public command leaves actual published facts") dialog.call("refresh") var list := dialog.find_child("EventLogList", true, false) as ItemList _expect(list != null and list.item_count == expected_rows.size(), "visible list covers all retained records without an added cap") var saved: Dictionary = runtime.create_snapshot() var saved_bytes: PackedByteArray = var_to_bytes(saved) if list != null: for index: int in range(expected_rows.size()): list.select(index) list.item_selected.emit(index) _expect(var_to_bytes(dialog.call("get_selected_event")) == var_to_bytes(expected_rows[index]), "selected row owns every typed field of the exact existing record") _expect(var_to_bytes(runtime.create_snapshot()) == saved_bytes, "selection preserves IDs/RNG/all systems/clock/events/queue") # Formatter-only synthetic rows exercise known/unknown labels without # publishing facts or claiming natural employment/arrival acceptance. var known_row := SimulationDomainEvent.new(&"fixture.naming", &"STAFF_REGISTERED", 360, &"staff_service", [&"staff_eri"], {&"nested": [{&"preserve_type": &"original"}]}, 0).to_dictionary() var row_bytes := var_to_bytes(known_row) var named: Dictionary = dialog.call("get_event_presentation", known_row) var entry: Dictionary = runtime.mvp_content_catalog.get_entry(&"staff_candidates", &"staff_eri") _expect(named[&"title"] == "従業員を登録" and named[&"targets"] == entry[&"display_name"], "known fact uses Japanese type and existing target display name") _expect(not String(named[&"title"]).contains("STAFF_REGISTERED") and not String(named[&"targets"]).contains("staff_eri"), "raw type and entity ID are not primary labels") _expect(String(named[&"supplement"]).contains("STAFF_REGISTERED") and String(named[&"supplement"]).contains("staff_eri"), "original raw identifiers remain available as supplemental metadata") var unknown_row := SimulationDomainEvent.new(&"fixture.unknown", &"FUTURE_NOTIFICATION", 361, &"future_service", [&"unknown_target"], {}, 0).to_dictionary() var unknown: Dictionary = dialog.call("get_event_presentation", unknown_row) _expect(unknown[&"title"] == "未識別の記録" and unknown[&"targets"] == "名称を確認できない対象(1件)", "unknown kind and target use safe human-readable fallback") _expect(var_to_bytes(known_row) == row_bytes and var_to_bytes(runtime.create_snapshot()) == saved_bytes, "name formatting preserves full input types and whole Runtime") for facility: FacilityInstance in runtime.facility_service.get_instances(): var facility_row := SimulationDomainEvent.new(&"fixture.facility", &"FACILITY_STATE_CHANGED", 360, &"facility_service", [facility.instance_id], {}, 0).to_dictionary() var presentation: Dictionary = dialog.call("get_event_presentation", facility_row) var definition: FacilityDefinition = runtime.definition_registry.get_facility(facility.definition_id) _expect(definition != null and String(presentation[&"targets"]).contains(definition.display_name), "existing facility definition name resolves without new catalog membership") if list != null: for index: int in range(expected_rows.size()): var presentation: Dictionary = dialog.call("get_event_presentation", expected_rows[index]) _expect(list.get_item_text(index) == "%s %s — %s" % [presentation[&"time"], presentation[&"title"], presentation[&"targets"]], "each actual retained row uses its human-readable presentation") _expect(var_to_bytes(runtime.create_snapshot()) == saved_bytes, "all actual and synthetic formatting leaves whole Runtime unchanged") rows = dialog.call("get_event_rows") if not rows.is_empty(): rows[0]["payload"][&"outside_mutation_probe"] = true _expect(var_to_bytes(dialog.call("get_event_rows")) == var_to_bytes(expected_rows), "nested returned payload mutation cannot affect source or next query") _expect(var_to_bytes(runtime.create_snapshot()) == saved_bytes, "defensive copies preserve the entire Runtime") dialog.call("apply_layer_skin", 1) dialog.call("apply_layer_skin", 0) dialog.call("_select_row", -1) dialog.call("_select_row", expected_rows.size()) _expect(var_to_bytes(runtime.create_snapshot()) == saved_bytes, "skin changes and invalid selection create no commands or state changes") _expect(runtime.restore_snapshot(saved), "unchanged Runtime14 snapshot restores through existing validation") dialog.call("refresh") _expect(var_to_bytes(dialog.call("get_event_rows")) == var_to_bytes(expected_rows), "view queries the replaced live stream after restore") _expect(var_to_bytes(runtime.create_snapshot()) == saved_bytes, "same-process restore retains every typed snapshot byte") dialog.hide() var cleanup: Dictionary = await FixtureCleanup.free_owner_and_wait(self, main) _expect(bool(cleanup.get(&"passed", false)), "ordinary Main release preserves whole typed Runtime and controls") _finish() func _recent_rows(runtime: Variant) -> Array[Dictionary]: var result: Array[Dictionary] = [] for event: SimulationDomainEvent in runtime.domain_events.recent_events(): result.append(event.to_dictionary()) return result func _expect(condition: bool, message: String) -> void: _checks += 1 if not condition: _failures += 1 push_error(message) func _finish() -> void: print("Event log UI: %d checks, %d failures" % [_checks, _failures]) quit(_failures)