Files
h-school/tests/HSchool.AppHost.Tests/PersonLogApiTests.cs
T
Leonid PershinandCursor 6be4fa75ab Split the person card into overview, clothes, carry and now tabs.
Today's history is a paged HTTP log on the worker, not on the card or in people.json.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-20 04:00:38 +03:00

107 lines
4.3 KiB
C#

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<PersonLogResponse>(
$"/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<PeopleList> GetPeopleAsync(HttpClient client, int schoolId)
{
var page = await client.GetFromJsonAsync<PeopleList>(
$"/api/schools/{schoolId}/people?pageSize=10",
TestContext.Current.CancellationToken);
Assert.NotNull(page);
Assert.NotEmpty(page.People);
return page;
}
private static async Task<PersonLogResponse> GetLogAsync(HttpClient client, int schoolId, string personId, string query)
{
var page = await client.GetFromJsonAsync<PersonLogResponse>(
$"/api/schools/{schoolId}/people/{Uri.EscapeDataString(personId)}/log?{query}",
TestContext.Current.CancellationToken);
Assert.NotNull(page);
return page;
}
private static async Task<string?> ProblemCodeAsync(HttpResponseMessage response)
{
var problem = await response.Content.ReadFromJsonAsync<ProblemResponse>(TestContext.Current.CancellationToken);
return problem?.Code;
}
private sealed record ProblemResponse(string? Code);
private sealed record PeopleList(IReadOnlyList<PersonRow> People);
private sealed record PersonRow(string Id);
private sealed record PersonLogResponse(
int Total,
int Page,
int PageSize,
IReadOnlyList<PersonLogEntry> Entries);
private sealed record PersonLogEntry(DateTime Time, string Type, string Label, string? ThingDef);
}