extends GdUnitTestSuite ## NEO-73: allowed resource-node interact triggers inventory + skill refresh. const IxClient := preload("res://scripts/interaction_request_client.gd") const InventoryClient := preload("res://scripts/inventory_client.gd") const SkillProgressionClient := preload("res://scripts/skill_progression_client.gd") const Picker := preload("res://scripts/prototype_interactable_picker.gd") class MockInteractTransport: extends Node signal request_completed( result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray ) var last_body: String = "" var body_json: String = '{"schemaVersion":1,"allowed":true}' var response_code: int = 200 func request( _url: String, _custom_headers: PackedStringArray = PackedStringArray(), _method: HTTPClient.Method = HTTPClient.METHOD_POST, request_data: String = "" ) -> Error: last_body = request_data var body_bytes: PackedByteArray = body_json.to_utf8_buffer() request_completed.emit( HTTPRequest.RESULT_SUCCESS, response_code, PackedStringArray(), body_bytes ) return OK class SpySyncClient: extends Node var sync_calls: int = 0 func request_sync_from_server() -> void: sync_calls += 1 class GatherRefreshHarness: extends Node var inventory_sync_calls: int = 0 var skill_sync_calls: int = 0 var _inventory: SpySyncClient var _skill: SpySyncClient var _ix: Node func setup(parent: Node, ix_transport: Node) -> void: _inventory = SpySyncClient.new() _skill = SpySyncClient.new() _ix = IxClient.new() _ix.set("injected_http", ix_transport) parent.add_child(_ix) parent.add_child(_inventory) parent.add_child(_skill) _ix.connect("interaction_result_received", Callable(self, "_on_interaction_result")) func _on_interaction_result( interactable_id: String, allowed: bool, _reason_code: String ) -> void: if not Picker.is_resource_node_id([], interactable_id): return if not allowed: return _inventory.request_sync_from_server() _skill.request_sync_from_server() func post_resource_alpha() -> void: _ix.call("post_interact_id", "prototype_resource_node_alpha") func test_allowed_resource_interact_triggers_both_refreshes() -> void: # Arrange var transport := MockInteractTransport.new() var harness := GatherRefreshHarness.new() auto_free(transport) auto_free(harness) add_child(harness) harness.setup(self, transport) monitor_signals(harness._ix) # Act harness.post_resource_alpha() # Assert assert_signal(harness._ix).is_emitted("interaction_result_received") assert_that(harness._inventory.sync_calls).is_equal(1) assert_that(harness._skill.sync_calls).is_equal(1) func test_denied_resource_interact_skips_refreshes() -> void: # Arrange var transport := MockInteractTransport.new() transport.body_json = '{"schemaVersion":1,"allowed":false,"reasonCode":"node_depleted"}' var harness := GatherRefreshHarness.new() auto_free(transport) auto_free(harness) add_child(harness) harness.setup(self, transport) # Act harness.post_resource_alpha() # Assert assert_that(harness._inventory.sync_calls).is_equal(0) assert_that(harness._skill.sync_calls).is_equal(0)