using System.Net.Http.Json; using System.Text.Json; namespace HSchool.AppHost.Tests; [Collection(AppHostCollection.Name)] public class PersonLogApiTests(AppHostFixture fixture) { private static readonly DateTime Start = new(2012, 4, 3, 6, 0, 0, DateTimeKind.Utc); [Fact] public async Task Card_DoesNotIncludeTheLog() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); var school = await SchoolApiTests.CreateAsync(client, "Карточка без лога", Start, seed: 36); var page = await GetPeopleAsync(client, school.Id); var id = page.People[0].Id; using var response = await client.GetAsync( $"/api/schools/{school.Id}/people/{Uri.EscapeDataString(id)}", TestContext.Current.CancellationToken); response.EnsureSuccessStatusCode(); using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken)); Assert.False(json.RootElement.TryGetProperty("entries", out _)); Assert.False(json.RootElement.TryGetProperty("log", out _)); var log = await client.GetFromJsonAsync( $"/api/schools/{school.Id}/people/{Uri.EscapeDataString(id)}/log?pageSize=20", TestContext.Current.CancellationToken); Assert.NotNull(log); Assert.Equal(1, log.Page); Assert.Equal(20, log.PageSize); Assert.True(log.Total >= 0); Assert.NotNull(log.Entries); } [Fact] public async Task Log_UnknownPerson_IsNotFound() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); var school = await SchoolApiTests.CreateAsync(client, "Лог 404", Start, seed: 36); using var response = await client.GetAsync( $"/api/schools/{school.Id}/people/nobody/log", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); Assert.Equal("unknown-person", await ProblemCodeAsync(response)); } [Fact] public async Task Log_PagesDoNotOverlap() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.ResetAsync(client); var school = await SchoolApiTests.CreateAsync(client, "Лог страницы", Start, seed: 36); var page = await GetPeopleAsync(client, school.Id); var id = page.People[0].Id; var first = await GetLogAsync(client, school.Id, id, "page=1&pageSize=10&dir=asc"); var second = await GetLogAsync(client, school.Id, id, "page=2&pageSize=10&dir=asc"); Assert.Equal(first.Total, second.Total); Assert.Empty(first.Entries.Select(row => (row.Time, row.Type, row.ThingDef)) .Intersect(second.Entries.Select(row => (row.Time, row.Type, row.ThingDef)))); } private static async Task GetPeopleAsync(HttpClient client, int schoolId) { var page = await client.GetFromJsonAsync( $"/api/schools/{schoolId}/people?pageSize=10", TestContext.Current.CancellationToken); Assert.NotNull(page); Assert.NotEmpty(page.People); return page; } private static async Task GetLogAsync(HttpClient client, int schoolId, string personId, string query) { var page = await client.GetFromJsonAsync( $"/api/schools/{schoolId}/people/{Uri.EscapeDataString(personId)}/log?{query}", TestContext.Current.CancellationToken); Assert.NotNull(page); return page; } private static async Task ProblemCodeAsync(HttpResponseMessage response) { var problem = await response.Content.ReadFromJsonAsync(TestContext.Current.CancellationToken); return problem?.Code; } private sealed record ProblemResponse(string? Code); private sealed record PeopleList(IReadOnlyList People); private sealed record PersonRow(string Id); private sealed record PersonLogResponse( int Total, int Page, int PageSize, IReadOnlyList Entries); private sealed record PersonLogEntry(DateTime Time, string Type, string Label, string? ThingDef); }