Expand test coverage to match specs

This commit is contained in:
2026-02-05 18:57:25 +01:00
parent e11cb23313
commit 67a164e53b
14 changed files with 861 additions and 32 deletions

View File

@@ -11,6 +11,142 @@ namespace GameList.Tests;
public class StateTests
{
[Fact]
public async Task State_endpoint_returns_expected_payload_for_authenticated_user()
{
using var factory = new TestWebApplicationFactory();
var client = factory.CreateClientWithCookies();
await client.RegisterAsync("payload");
await factory.WithDbContextAsync(async db =>
{
var player = await db.Players.FirstAsync();
player.HasJoker = true;
await db.SaveChangesAsync();
});
await client.CreateSuggestionAsync("One");
var state = await client.GetFromJsonAsync<JsonElement>("/api/state");
Assert.Equal(Phase.Suggest.ToString(), state.GetProperty("currentPhase").GetString());
Assert.False(state.GetProperty("votesFinal").GetBoolean());
Assert.True(state.GetProperty("hasJoker").GetBoolean());
Assert.True(state.GetProperty("players").GetInt32() >= 1);
Assert.True(state.GetProperty("suggestions").GetInt32() >= 1);
Assert.True(state.GetProperty("votes").GetInt32() >= 0);
}
[Fact]
public async Task GetPhase_upgrades_reveal_and_resets_when_results_close()
{
using var factory = new TestWebApplicationFactory();
Guid playerId = Guid.Empty;
await factory.WithDbContextAsync(async db =>
{
var player = new Player
{
Id = Guid.NewGuid(),
Username = "legacy",
NormalizedUsername = "legacy",
PasswordHash = new byte[] { 1 },
PasswordSalt = new byte[] { 1 },
DisplayName = "Legacy",
CurrentPhase = Phase.Reveal,
VotesFinal = true
};
playerId = player.Id;
db.Players.Add(player);
var state = await db.AppState.FirstAsync();
state.ResultsOpen = true;
await db.SaveChangesAsync();
});
using (var scope = factory.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var phase = await GameList.Endpoints.EndpointHelpers.GetPhase(db, playerId);
Assert.Equal(Phase.Results, phase);
}
await factory.WithDbContextAsync(async db =>
{
var state = await db.AppState.FirstAsync();
state.ResultsOpen = false;
await db.SaveChangesAsync();
});
using (var scope = factory.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var phase = await GameList.Endpoints.EndpointHelpers.GetPhase(db, playerId);
var player = await db.Players.FindAsync(playerId);
Assert.Equal(Phase.Vote, phase);
Assert.False(player!.VotesFinal);
}
}
[Fact]
public async Task Phase_next_advances_and_clears_votesfinal()
{
using var factory = new TestWebApplicationFactory();
var client = factory.CreateClientWithCookies();
await client.RegisterAsync("advance");
await factory.WithDbContextAsync(async db =>
{
var player = await db.Players.FirstAsync();
player.VotesFinal = true;
await db.SaveChangesAsync();
});
var toVote = await client.PostAsJsonAsync("/api/me/phase/next", new { });
toVote.EnsureSuccessStatusCode();
var toResultsLocked = await client.PostAsJsonAsync("/api/me/phase/next", new { });
Assert.Equal(HttpStatusCode.BadRequest, toResultsLocked.StatusCode);
// unlock results and advance
var admin = factory.CreateClientWithCookies();
await admin.RegisterAsync("admin", admin: true);
await admin.PostAsJsonAsync("/api/admin/results", new { resultsOpen = true });
var toResults = await client.PostAsJsonAsync("/api/me/phase/next", new { });
toResults.EnsureSuccessStatusCode();
var me = await client.GetFromJsonAsync<JsonElement>("/api/me");
Assert.False(me.GetProperty("votesFinal").GetBoolean());
Assert.Equal(Phase.Results.ToString(), me.GetProperty("currentPhase").GetString());
}
[Fact]
public async Task Phase_prev_moves_back_and_clears_votesfinal()
{
using var factory = new TestWebApplicationFactory();
var admin = factory.CreateClientWithCookies();
await admin.RegisterAsync("admin", admin: true);
await admin.PostAsJsonAsync("/api/me/phase/next", new { }); // Vote
await factory.WithDbContextAsync(async db =>
{
var player = await db.Players.FirstAsync();
player.VotesFinal = true;
await db.SaveChangesAsync();
});
var backToSuggest = await admin.PostAsJsonAsync("/api/me/phase/prev", new { });
backToSuggest.EnsureSuccessStatusCode();
var me = await admin.GetFromJsonAsync<JsonElement>("/api/me");
Assert.Equal(Phase.Suggest.ToString(), me.GetProperty("currentPhase").GetString());
Assert.False(me.GetProperty("votesFinal").GetBoolean());
}
[Fact]
public async Task Name_endpoint_rejects_over_16_chars()
{
using var factory = new TestWebApplicationFactory();
var client = factory.CreateClientWithCookies();
await client.RegisterAsync("namelimit");
var resp = await client.PostAsJsonAsync("/api/me/name", new { name = new string('a', 17) });
Assert.Equal(HttpStatusCode.BadRequest, resp.StatusCode);
}
[Fact]
public async Task Cannot_advance_to_results_when_locked()
{