extends GdUnitTestSuite ## NEO-74: successful craft triggers inventory + skill refresh; deny skips refresh. const CraftClient := preload("res://scripts/craft_client.gd") class MockCraftTransport: extends Node signal request_completed( result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray ) var body_json: String = '{"schemaVersion":1,"success":true,"outputsGranted":[]}' func request( _url: String, _custom_headers: PackedStringArray = PackedStringArray(), _method: HTTPClient.Method = HTTPClient.METHOD_POST, _request_data: String = "" ) -> Error: request_completed.emit( HTTPRequest.RESULT_SUCCESS, 200, PackedStringArray(), body_json.to_utf8_buffer() ) return OK class SpySyncClient: extends Node var sync_calls: int = 0 func request_sync_from_server() -> void: sync_calls += 1 class CraftRefreshHarness: extends Node var inventory_sync_calls: int = 0 var skill_sync_calls: int = 0 var _inventory: SpySyncClient var _skill: SpySyncClient var _craft: Node func setup(parent: Node, transport: Node) -> void: _inventory = SpySyncClient.new() _skill = SpySyncClient.new() _craft = CraftClient.new() _craft.set("injected_http", transport) parent.add_child(_craft) parent.add_child(_inventory) parent.add_child(_skill) _craft.connect("craft_result_received", Callable(self, "_on_craft_result")) func _on_craft_result(_recipe_id: String, result: Dictionary) -> void: if not bool(result.get("success", false)): return _inventory.request_sync_from_server() _skill.request_sync_from_server() func post_craft(recipe_id: String) -> void: _craft.call("request_craft", recipe_id) func test_successful_craft_triggers_both_refreshes() -> void: # Arrange var transport := MockCraftTransport.new() var harness := CraftRefreshHarness.new() auto_free(transport) auto_free(harness) add_child(harness) harness.setup(self, transport) monitor_signals(harness._craft) # Act harness.post_craft("refine_scrap_standard") # Assert assert_signal(harness._craft).is_emitted("craft_result_received") assert_that(harness._inventory.sync_calls).is_equal(1) assert_that(harness._skill.sync_calls).is_equal(1) func test_denied_craft_skips_refreshes() -> void: # Arrange var transport := MockCraftTransport.new() transport.body_json = ( '{"schemaVersion":1,"success":false,"reasonCode":"insufficient_materials",' + '"inputsConsumed":[],"outputsGranted":[]}' ) var harness := CraftRefreshHarness.new() auto_free(transport) auto_free(harness) add_child(harness) harness.setup(self, transport) # Act harness.post_craft("refine_scrap_standard") # Assert assert_that(harness._inventory.sync_calls).is_equal(0) assert_that(harness._skill.sync_calls).is_equal(0)