using System.Net; using System.Text; using Microsoft.Extensions.Configuration; using Nexus.Api.Services; using Xunit; namespace Nexus.Api.Tests; public sealed class OpenClawGatewayClientTests { [Fact] public async Task GetSessionHistoryAsync_ProjectsOnlyUserAndAssistantText() { var client = CreateClient( """ { "ok": true, "result": { "details": { "messages": [ { "role": "user", "content": [{ "type": "text", "text": "Plan the release" }], "timestamp": "2026-07-30T10:00:00Z" }, { "role": "assistant", "content": [ { "type": "text", "text": "Release" }, { "type": "text", "text": "planned" }, { "type": "toolCall", "name": "ignored" } ], "timestamp": "2026-07-30T10:01:00Z" }, { "role": "tool", "content": [{ "type": "text", "text": "hidden tool output" }] } ] } } } """); var history = await client.GetSessionHistoryAsync("agent:iris:main"); Assert.Collection( history, message => { Assert.Equal("user", message.Role); Assert.Equal("Plan the release", message.Content); }, message => { Assert.Equal("assistant", message.Role); Assert.Equal("Release planned", message.Content); }); } [Fact] public async Task GetSessionHistoryAsync_GatewayFailureReturnsNoFabricatedMessages() { var configuration = new ConfigurationBuilder().Build(); var httpClient = new HttpClient(new StubHandler(_ => new HttpResponseMessage(HttpStatusCode.ServiceUnavailable))) { BaseAddress = new Uri("http://gateway.local") }; var client = new OpenClawGatewayClient(httpClient, configuration); var history = await client.GetSessionHistoryAsync("agent:iris:main"); Assert.Empty(history); } private static OpenClawGatewayClient CreateClient(string responseJson) { var configuration = new ConfigurationBuilder().Build(); var httpClient = new HttpClient(new StubHandler(_ => new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(responseJson, Encoding.UTF8, "application/json") })) { BaseAddress = new Uri("http://gateway.local") }; return new OpenClawGatewayClient(httpClient, configuration); } private sealed class StubHandler( Func responder) : HttpMessageHandler { protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) => Task.FromResult(responder(request)); } }