neon-sprawl/client/test/interaction_request_client_...

167 lines
4.9 KiB
GDScript

extends GdUnitTestSuite
## NEO-25 / NEO-73: `InteractionRequestClient` POST bodies, result/failure signals.
const IxClient := preload("res://scripts/interaction_request_client.gd")
class MockHttpTransport:
extends Node
signal request_completed(
result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray
)
var last_url: String = ""
var last_body: String = ""
var last_method: HTTPClient.Method = HTTPClient.Method.METHOD_GET
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.METHOD_GET,
request_data: String = ""
) -> Error:
last_url = url
last_body = request_data
last_method = method
var body_bytes: PackedByteArray = body_json.to_utf8_buffer()
request_completed.emit(
HTTPRequest.RESULT_SUCCESS, response_code, PackedStringArray(), body_bytes
)
return OK
## First POST defers completion one frame so a second press can queue as `_pending_interactable_id`.
class HoldFirstThenAutoTransport:
extends Node
signal request_completed(
result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray
)
var bodies: Array[String] = []
var _first: bool = true
func request(
_url: String,
_custom_headers: PackedStringArray = PackedStringArray(),
_method: HTTPClient.Method = HTTPClient.METHOD_GET,
request_data: String = ""
) -> Error:
bodies.append(request_data)
var body_bytes: PackedByteArray = '{"schemaVersion":1,"allowed":true}'.to_utf8_buffer()
if _first:
_first = false
call_deferred("_emit", body_bytes)
else:
request_completed.emit(HTTPRequest.RESULT_SUCCESS, 200, PackedStringArray(), body_bytes)
return OK
func _emit(body_bytes: PackedByteArray) -> void:
request_completed.emit(HTTPRequest.RESULT_SUCCESS, 200, PackedStringArray(), body_bytes)
func _make_ix(transport: Node) -> Node:
var ix: Node = IxClient.new()
ix.set("injected_http", transport)
auto_free(transport)
auto_free(ix)
add_child(ix)
return ix
func test_post_terminal_body_contains_prototype_terminal() -> void:
# Arrange
var transport := MockHttpTransport.new()
var ix := _make_ix(transport)
# Act
ix.call("_post_interact", "prototype_terminal")
# Assert
assert_that(transport.last_body).contains("prototype_terminal")
assert_that(transport.last_url).contains("/interact")
func test_post_resource_body_contains_resource_node_id() -> void:
# Arrange
var transport := MockHttpTransport.new()
var ix := _make_ix(transport)
# Act
ix.call("_post_interact", "prototype_resource_node_alpha")
# Assert
assert_that(transport.last_body).contains("prototype_resource_node_alpha")
func test_post_interact_terminal_public_entrypoint() -> void:
# Arrange
var transport := MockHttpTransport.new()
var ix := _make_ix(transport)
# Act
ix.call("post_interact_terminal")
# Assert
assert_that(transport.last_body).contains("prototype_terminal")
func test_post_interact_resource_public_entrypoint() -> void:
# Arrange
var transport := MockHttpTransport.new()
var ix := _make_ix(transport)
# Act
ix.call("post_interact_resource")
# Assert
assert_that(transport.last_body).contains("prototype_resource_node_alpha")
func test_interaction_result_emits_allow_signal() -> void:
# Arrange
var transport := MockHttpTransport.new()
var ix := _make_ix(transport)
monitor_signals(ix)
# Act
ix.call("post_interact_id", "prototype_resource_node_alpha")
# Assert
await assert_signal(ix).is_emitted(
"interaction_result_received", "prototype_resource_node_alpha", true, ""
)
func test_interaction_result_emits_deny_signal() -> void:
# Arrange
var transport := MockHttpTransport.new()
transport.body_json = '{"schemaVersion":1,"allowed":false,"reasonCode":"node_depleted"}'
var ix := _make_ix(transport)
monitor_signals(ix)
# Act
ix.call("post_interact_id", "prototype_urban_bulk_delta")
# Assert
await assert_signal(ix).is_emitted(
"interaction_result_received", "prototype_urban_bulk_delta", false, "node_depleted"
)
func test_interaction_request_failed_emits_on_http_error() -> void:
# Arrange
var transport := MockHttpTransport.new()
transport.response_code = 500
var ix := _make_ix(transport)
monitor_signals(ix)
# Act
ix.call("post_interact_id", "prototype_resource_node_alpha")
# Assert
await assert_signal(ix).is_emitted(
"interaction_request_failed", "prototype_resource_node_alpha", "HTTP 500"
)
func test_last_wins_second_press_before_first_completes() -> void:
# Arrange
var transport := HoldFirstThenAutoTransport.new()
var ix := _make_ix(transport)
# Act
ix.call("_post_interact", "prototype_terminal")
ix.call("_post_interact", "prototype_resource_node_alpha")
await get_tree().process_frame
await get_tree().process_frame
# Assert
assert_that(transport.bodies.size()).is_equal(2)
assert_that(transport.bodies[0]).contains("prototype_terminal")
assert_that(transport.bodies[1]).contains("prototype_resource_node_alpha")