167 lines
4.9 KiB
GDScript
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")
|