Show unseen Server commits after login.
Bake first-parent git log at Server build and remember the SHA in a browser cookie. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
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<ChangelogDto>(
|
||||
"/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<ChangelogDto>(
|
||||
"/api/changelog",
|
||||
JsonOptions,
|
||||
TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(first);
|
||||
|
||||
var again = await client.GetFromJsonAsync<ChangelogDto>(
|
||||
$"/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);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using HSchool.Server.Changelog;
|
||||
|
||||
namespace HSchool.Server.Tests;
|
||||
|
||||
public class BuildChangelogTests
|
||||
{
|
||||
private const string Head = "cccccccccccccccccccccccccccccccccccccccc";
|
||||
private const string Mark = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
|
||||
private const string Merge = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||
private const string Unknown = "dddddddddddddddddddddddddddddddddddddddd";
|
||||
|
||||
private static readonly string Sample = string.Join('\n',
|
||||
Head,
|
||||
$"{Head}\u001f2026-01-03T12:00:00Z\u001fAdd changelog window",
|
||||
$"{Mark}\u001f2026-01-02T12:00:00Z\u001fMark phase 54 in progress.",
|
||||
$"{Merge}\u001f2026-01-01T12:00:00Z\u001fMerge branch 'phase/53-weather-commute'");
|
||||
|
||||
[Fact]
|
||||
public void VisibleSince_KnownSha_ReturnsOlderToNewerWithoutMarkPhase()
|
||||
{
|
||||
var changelog = BuildChangelog.Parse(Sample);
|
||||
|
||||
var visible = changelog.VisibleSince(Merge);
|
||||
|
||||
var commit = Assert.Single(visible);
|
||||
Assert.Equal(Head, commit.Sha);
|
||||
Assert.Equal("Add changelog window", commit.Subject);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VisibleSince_MarkPhaseAnchor_StillReturnsLaterVisibleCommits()
|
||||
{
|
||||
var changelog = BuildChangelog.Parse(Sample);
|
||||
|
||||
var visible = changelog.VisibleSince(Mark);
|
||||
|
||||
var commit = Assert.Single(visible);
|
||||
Assert.Equal("Add changelog window", commit.Subject);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VisibleSince_MissingUnknownOrCurrent_ReturnsEmpty()
|
||||
{
|
||||
var changelog = BuildChangelog.Parse(Sample);
|
||||
|
||||
Assert.Empty(changelog.VisibleSince(null));
|
||||
Assert.Empty(changelog.VisibleSince(""));
|
||||
Assert.Empty(changelog.VisibleSince(Unknown));
|
||||
Assert.Empty(changelog.VisibleSince(Head));
|
||||
Assert.Empty(changelog.VisibleSince(Head.ToUpperInvariant()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsMarkPhase_MatchesStatusLineSubjects()
|
||||
{
|
||||
Assert.True(BuildChangelog.IsMarkPhase("Mark phase 54 in progress."));
|
||||
Assert.True(BuildChangelog.IsMarkPhase("Mark phase 47 romance pack as complete."));
|
||||
Assert.False(BuildChangelog.IsMarkPhase("Merge branch 'phase/54-whats-new'"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user