extends GdUnitTestSuite ## NEO-142: `FactionStandingClient` GET parse + failure signals. const FactionStandingClient := preload("res://scripts/faction_standing_client.gd") var _standing_capture: Dictionary = {} func _capture_standing(snapshot: Dictionary) -> void: _standing_capture = snapshot class MockHttpTransport: extends Node signal request_completed( result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray ) var last_url: String = "" var response_code: int = 200 var body_json: String = "" func request( url: String, _custom_headers: PackedStringArray = PackedStringArray(), _method: HTTPClient.Method = HTTPClient.METHOD_GET, _request_data: String = "" ) -> Error: last_url = url request_completed.emit( HTTPRequest.RESULT_SUCCESS, response_code, PackedStringArray(), body_json.to_utf8_buffer() ) return OK class PendingSyncHttpTransport: extends Node signal request_completed( result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray ) var request_count: int = 0 var response_code: int = 200 var body_json: String = "" func request( _url: String, _custom_headers: PackedStringArray = PackedStringArray(), _method: HTTPClient.Method = HTTPClient.METHOD_GET, _request_data: String = "" ) -> Error: request_count += 1 return OK func complete_pending() -> void: request_completed.emit( HTTPRequest.RESULT_SUCCESS, response_code, PackedStringArray(), body_json.to_utf8_buffer() ) static func _default_standing_json() -> String: return ( '{"schemaVersion":1,"playerId":"dev-local-1","factions":[' + '{"id":"prototype_faction_grid_operators","standing":0},' + '{"id":"prototype_faction_rust_collective","standing":0}' + "]}" ) static func _post_operator_chain_standing_json() -> String: return ( '{"schemaVersion":1,"playerId":"dev-local-1","factions":[' + '{"id":"prototype_faction_rust_collective","standing":0},' + '{"id":"prototype_faction_grid_operators","standing":15}' + "]}" ) func _make_client(transport: Node) -> Node: var c: Node = FactionStandingClient.new() c.set("injected_http", transport) auto_free(transport) auto_free(c) add_child(c) return c func test_parse_faction_standing_json_reads_grid_operators_row() -> void: # Arrange var json := _post_operator_chain_standing_json() # Act var snapshot: Variant = FactionStandingClient.parse_faction_standing_json(json) # Assert assert_that(snapshot is Dictionary).is_true() ( assert_that( FactionStandingClient.standing_for( FactionStandingClient.GRID_OPERATORS_ID, snapshot as Dictionary ) ) . is_equal(15) ) func test_parse_faction_standing_json_rejects_bad_schema() -> void: # Arrange var json := '{"schemaVersion":2,"playerId":"dev-local-1","factions":[]}' # Act var snapshot: Variant = FactionStandingClient.parse_faction_standing_json(json) # Assert assert_that(snapshot).is_null() func test_standing_for_defaults_to_zero_when_row_missing() -> void: # Arrange var snapshot := {"schemaVersion": 1, "playerId": "dev-local-1", "factions": []} # Act var standing: int = FactionStandingClient.standing_for( FactionStandingClient.GRID_OPERATORS_ID, snapshot ) # Assert assert_that(standing).is_equal(0) func test_display_name_for_prototype_factions() -> void: # Arrange # Act var grid_label := FactionStandingClient.display_name_for( FactionStandingClient.GRID_OPERATORS_ID ) var rust_label := FactionStandingClient.display_name_for( FactionStandingClient.RUST_COLLECTIVE_ID ) # Assert assert_str(grid_label).is_equal("Grid Operators") assert_str(rust_label).is_equal("Rust Collective") func test_request_sync_emits_faction_standing_received() -> void: # Arrange _standing_capture = {} var transport := MockHttpTransport.new() transport.body_json = _default_standing_json() var c := _make_client(transport) c.connect("faction_standing_received", Callable(self, "_capture_standing")) monitor_signals(c) # Act c.call("request_sync_from_server") # Assert assert_signal(c).is_emitted("faction_standing_received", any()) assert_that(_standing_capture.has("factions")).is_true() assert_that(transport.last_url).contains("/faction-standing") func test_http_404_emits_faction_standing_sync_failed() -> void: # Arrange var transport := MockHttpTransport.new() transport.response_code = 404 var c := _make_client(transport) monitor_signals(c) # Act c.call("request_sync_from_server") # Assert assert_signal(c).is_emitted("faction_standing_sync_failed", "HTTP 404 (player unknown)") func test_request_sync_queues_while_busy_and_flushes_after_completion() -> void: # Arrange var transport := PendingSyncHttpTransport.new() transport.body_json = _default_standing_json() var c := _make_client(transport) # Act c.call("request_sync_from_server") c.call("request_sync_from_server") # Assert assert_that(transport.request_count).is_equal(1) transport.complete_pending() assert_that(transport.request_count).is_equal(2)