extends SceneTree ## Real Main controls, paid builds and the Runtime command queue. Dedicated disk ## saves verify that a pending edit cannot be charged/applied twice after Load. var _checks := 0 var _failures := 0 var _main: Control var _panel: BusinessManagementPanel var _runtime: Variant var _clock: Variant var _rooms: Array[StringName] = [] var _reception: StringName = &"" var _warehouse: StringName = &"" var _save_path := "user://tests/business_ui_%d/queued_policy" % OS.get_process_id() func _initialize() -> void: call_deferred("_run") func _run() -> void: _clock = root.get_node("GameClock") _runtime = root.get_node("SimulationRuntime") var state: Variant = root.get_node("GameState") _clock.reset(1, 6, 0) state.reset() _runtime.initialize(_clock, state, 824260) _clock.set_paused(true) root.size = Vector2i(1280, 720) _main = load("res://scenes/main/main.tscn").instantiate() as Control _main.set("manual_save_path", "user://tests/business_ui_%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 _panel = _main.find_child("BusinessManagementPanel", true, false) as BusinessManagementPanel _expect(_panel != null, "normal Main includes business management") if _panel == null: _finish() return (_main.get("navigation_buttons")[&"business"] as Button).pressed.emit() _expect(_panel.visible and _panel.apply_button.disabled and _panel.facility_option.disabled, "business nav opens a safe empty state before completed construction") _expect("完成" in _panel.facility_status_label.text, "empty state explains completed facility prerequisite") for request: Array in [ [&"reception", Vector3i(-8, 0, 0)], [&"standard_room", Vector3i(-8, 2, 0)], [&"standard_room", Vector3i(-6, 2, 0)], [&"warehouse", Vector3i(-8, 0, 1)], ]: var before: int = _runtime.construction_service.get_jobs().size() _main.call("_select_build_definition", request[0]) _main.call("_on_map_cell_clicked", request[1]) _expect(_runtime.construction_service.get_jobs().size() == before + 1, "normal UI pays for construction of %s" % request[0]) if request[0] == &"reception": _clock.advance_minutes(120) _clock.advance_minutes(180) for facility: FacilityInstance in _runtime.facility_service.get_instances(): if facility.definition_id == &"standard_room": _rooms.append(facility.instance_id) elif facility.definition_id == &"reception": _reception = facility.instance_id elif facility.definition_id == &"warehouse": _warehouse = facility.instance_id _expect(_rooms.size() == 2 and not _reception.is_empty() and not _warehouse.is_empty(), "paid builds complete two rooms, free reception and warehouse") if _rooms.size() != 2 or _reception.is_empty() or _warehouse.is_empty(): _finish() return _main.call("_activate_management_mode", &"business") _panel.refresh() _test_prices_and_drafts() _test_open_close() _test_saved_pending_edit() await _test_navigation_and_layout() _finish() func _test_prices_and_drafts() -> void: _choose(_panel.facility_option, _rooms[0]) _expect(_panel.price_option.item_count == 5 and not _panel.price_option.disabled, "five price modes are available for paid guest rooms") var row := _row(_rooms[0]) _expect(int(row.get(&"base_price", 0)) == 120 and "120G" in _panel.quote_label.text, "initial room shows actual 120 G base and current quotation") var digest: String = _runtime.latest_digest var cash: int = _runtime.economy_service.get_balance(&"PLAYER_CASH") for pair: Array in [[&"charitable", 72], [&"affordable", 96], [&"standard", 120], [&"expensive", 180], [&"exorbitant", 300]]: _choose(_panel.price_option, pair[0]) _expect("設定後 %dG" % pair[1] in _panel.quote_label.text, "%s mode previews authoritative rounded price" % pair[0]) _expect(_runtime.latest_digest == digest and _runtime.economy_service.get_balance(&"PLAYER_CASH") == cash, "changing drafts and displaying quotes never mutates Runtime or spends cash") _expect("満足度" in _panel.effect_label.text and "支払えない" in _panel.effect_label.text, "highest price explains satisfaction and affordability instead of an invented demand forecast") _choose(_panel.price_option, &"affordable") _main.call("_activate_management_mode", &"product") _clock.advance_minutes(1) _main.call("_activate_management_mode", &"business") _expect(_selected_mode() == &"affordable" and not _panel.apply_button.disabled, "unsaved price draft survives time updates and other management panels") _choose(_panel.facility_option, _rooms[1]) _choose(_panel.price_option, &"expensive") _choose(_panel.facility_option, _rooms[0]) _expect(_selected_mode() == &"affordable", "separate facilities keep separate price drafts") _clock.set_paused(false) _panel.apply_button.pressed.emit() _expect(_panel.apply_button.disabled and _panel.price_option.disabled and _panel.business_open_button.disabled, "queued policy disables edits and duplicate submissions for that facility") _choose(_panel.facility_option, _rooms[1]) _clock.advance_minutes(1) _clock.set_paused(true) _expect(_selected_mode() == &"expensive" and _panel.selected_facility_id == _rooms[1], "completion on one facility preserves the selected other facility draft") _expect(StringName(_row(_rooms[0]).get(&"price_mode", &"")) == &"affordable" and int(_row(_rooms[0]).get(&"price", 0)) == 96, "accepted price reaches facility policy and Runtime report") _panel.apply_button.pressed.emit() _expect(int(_row(_rooms[1]).get(&"price", 0)) == 180 and "反映" in _panel.result_label.text, "paused submission applies another facility's own draft with Japanese confirmation") _expect(_panel.apply_button.disabled, "applied unchanged draft cannot be submitted again") func _test_open_close() -> void: _panel.business_open_button.button_pressed = false _expect(not _panel.apply_button.disabled, "closing admission is an explicit unsaved draft") _panel.apply_button.pressed.emit() _expect(not bool(_row(_rooms[1]).get(&"business_open", true)) and "停止" in _panel.facility_status_label.text, "close reaches actual facility operator state and status text") _expect("受付済みの料金は変わりません" in _panel.explanation_label.text and "開始済みのサービス" in _panel.explanation_label.text and "給与は発生" in _panel.explanation_label.text, "UI explains fixed accepted prices, service completion, and continued wages during closure") _panel.business_open_button.button_pressed = true _panel.apply_button.pressed.emit() _expect(bool(_row(_rooms[1]).get(&"business_open", false)), "admission can be reopened through the same controls") _choose(_panel.facility_option, _reception) _expect(_panel.price_option.disabled and "利用料金はありません" in _panel.quote_label.text, "free reception has no editable price") _panel.business_open_button.button_pressed = false _panel.apply_button.pressed.emit() _expect(not bool(_row(_reception).get(&"business_open", true)), "free facility still supports admission control") _panel.business_open_button.button_pressed = true _panel.apply_button.pressed.emit() _expect(bool(_row(_reception).get(&"business_open", false)), "free reception can reopen without sending a price patch") _choose(_panel.facility_option, _warehouse) _expect(_panel.price_option.disabled and _panel.business_open_button.text == "営業する" and "調理と新しい補給" in _panel.explanation_label.text and "荷物は保持" in _panel.explanation_label.text, "backroom warehouse explains supply pause and retained cargo instead of guest admission") _panel.business_open_button.button_pressed = false _panel.apply_button.pressed.emit() _expect(not bool(_row(_warehouse).get(&"business_open", true)), "warehouse closing updates the real operator policy") _panel.business_open_button.button_pressed = true _panel.apply_button.pressed.emit() _expect(bool(_row(_warehouse).get(&"business_open", false)), "warehouse can reopen through the same business panel") func _test_saved_pending_edit() -> void: _choose(_panel.facility_option, _rooms[0]) _choose(_panel.price_option, &"charitable") _clock.set_paused(false) _panel.apply_button.pressed.emit() var pending_before: int = _runtime.command_queue.create_snapshot().get("pending", []).size() _panel.submit_policy() _expect(pending_before == 1 and _runtime.command_queue.create_snapshot().get("pending", []).size() == 1, "a second press cannot enqueue duplicate policy edits") var saved: Dictionary = _runtime.save_to_path(_save_path) _expect(bool(saved.get(&"ok", false)), "pending price policy saves to an isolated disk slot") _clock.advance_minutes(1) var loaded: Dictionary = _runtime.load_from_path(_save_path) _expect(bool(loaded.get(&"ok", false)), "pending policy restores from disk") _panel.refresh() _expect(_panel.apply_button.disabled and _selected_mode() == &"charitable" and "設定後 72G" in _panel.quote_label.text, "restored pending edit remains locked and displays its accepted draft, not stale live policy") _clock.advance_minutes(1) _clock.set_paused(true) _panel.refresh() _expect(int(_row(_rooms[0]).get(&"price", 0)) == 72 and not _panel.price_option.disabled, "restored policy executes once and unlocks editing") _choose(_panel.price_option, &"standard") _panel.apply_button.pressed.emit() _expect(int(_row(_rooms[0]).get(&"price", 0)) == 120, "restored command key sequence permits a genuinely new policy edit") var report := _panel.get_report() (report[&"facilities"] as Array).clear() _panel.refresh() _expect(not (_panel.get_report().get(&"facilities", []) as Array).is_empty(), "read model returned to callers is defensive") func _test_navigation_and_layout() -> void: for entry: Array in [[&"ledger", "operating_ledger_panel"], [&"product", "supply_management_panel"], [&"staff", "staff_management_panel"]]: _main.call("_activate_management_mode", entry[0]) _expect(not _panel.visible and (_main.get(entry[1]) as Control).visible, "%s exclusively replaces business controls" % entry[0]) _main.call("_activate_management_mode", &"business") _expect(_panel.visible and not (_main.get(entry[1]) as Control).visible, "business exclusively replaces %s controls" % entry[0]) _main.call("_unhandled_key_input", _key(KEY_H)) _expect(not _panel.visible and (_main.get("staff_candidate_panel") as Control).visible, "H replaces business with hiring candidates") _main.call("_activate_management_mode", &"business") _choose(_panel.facility_option, _rooms[1]) _main.call("_set_layer", 0) await process_frame await process_frame var side := _main.find_child("SidePanel", true, false) as Control var guide := _main.find_child("InnOpeningGuide", true, false) as Control _expect(not side.get_global_rect().intersects(guide.get_global_rect()), "1280x720 business inspector stays clear of opening guidance") for control: Control in [_panel, _panel.facility_option, _panel.price_option, _panel.business_open_button, _panel.apply_button]: _expect(control.get_global_rect().position.x >= side.get_global_rect().position.x and control.get_global_rect().end.x <= side.get_global_rect().end.x, "%s fits inside narrow sidebar" % control.name) if OS.get_environment("THE_TREE_BUSINESS_UI_CAPTURE") == "1": var capture_dir := ProjectSettings.globalize_path("res://artifacts/business-management") DirAccess.make_dir_recursive_absolute(capture_dir) await RenderingServer.frame_post_draw root.get_texture().get_image().save_png(capture_dir.path_join("business-panel.png")) _choose(_panel.facility_option, _warehouse) _main.call("_set_layer", 1) await process_frame await RenderingServer.frame_post_draw root.get_texture().get_image().save_png(capture_dir.path_join("warehouse-policy.png")) _main.call("_unhandled_key_input", _key(KEY_ESCAPE)) _expect(not _panel.visible and not bool(_main.get("_management_panel_open")), "Escape closes business inspector and restores full map") func _row(id: StringName) -> Dictionary: for row: Dictionary in _runtime.get_business_management_report().get(&"facilities", []): if StringName(row.get(&"facility_id", &"")) == id: return row return {} func _selected_mode() -> StringName: return StringName(_panel.price_option.get_item_metadata(_panel.price_option.selected)) func _choose(picker: OptionButton, id: StringName) -> void: for index: int in picker.item_count: if StringName(picker.get_item_metadata(index)) == id: picker.select(index) picker.item_selected.emit(index) return _expect(false, "requested business dropdown value exists: %s" % id) func _key(code: Key) -> InputEventKey: var event := InputEventKey.new() event.keycode = code event.pressed = true return event func _expect(condition: bool, message: String) -> void: _checks += 1 if not condition: _failures += 1 push_error(message) func _finish() -> void: SaveService.delete_save(_save_path) if is_instance_valid(_main): _main.queue_free() print("Business management UI: %d checks, %d failures" % [_checks, _failures]) quit(1 if _failures > 0 else 0)