extends GdUnitTestSuite ## NEO-97: `NpcRuntimeClient` GET parse + row helpers. const NpcRuntimeClient := preload("res://scripts/npc_runtime_client.gd") 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 static func _runtime_snapshot_json() -> String: return ( '{"schemaVersion":1,"serverTimeUtc":"2026-05-29T12:00:00Z","npcInstances":[' + '{"npcInstanceId":"prototype_npc_elite","behaviorDefId":"prototype_elite_boss",' + '"state":"telegraph_windup","aggroHolderPlayerId":"dev-local-1",' + '"activeTelegraph":{"telegraphId":"prototype_elite_slam","npcInstanceId":' + '"prototype_npc_elite","windupRemainingSeconds":2.5,"archetypeKind":"elite"}},' + '{"npcInstanceId":"prototype_npc_melee","behaviorDefId":"prototype_melee_rush",' + '"state":"idle","aggroHolderPlayerId":null,"activeTelegraph":null}' + "]}" ) func _make_client(transport: Node) -> Node: var c: Node = NpcRuntimeClient.new() c.set("injected_http", transport) auto_free(transport) auto_free(c) add_child(c) return c func test_request_sync_gets_npc_runtime_snapshot_url() -> void: # Arrange var transport := MockHttpTransport.new() transport.body_json = _runtime_snapshot_json() var c := _make_client(transport) # Act c.call("request_sync_from_server") # Assert assert_that(transport.last_url).contains("/game/world/npc-runtime-snapshot") func test_runtime_received_emits_parsed_snapshot() -> void: # Arrange var transport := MockHttpTransport.new() transport.body_json = _runtime_snapshot_json() var c := _make_client(transport) var got: Array = [] c.connect("runtime_received", func(snapshot: Dictionary) -> void: got.append(snapshot)) # Act c.call("request_sync_from_server") # Assert assert_that(got.size()).is_equal(1) var instances: Variant = (got[0] as Dictionary).get("npcInstances", null) assert_that(instances is Array).is_true() assert_that((instances as Array).size()).is_equal(2) func test_npc_row_returns_elite_telegraph_fields() -> void: # Arrange var parsed: Variant = NpcRuntimeClient.parse_runtime_json(_runtime_snapshot_json()) # Act var row: Dictionary = NpcRuntimeClient.npc_row( "prototype_npc_elite", parsed as Dictionary ) # Assert assert_that(str(row.get("state", ""))).is_equal("telegraph_windup") var telegraph: Variant = row.get("activeTelegraph", null) assert_that(telegraph is Dictionary).is_true() assert_that(float((telegraph as Dictionary).get("windupRemainingSeconds", 0.0))).is_equal(2.5) func test_row_for_aggro_holder_returns_elite_row() -> void: # Arrange var parsed: Variant = NpcRuntimeClient.parse_runtime_json(_runtime_snapshot_json()) # Act var row: Dictionary = NpcRuntimeClient.row_for_aggro_holder( "dev-local-1", parsed as Dictionary ) # Assert assert_that(str(row.get("npcInstanceId", ""))).is_equal("prototype_npc_elite") func test_npc_row_falls_back_to_last_snapshot_on_instance() -> void: # Arrange var transport := MockHttpTransport.new() transport.body_json = _runtime_snapshot_json() var c := _make_client(transport) var got: Array = [] c.connect("runtime_received", func(snapshot: Dictionary) -> void: got.append(snapshot)) c.call("request_sync_from_server") # Act var row: Dictionary = c.call("npc_row", "prototype_npc_elite") as Dictionary # Assert assert_that(str(row.get("state", ""))).is_equal("telegraph_windup") func test_invalid_schema_emits_sync_failed() -> void: # Arrange var transport := MockHttpTransport.new() transport.body_json = '{"schemaVersion":2,"npcInstances":[]}' var c := _make_client(transport) var failed: Array = [] c.connect("runtime_sync_failed", func(reason: String) -> void: failed.append(reason)) # Act c.call("request_sync_from_server") # Assert assert_that(failed.size()).is_equal(1) assert_that(str(failed[0])).contains("schemaVersion")