Refactor phase reads to pure lookups and align admin docs
This commit is contained in:
@@ -4,6 +4,7 @@ using GameList.Domain;
|
||||
using GameList.Infrastructure;
|
||||
using GameList.Tests.Support;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace GameList.Tests;
|
||||
@@ -50,7 +51,30 @@ public class FiltersTests
|
||||
await AssertStatusAsync(result, StatusCodes.Status400BadRequest);
|
||||
}
|
||||
|
||||
private static async Task<TestInvocationContext> BuildContextAsync(TestWebApplicationFactory factory, bool isAdmin, Phase phase = Phase.Vote, bool hasJoker = false)
|
||||
[Fact]
|
||||
public async Task Phase_requirement_uses_effective_phase_without_mutating_player()
|
||||
{
|
||||
await using var factory = new TestWebApplicationFactory();
|
||||
var ctx = await BuildContextAsync(factory, isAdmin: false, phase: Phase.Vote, resultsOpen: true);
|
||||
var filter = new PhaseRequirementFilter(Phase.Results);
|
||||
var called = false;
|
||||
|
||||
var result = await filter.InvokeAsync(ctx, _ =>
|
||||
{
|
||||
called = true;
|
||||
return ValueTask.FromResult<object?>(Results.Ok());
|
||||
});
|
||||
|
||||
Assert.True(called);
|
||||
await AssertStatusAsync(result, StatusCodes.Status200OK);
|
||||
|
||||
var playerId = Guid.Parse(ctx.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier)!);
|
||||
var db = ctx.HttpContext.RequestServices.GetRequiredService<AppDbContext>();
|
||||
var storedPlayer = await db.Players.AsNoTracking().SingleAsync(p => p.Id == playerId);
|
||||
Assert.Equal(Phase.Vote, storedPlayer.CurrentPhase);
|
||||
}
|
||||
|
||||
private static async Task<TestInvocationContext> BuildContextAsync(TestWebApplicationFactory factory, bool isAdmin, Phase phase = Phase.Vote, bool hasJoker = false, bool resultsOpen = false)
|
||||
{
|
||||
var scope = factory.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
@@ -67,6 +91,8 @@ public class FiltersTests
|
||||
DisplayName = "User"
|
||||
};
|
||||
db.Players.Add(player);
|
||||
var state = await db.AppState.FirstAsync();
|
||||
state.ResultsOpen = resultsOpen;
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
var ctx = new DefaultHttpContext
|
||||
|
||||
@@ -36,7 +36,7 @@ public class StateTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetPhase_upgrades_reveal_and_resets_when_results_close()
|
||||
public async Task GetCurrentPhase_reads_effective_phase_without_mutating_player()
|
||||
{
|
||||
await using var factory = new TestWebApplicationFactory();
|
||||
Guid playerId = Guid.Empty;
|
||||
@@ -63,7 +63,7 @@ public class StateTests
|
||||
using (var scope = factory.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
var phase = await Endpoints.EndpointHelpers.GetPhase(db, playerId);
|
||||
var phase = await Endpoints.EndpointHelpers.GetCurrentPhaseAsync(db, playerId);
|
||||
Assert.Equal(Phase.Results, phase);
|
||||
}
|
||||
|
||||
@@ -77,10 +77,11 @@ public class StateTests
|
||||
using (var scope = factory.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
var phase = await Endpoints.EndpointHelpers.GetPhase(db, playerId);
|
||||
var phase = await Endpoints.EndpointHelpers.GetCurrentPhaseAsync(db, playerId);
|
||||
var player = await db.Players.FindAsync(playerId);
|
||||
Assert.Equal(Phase.Vote, phase);
|
||||
Assert.False(player!.VotesFinal);
|
||||
Assert.Equal(Phase.Reveal, player!.CurrentPhase);
|
||||
Assert.True(player.VotesFinal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +232,37 @@ public class StateTests
|
||||
Assert.Equal("ok", resp.GetProperty("status").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task State_and_me_reads_do_not_persist_phase_reconciliation()
|
||||
{
|
||||
await using var factory = new TestWebApplicationFactory();
|
||||
var client = factory.CreateClientWithCookies();
|
||||
await client.RegisterAsync("reader");
|
||||
|
||||
await factory.WithDbContextAsync(async db =>
|
||||
{
|
||||
var player = await db.Players.FirstAsync();
|
||||
player.CurrentPhase = Phase.Results;
|
||||
player.VotesFinal = true;
|
||||
var state = await db.AppState.FirstAsync();
|
||||
state.ResultsOpen = false;
|
||||
await db.SaveChangesAsync();
|
||||
});
|
||||
|
||||
var stateResponse = await client.GetFromJsonAsync<JsonElement>("/api/state");
|
||||
var meResponse = await client.GetFromJsonAsync<JsonElement>("/api/me");
|
||||
|
||||
Assert.Equal(nameof(Phase.Vote), stateResponse.GetProperty("currentPhase").GetString());
|
||||
Assert.Equal(nameof(Phase.Vote), meResponse.GetProperty("currentPhase").GetString());
|
||||
|
||||
await factory.WithDbContextAsync(async db =>
|
||||
{
|
||||
var player = await db.Players.AsNoTracking().FirstAsync();
|
||||
Assert.Equal(Phase.Results, player.CurrentPhase);
|
||||
Assert.True(player.VotesFinal);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetPhase_aligns_to_results_when_open()
|
||||
{
|
||||
@@ -256,8 +288,9 @@ public class StateTests
|
||||
using var scope = factory.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
var playerId = await db.Players.Select(p => p.Id).FirstAsync();
|
||||
var phase = await Endpoints.EndpointHelpers.GetPhase(db, playerId);
|
||||
var phase = await Endpoints.EndpointHelpers.GetCurrentPhaseAsync(db, playerId);
|
||||
|
||||
Assert.Equal(Phase.Results, phase);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user