neon-sprawl/client/test/gather_feedback_refresh_tes...

169 lines
5.3 KiB
GDScript

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 pending_gather_interactable_id: String = ""
var awaiting_inventory_finalize: bool = false
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 queue_resource_gather(interactable_id: String) -> void:
pending_gather_interactable_id = interactable_id
awaiting_inventory_finalize = false
func _clear_gather_session() -> void:
pending_gather_interactable_id = ""
awaiting_inventory_finalize = false
func _on_interaction_result(
interactable_id: String, allowed: bool, _reason_code: String
) -> void:
if pending_gather_interactable_id.is_empty():
return
if interactable_id != pending_gather_interactable_id:
if awaiting_inventory_finalize:
return
_clear_gather_session()
return
if not Picker.is_resource_node_id([], interactable_id):
_clear_gather_session()
return
if not allowed:
_clear_gather_session()
return
awaiting_inventory_finalize = true
_inventory.request_sync_from_server()
_skill.request_sync_from_server()
func post_resource_alpha() -> void:
queue_resource_gather("prototype_resource_node_alpha")
_ix.call("post_interact_id", "prototype_resource_node_alpha")
func emit_terminal_allowed() -> void:
_ix.set("_current_interactable_id", "prototype_terminal")
var body_bytes: PackedByteArray = '{"schemaVersion":1,"allowed":true}'.to_utf8_buffer()
_ix.call("_on_request_completed", 0, 200, PackedStringArray(), body_bytes)
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
await assert_signal(harness._ix).is_emitted(
"interaction_result_received", "prototype_resource_node_alpha", true, ""
)
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)
func test_terminal_result_clears_orphaned_gather_pending() -> void:
# Arrange
var transport := MockInteractTransport.new()
var harness := GatherRefreshHarness.new()
auto_free(transport)
auto_free(harness)
add_child(harness)
harness.setup(self, transport)
harness.queue_resource_gather("prototype_resource_node_alpha")
# Act
harness.emit_terminal_allowed()
# Assert
assert_that(harness.pending_gather_interactable_id).is_empty()
assert_that(harness.awaiting_inventory_finalize).is_false()
assert_that(harness._inventory.sync_calls).is_equal(0)
assert_that(harness._skill.sync_calls).is_equal(0)
func test_terminal_after_gather_success_keeps_awaiting_inventory() -> void:
# Arrange
var transport := MockInteractTransport.new()
var harness := GatherRefreshHarness.new()
auto_free(transport)
auto_free(harness)
add_child(harness)
harness.setup(self, transport)
# Act
harness.post_resource_alpha()
harness.emit_terminal_allowed()
# Assert
assert_that(harness.awaiting_inventory_finalize).is_true()
assert_that(harness.pending_gather_interactable_id).is_equal("prototype_resource_node_alpha")
assert_that(harness._inventory.sync_calls).is_equal(1)
assert_that(harness._skill.sync_calls).is_equal(1)