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.
111 lines
7.6 KiB
GDScript
111 lines
7.6 KiB
GDScript
extends SceneTree
|
|
const FixtureCleanup := preload("res://tests/helpers/ui_audio_fixture_cleanup.gd")
|
|
var checks := 0
|
|
var failures := 0
|
|
func expect(ok: bool, message: String) -> void:
|
|
checks += 1
|
|
if not ok: failures += 1; push_error(message)
|
|
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(); runtime.initialize(clock,state,42601); clock.set_paused(true)
|
|
root.size = Vector2i(1280,720)
|
|
var main: Control = load("res://scenes/main/main.tscn").instantiate()
|
|
var path := "user://tests/anri-recruitment-%d" % Time.get_ticks_usec()
|
|
main.manual_save_path = path
|
|
root.add_child(main)
|
|
runtime.configure_save_policy({&"enabled":false,&"daily_checkpoint_enabled":false})
|
|
await process_frame; await process_frame
|
|
var before: Dictionary = runtime.create_snapshot()
|
|
var economy_before: Dictionary = runtime.economy_service.create_snapshot()
|
|
main.staff_candidate_toggle_button.pressed.emit()
|
|
var button: Button = main.staff_candidate_buttons.get(&"heroine_anri")
|
|
expect(button != null and button.text == "無料で加入" and button.is_visible_in_tree(), "normal staff screen offers Anri free recruitment")
|
|
clock.set_paused(false)
|
|
button.pressed.emit()
|
|
clock.set_paused(true)
|
|
expect(button.disabled and not runtime.staff_service.has_staff(&"heroine_anri"), "running game queues recruitment without premature joining")
|
|
button.pressed.emit()
|
|
expect(runtime.command_queue.create_snapshot()["pending"].size() == 1, "repeated UI action does not duplicate recruitment")
|
|
main.call("_save_manual")
|
|
expect(SaveService.load_snapshot(path)[&"ok"], "pending Anri recruitment saves through normal UI")
|
|
expect(runtime.restore_snapshot(before), "restore control before loading pending recruitment")
|
|
main.call("_load_manual")
|
|
clock.advance_one_minute()
|
|
var anri: StaffRuntime = runtime.staff_service.get_staff(&"heroine_anri")
|
|
expect(anri != null and anri.role_id == &"innkeeper" and anri.employment_kind == StaffRuntime.EmploymentKind.UNIQUE, "restored request creates canonical unique innkeeper")
|
|
expect(runtime.economy_service.create_snapshot() == economy_before and anri.daily_wage == 0, "joining costs no cash and creates no daily wage")
|
|
expect(button.disabled and button.text == "加入済み", "joined unique cannot be recruited twice in UI")
|
|
main.staff_management_toggle_button.pressed.emit()
|
|
var panel: StaffManagementPanel = main.find_child("StaffManagementPanel",true,false)
|
|
panel.select_staff(&"heroine_anri")
|
|
expect(panel.staff_detail_label.text.contains("アンリ") and panel.staff_detail_label.text.contains("女将") and panel.staff_detail_label.text.contains("日給 G0"), "staff screen uses unique name role and zero upkeep")
|
|
main.call("_save_manual")
|
|
var joined: Dictionary = runtime.create_snapshot()
|
|
expect(runtime.restore_snapshot(before), "restore pre-join control")
|
|
main.call("_load_manual")
|
|
expect(runtime.staff_service.has_staff(&"heroine_anri") and runtime.get_hired_staff_candidate_ids().has(&"heroine_anri"), "normal load restores unique identity and recruitment history")
|
|
expect(not runtime.staff_service.retire_staff(&"heroine_anri").is_success(), "recruited Anri cannot retire")
|
|
var invalid := joined.duplicate(true)
|
|
for row: Dictionary in invalid[&"systems"][&"runtime"][&"staff"][&"staff"]:
|
|
if row[&"staff_id"] == "heroine_anri": row[&"employment_kind"] = "FREE_HIRE"
|
|
var intact: Dictionary = runtime.create_snapshot()
|
|
expect(not runtime.restore_snapshot(invalid) and runtime.create_snapshot() == intact, "save cannot downgrade Anri to removable generic employment")
|
|
# Place the recruited manager through the normal staff controls.
|
|
for build: Array in [[&"reception",Vector3i(-6,0,0)],[&"public_bath",Vector3i(1,0,0)]]:
|
|
main.call("_select_build_definition", build[0])
|
|
main.call("_on_map_cell_clicked", build[1])
|
|
clock.advance_minutes(runtime.definition_registry.get_facility(build[0]).build_minutes)
|
|
var reception: StringName = &""
|
|
var bath: StringName = &""
|
|
for facility: FacilityInstance in runtime.facility_service.get_instances():
|
|
if facility.definition_id==&"reception": reception=facility.instance_id
|
|
if facility.definition_id==&"public_bath": bath=facility.instance_id
|
|
expect(not reception.is_empty() and not bath.is_empty(), "normal UI builds manager workplace and same-floor service")
|
|
panel.refresh(); panel.select_staff(&"heroine_anri")
|
|
for i in panel.facility_option.item_count:
|
|
if panel.facility_option.get_item_metadata(i)==reception:
|
|
panel.facility_option.select(i); panel.facility_option.item_selected.emit(i)
|
|
panel.apply_button.pressed.emit()
|
|
expect(runtime.staff_service.get_work_assignment(&"heroine_anri").get(&"facility_id")==reception, "normal staff controls place unique innkeeper")
|
|
var reception_instance: FacilityInstance=runtime.facility_service.get_instance(reception)
|
|
expect(reception_instance.active_staff_ids.is_empty(), "Anri does not meet the receptionist staffing requirement")
|
|
expect(not main.opening_guide._has_reception_assignment(reception_instance), "opening guide does not mistake innkeeper placement for receptionist coverage")
|
|
var manager_only: Dictionary=runtime.create_snapshot()
|
|
main.call("_hire_staff_candidate", &"staff_akane")
|
|
panel.refresh();panel.select_staff(&"staff_akane")
|
|
for i in panel.facility_option.item_count:
|
|
if panel.facility_option.get_item_metadata(i)==reception:
|
|
panel.facility_option.select(i);panel.facility_option.item_selected.emit(i)
|
|
panel.apply_button.pressed.emit()
|
|
expect(main.opening_guide._has_reception_assignment(reception_instance), "actual receptionist placement satisfies opening guide")
|
|
expect(runtime.restore_snapshot(manager_only), "restore manager-only workplace after receptionist comparison")
|
|
expect(not main.opening_guide._has_reception_assignment(runtime.facility_service.get_instance(reception)), "loading manager-only placement restores unsatisfied receptionist guidance")
|
|
main.navigation_buttons[&"business"].pressed.emit()
|
|
var business: BusinessManagementPanel = main.find_child("BusinessManagementPanel",true,false)
|
|
business.refresh()
|
|
for i in business.facility_option.item_count:
|
|
if business.facility_option.get_item_metadata(i)==bath:
|
|
business.facility_option.select(i); business.facility_option.item_selected.emit(i)
|
|
expect("24G" in business.quote_label.text and "アンリ配置フロア" in business.effect_label.text, "normal business screen explains current20percent floor price")
|
|
for i in business.price_option.item_count:
|
|
if business.price_option.get_item_metadata(i)==&"expensive":
|
|
business.price_option.select(i); business.price_option.item_selected.emit(i)
|
|
business.refresh()
|
|
expect("設定後 36G" in business.quote_label.text, "draft150percent policy combines with Anri120percent consistently")
|
|
if OS.get_environment("THE_TREE_ANRI_CAPTURE") == "1":
|
|
if not panel.visible: main.staff_management_toggle_button.pressed.emit()
|
|
panel.select_staff(&"heroine_anri")
|
|
expect(panel.is_visible_in_tree(), "recruited staff panel visible for rendered inspection")
|
|
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/anri-floor-assigned.png")) == OK, "capture recruited Anri")
|
|
SaveService.delete_save(path)
|
|
var cleanup: Dictionary = await FixtureCleanup.free_owner_and_wait(self, main)
|
|
if not bool(cleanup.get(&"passed", false)):
|
|
push_error("Anri recruitment ordinary owner cleanup failed: %s" % str(cleanup))
|
|
quit(96)
|
|
return
|
|
print("Anri recruitment UI: %d checks, %d failures" % [checks,failures]); quit(failures)
|