using System.Net.Http.Json; using System.Text.Json; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using TermRemoteCtl.Agent.History; using TermRemoteCtl.Agent.Sessions; namespace TermRemoteCtl.Agent.IntegrationTests; public sealed class SessionHistoryApiTests { private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); [Fact] public async Task GetHistory_Returns_Recent_Lines_And_HasMoreAbove() { await using var fixture = new AgentFixture(); using var client = fixture.CreateClient(); var registry = fixture.Services.GetRequiredService(); var session = registry.Create("codex-main", DateTimeOffset.UtcNow); await registry.AppendOutputAsync(session.SessionId, "one\ntwo\nthree\n", CancellationToken.None); var response = await client.GetFromJsonAsync( $"/api/sessions/{session.SessionId}/history?lineCount=2", JsonOptions); Assert.NotNull(response); Assert.Equal(session.SessionId, response!.SessionId); Assert.Equal(["two", "three"], response.Lines); Assert.True(response.HasMoreAbove); } private sealed class AgentFixture : WebApplicationFactory { private readonly string _dataRoot = Path.Combine(Path.GetTempPath(), "TermRemoteCtl.Tests", Guid.NewGuid().ToString("N")); protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.UseEnvironment("Development"); builder.ConfigureAppConfiguration((_, configBuilder) => { configBuilder.AddInMemoryCollection(new Dictionary { ["Agent:DataRoot"] = _dataRoot, ["Agent:BindAddress"] = "127.0.0.1", ["Agent:HttpsPort"] = "9443", ["Agent:WebSocketFrameFlushMilliseconds"] = "33", ["Agent:RingBufferLineLimit"] = "4000" }); }); } public new async ValueTask DisposeAsync() { await base.DisposeAsync(); if (Directory.Exists(_dataRoot)) { Directory.Delete(_dataRoot, true); } } } private sealed record SessionHistoryResponse(string SessionId, IReadOnlyList Lines, bool HasMoreAbove); }