extends SceneTree const AudioTeardown := preload("res://tests/helpers/ui_audio_teardown.gd") ## Normal build/purchase commands: UI drafts, money/stock reconciliation, queued ## purchases and an isolated save slot. No free inventory is inserted. var _checks := 0 var _failures := 0 var _main: Control var _panel: SupplyManagementPanel var _runtime: Variant var _clock: Variant var _warehouse: StringName = &"" var _kitchens: Array[StringName] = [] var _item: StringName = &"" var _save_path := "user://tests/supply_ui_%d/queued_purchase" % OS.get_process_id() func _test_layer_palette() -> void: _main.call("_set_layer", 0) var before: Color = _panel.warehouse_stock_label.get_theme_color("font_color") var selected: bool = _panel.production_enabled.button_pressed _main.call("_set_layer", 1) _panel.refresh() _expect(_panel.warehouse_stock_label.get_theme_color("font_color") == Color("d8eeea"), "BACK panel text survives refresh") _expect(_panel.production_enabled.get_theme_color("font_hover_color") == Color("d8eeea") and _panel.production_enabled.get_theme_color("font_disabled_color") == Color("8da4a4"), "BACK toggle remains readable for hover and disabled states") _panel.call("_set_result", "条件未達", false) _expect(_panel.result_label.get_theme_color("font_color") == Color("ffb498"), "BACK error retains warning colour") _main.call("_set_layer", 0) _expect(_panel.warehouse_stock_label.get_theme_color("font_color") == before and _panel.result_label.get_theme_color("font_color") == Color("a7402e"), "FRONT restores panel and warning colours") _expect(_panel.production_enabled.button_pressed == selected, "palette does not toggle policy") _panel.call("_set_result", "", true) 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, 824242) _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/supply_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("SupplyManagementPanel", true, false) as SupplyManagementPanel _expect(_panel != null, "normal scene includes supply management") if _panel == null: await _finish() return (_main.get("navigation_buttons")[&"product"] as Button).pressed.emit() _expect(_panel.visible and _panel.purchase_button.disabled, "product opens a safe empty state before any warehouse exists") _expect("倉庫" in _panel.warehouse_stock_label.text, "empty purchase page explains the warehouse prerequisite") _test_layer_palette() for request: Array in [ [&"warehouse", Vector3i(-8, 0, 1)], [&"kitchen", Vector3i(0, 0, 1)], [&"kitchen", Vector3i(6, 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 builds %s" % request[0]) _clock.advance_minutes(180) for facility: FacilityInstance in _runtime.facility_service.get_instances(): if facility.definition_id == &"warehouse": _warehouse = facility.instance_id elif facility.definition_id == &"kitchen": _kitchens.append(facility.instance_id) _expect(not _warehouse.is_empty() and _kitchens.size() == 2, "paid construction produces a warehouse and two kitchens") if _warehouse.is_empty() or _kitchens.size() != 2: await _finish() return _main.call("_activate_management_mode", &"product") _panel.refresh() _item = _panel.selected_item_id _expect(not _item.is_empty(), "Runtime purchase catalog supplies a real item") _test_purchase_and_failure() _test_kitchen_drafts() _test_saved_pending_purchase() await _test_navigation_and_layout() await _finish() func _test_purchase_and_failure() -> void: _choose(_panel.warehouse_option, _warehouse) _panel.quantity_spin.value = 4 var quote: Dictionary = _runtime.preview_supply_purchase(_warehouse, _item, 4) _expect(bool(quote.get(&"ok", false)), "Runtime quotes a paid purchase for the completed warehouse") var balance_before: int = _runtime.economy_service.get_balance(&"PLAYER_CASH") var stock_before := _stock() _panel.purchase_button.pressed.emit() _expect(_stock() == stock_before + 4, "purchase button credits the warehouse's actual inventory") _expect(_runtime.economy_service.get_balance(&"PLAYER_CASH") == balance_before - int(quote.get(&"total_cost", -1)), "purchase pays exactly the authoritative quoted cost") _expect("仕入れました" in _panel.result_label.text, "successful purchase is visible in Japanese") # A deliberately oversized draft must fail without reducing cash or stock. _panel.quantity_spin.allow_greater = true _panel.quantity_spin.value = int(quote.get(&"max_quantity", 100)) + 100 var invalid_quantity := int(_panel.quantity_spin.value) var balance_after: int = _runtime.economy_service.get_balance(&"PLAYER_CASH") var stock_after := _stock() _expect(_panel.purchase_button.disabled, "invalid quoted quantity disables purchase before submission") _panel.submit_purchase() _expect(_stock() == stock_after and _runtime.economy_service.get_balance(&"PLAYER_CASH") == balance_after, "rejected purchase never partially spends money or inserts stock") _expect(int(_panel.quantity_spin.value) == invalid_quantity and not _panel.result_label.text.is_empty(), "rejected purchase preserves the quantity and an actionable result") _panel.quantity_spin.allow_greater = false _panel.quantity_spin.value = 2 func _test_kitchen_drafts() -> void: _panel.select_tab(&"kitchen") _choose(_panel.kitchen_option, _kitchens[0]) _panel.production_enabled.button_pressed = true _panel.target_spin.value = 4 _panel.select_tab(&"purchase") _clock.advance_minutes(1) _panel.select_tab(&"kitchen") _expect(_panel.production_enabled.button_pressed and int(_panel.target_spin.value) == 4, "time updates and tab changes preserve an unsaved kitchen draft") _clock.set_paused(false) _panel.production_button.pressed.emit() _expect(_panel.production_button.disabled, "queued kitchen setting disables another submission for that kitchen") _choose(_panel.kitchen_option, _kitchens[1]) _panel.production_enabled.button_pressed = true _panel.target_spin.value = 8 _clock.advance_minutes(1) _clock.set_paused(true) _expect(_panel.selected_kitchen_id == _kitchens[1] and int(_panel.target_spin.value) == 8 and _panel.production_enabled.button_pressed, "another kitchen's completion preserves the selected kitchen's draft") var configured := _kitchen_row(_kitchens[0]) _expect(bool(configured.get(&"enabled", false)) and int(configured.get(&"target_stock", -1)) == 4, "saved kitchen settings reach the authoritative Runtime model") _panel.production_button.pressed.emit() var second := _kitchen_row(_kitchens[1]) _expect(bool(second.get(&"enabled", false)) and int(second.get(&"target_stock", -1)) == 8, "second kitchen applies its own saved target") _expect("職員" in _panel.kitchen_status_label.text or "経路" in _panel.kitchen_status_label.text, "unready kitchen explains its authoritative staffing or route blocker in Japanese") _panel.production_enabled.button_pressed = false _panel.production_button.pressed.emit() _expect(not bool(_kitchen_row(_kitchens[1]).get(&"enabled", true)), "automatic production can be stopped through the same controls") func _test_saved_pending_purchase() -> void: _panel.select_tab(&"purchase") _panel.quantity_spin.value = 2 var stock_before := _stock() var balance_before: int = _runtime.economy_service.get_balance(&"PLAYER_CASH") var quote: Dictionary = _runtime.preview_supply_purchase(_warehouse, _item, 2) _clock.set_paused(false) _panel.purchase_button.pressed.emit() var pending_before: int = _runtime.command_queue.create_snapshot().get("pending", []).size() _panel.submit_purchase() _expect(pending_before == 1 and _runtime.command_queue.create_snapshot().get("pending", []).size() == 1, "repeated purchase cannot enqueue the same draft twice") var saved: Dictionary = _runtime.save_to_path(_save_path) _expect(bool(saved.get(&"ok", false)), "queued purchase saves to an isolated test slot") _clock.advance_minutes(1) var loaded: Dictionary = _runtime.load_from_path(_save_path) _expect(bool(loaded.get(&"ok", false)), "pending purchase reloads successfully") _panel.refresh() _expect(_panel.purchase_button.disabled, "restored pending purchase cannot be resubmitted") _clock.advance_minutes(1) _clock.set_paused(true) _panel.refresh() _expect(_stock() == stock_before + 2 and _runtime.economy_service.get_balance(&"PLAYER_CASH") == balance_before - int(quote.get(&"total_cost", -1)), "restored purchase credits and charges exactly once") _expect(not _panel.purchase_button.disabled, "completed restored command releases purchase controls") var digest: String = _runtime.latest_digest _panel.refresh() _panel.select_tab(&"delivery") _expect(_runtime.latest_digest == digest, "displaying stock and deliveries never mutates simulation") _expect(not (_panel.get_report().get(&"deliveries", []) as Array).is_empty(), "real warehouse stock creates visible kitchen replenishment requests") _expect("倉庫" in _panel.delivery_label.text and "厨房" in _panel.delivery_label.text, "delivery page resolves source and destination to identifiable facilities") _expect("運搬員" in _panel.delivery_label.text and "経路" in _panel.delivery_label.text, "waiting delivery explains the actual porter or route shortage in Japanese") func _test_navigation_and_layout() -> void: _main.call("_activate_management_mode", &"ledger") _expect(not _panel.visible and (_main.get("operating_ledger_panel") as Control).visible, "ledger replaces supply controls") _main.call("_unhandled_key_input", _key(KEY_H)) _expect(not _panel.visible and (_main.get("staff_candidate_panel") as Control).visible, "H returns to the hiring candidates") _main.call("_activate_management_mode", &"product") 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 keeps supply inspector clear of opening guidance") _expect(_panel.get_global_rect().position.x >= side.get_global_rect().position.x and _panel.get_global_rect().end.x <= side.get_global_rect().end.x, "supply tabs and inputs fit inside the existing sidebar width") if OS.get_environment("THE_TREE_SUPPLY_UI_CAPTURE") == "1": for tab: StringName in [&"purchase", &"kitchen", &"delivery"]: _panel.select_tab(tab) if tab == &"kitchen": _choose(_panel.kitchen_option, _kitchens[0]) await process_frame await RenderingServer.frame_post_draw var captured := root.get_texture().get_image() captured.save_png("/tmp/the-tree-supply-%s.png" % tab) if tab == &"purchase": captured.save_png("/tmp/the-tree-supply-management.png") if OS.get_environment("THE_TREE_PANEL_SKIN_CAPTURE") == "1": _main.call("_set_layer", 1) _panel.select_tab(&"kitchen") _choose(_panel.kitchen_option, _kitchens[0]) await process_frame;await RenderingServer.frame_post_draw _expect(root.get_texture().get_image().save_png(ProjectSettings.globalize_path("res://artifacts/facility-dimensions-2026-09-29/supply-skin-back.png")) == OK, "capture BACK management skin") _main.call("_unhandled_key_input", _key(KEY_ESCAPE)) _expect(not _panel.visible and not bool(_main.get("_management_panel_open")), "Escape closes supply management and restores the map") func _stock() -> int: var facility: FacilityInstance = _runtime.facility_service.get_instance(_warehouse) return _runtime.inventory_service.total_quantity(facility.local_inventory_id, _item) func _kitchen_row(id: StringName) -> Dictionary: for row: Dictionary in _runtime.get_supply_management_report().get(&"kitchens", []): if StringName(row.get(&"facility_id", &"")) == id: return row return {} 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 facility appears in the relevant supply dropdown: %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) var teardown: Dictionary = await AudioTeardown.free_owner_and_wait(self, _main) _expect(bool(teardown.get(&"passed", false)) and not bool(teardown.get(&"deadline_reached", true)), "owned audio references release before bounded teardown deadline with whole Runtime unchanged") print("Supply management UI: %d checks, %d failures" % [_checks, _failures]) quit(1 if _failures > 0 else 0)