neon-sprawl/client/test/craft_feedback_refresh_test.gd

99 lines
2.7 KiB
GDScript

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
await assert_signal(harness._craft).is_emitted(
"craft_result_received", "refine_scrap_standard", any()
)
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)