using System.Net.Http.Json; using System.Text.Json; using System.Text.RegularExpressions; namespace HSchool.AppHost.Tests; [Collection(AppHostCollection.Name)] public class ChangelogApiTests(AppHostFixture fixture) { private static readonly Regex Sha = new("^[0-9a-f]{40}$", RegexOptions.CultureInvariant); [Fact] public async Task Changelog_WithoutSession_ReturnsUnauthorized() { var http = fixture.App.GetEndpoint("server", "http").ToString(); using var client = new HttpClient { BaseAddress = new Uri(http) }; using var response = await client.GetAsync("/api/changelog", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } [Fact] public async Task Changelog_WithoutSince_ReturnsCurrentAndEmptyCommits() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.LoginAsync(client); var body = await client.GetFromJsonAsync( "/api/changelog", JsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(body); Assert.Matches(Sha, body.Current); Assert.Empty(body.Commits); } [Fact] public async Task Changelog_SinceCurrent_ReturnsEmptyCommits() { using var client = fixture.App.CreateHttpClient("server"); await SchoolApiTests.LoginAsync(client); var first = await client.GetFromJsonAsync( "/api/changelog", JsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(first); var again = await client.GetFromJsonAsync( $"/api/changelog?since={first.Current}", JsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(again); Assert.Equal(first.Current, again.Current); Assert.Empty(again.Commits); } private static JsonSerializerOptions JsonOptions { get; } = new() { PropertyNameCaseInsensitive = true, }; private sealed record ChangelogDto(string Current, ChangelogCommitDto[] Commits); private sealed record ChangelogCommitDto(string Sha, DateTimeOffset Date, string Subject); }