145 lines
4.4 KiB
GDScript
145 lines
4.4 KiB
GDScript
extends GdUnitTestSuite
|
|
|
|
## NEO-74: `CraftClient` POST payload + success/deny parse (craft panel wiring tested separately).
|
|
|
|
const CraftClient := preload("res://scripts/craft_client.gd")
|
|
|
|
var _failed_reason: String = ""
|
|
var _failed_recipe_id: String = ""
|
|
|
|
|
|
func _capture_failed(recipe_id: String, reason: String) -> void:
|
|
_failed_recipe_id = recipe_id
|
|
_failed_reason = reason
|
|
|
|
|
|
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 response_code: int = 200
|
|
var body_json: String = ""
|
|
|
|
func request(
|
|
url: String,
|
|
_custom_headers: PackedStringArray = PackedStringArray(),
|
|
_method: HTTPClient.Method = HTTPClient.METHOD_POST,
|
|
request_data: String = ""
|
|
) -> Error:
|
|
last_url = url
|
|
last_body = request_data
|
|
request_completed.emit(
|
|
HTTPRequest.RESULT_SUCCESS,
|
|
response_code,
|
|
PackedStringArray(),
|
|
body_json.to_utf8_buffer()
|
|
)
|
|
return OK
|
|
|
|
|
|
static func _success_craft_json() -> String:
|
|
return (
|
|
'{"schemaVersion":1,"success":true,"reasonCode":null,'
|
|
+ '"inputsConsumed":[{"itemId":"scrap_metal_bulk","quantity":5}],'
|
|
+ '"outputsGranted":[{"itemId":"refined_plate_stock","quantity":1}],'
|
|
+ '"xpGrantSummary":{"skillId":"refine","amount":10,"sourceKind":"craft_refine"}}'
|
|
)
|
|
|
|
|
|
func _make_client(transport: Node) -> Node:
|
|
var c: Node = CraftClient.new()
|
|
c.set("injected_http", transport)
|
|
auto_free(transport)
|
|
auto_free(c)
|
|
add_child(c)
|
|
return c
|
|
|
|
|
|
func test_request_craft_posts_recipe_id_and_schema_version() -> void:
|
|
# Arrange
|
|
var transport := MockHttpTransport.new()
|
|
transport.body_json = _success_craft_json()
|
|
var c := _make_client(transport)
|
|
# Act
|
|
var started: bool = bool(c.call("request_craft", "refine_scrap_standard", 1))
|
|
# Assert
|
|
assert_that(started).is_true()
|
|
assert_that(transport.last_url).contains("/craft")
|
|
var parsed: Variant = JSON.parse_string(transport.last_body)
|
|
assert_that(parsed is Dictionary).is_true()
|
|
var body: Dictionary = parsed as Dictionary
|
|
assert_that(int(body.get("schemaVersion", -1))).is_equal(1)
|
|
assert_that(str(body.get("recipeId", ""))).is_equal("refine_scrap_standard")
|
|
assert_that(int(body.get("quantity", -1))).is_equal(1)
|
|
|
|
|
|
func test_success_response_emits_craft_result_received() -> void:
|
|
# Arrange
|
|
var transport := MockHttpTransport.new()
|
|
transport.body_json = _success_craft_json()
|
|
var c := _make_client(transport)
|
|
var got: Array = []
|
|
c.connect(
|
|
"craft_result_received",
|
|
func(recipe_id: String, result: Dictionary) -> void: got.append([recipe_id, result])
|
|
)
|
|
# Act
|
|
c.call("request_craft", "refine_scrap_standard")
|
|
# Assert
|
|
assert_that(got.size()).is_equal(1)
|
|
assert_that(str(got[0][0])).is_equal("refine_scrap_standard")
|
|
var result: Dictionary = got[0][1]
|
|
assert_that(bool(result.get("success", false))).is_true()
|
|
var outputs: Variant = result.get("outputsGranted", null)
|
|
assert_that(outputs is Array).is_true()
|
|
assert_that((outputs as Array).size()).is_equal(1)
|
|
|
|
|
|
func test_deny_response_emits_craft_result_with_reason_code() -> void:
|
|
# Arrange
|
|
var transport := MockHttpTransport.new()
|
|
transport.body_json = (
|
|
'{"schemaVersion":1,"success":false,"reasonCode":"insufficient_materials",'
|
|
+ '"inputsConsumed":[],"outputsGranted":[]}'
|
|
)
|
|
var c := _make_client(transport)
|
|
var got: Array = []
|
|
c.connect(
|
|
"craft_result_received",
|
|
func(_recipe_id: String, result: Dictionary) -> void: got.append(result)
|
|
)
|
|
# Act
|
|
c.call("request_craft", "refine_scrap_standard")
|
|
# Assert
|
|
var result: Dictionary = got[0]
|
|
assert_that(bool(result.get("success", true))).is_false()
|
|
assert_that(str(result.get("reasonCode", ""))).is_equal("insufficient_materials")
|
|
|
|
|
|
func test_http_error_emits_craft_request_failed() -> void:
|
|
# Arrange
|
|
_failed_reason = ""
|
|
var transport := MockHttpTransport.new()
|
|
transport.response_code = 404
|
|
var c := _make_client(transport)
|
|
c.connect("craft_request_failed", Callable(self, "_capture_failed"))
|
|
# Act
|
|
c.call("request_craft", "refine_scrap_standard")
|
|
# Assert
|
|
assert_that(_failed_reason).contains("404")
|
|
|
|
|
|
func test_request_craft_clears_busy_after_sync_mock_response() -> void:
|
|
# Arrange
|
|
var transport := MockHttpTransport.new()
|
|
transport.body_json = _success_craft_json()
|
|
var c := _make_client(transport)
|
|
# Act
|
|
var started: bool = bool(c.call("request_craft", "refine_scrap_standard", 1))
|
|
# Assert
|
|
assert_that(started).is_true()
|
|
assert_that(bool(c.call("is_busy"))).is_false()
|