using System.Net; using System.Net.Http.Json; using System.Text.Json; using GameList.Domain; using GameList.Tests.Support; using Microsoft.EntityFrameworkCore; using GameList.Data; using Microsoft.Extensions.DependencyInjection; namespace GameList.Tests; public class StateTests { [Fact] public async Task Cannot_advance_to_results_when_locked() { using var factory = new TestWebApplicationFactory(); var client = factory.CreateClientWithCookies(); await client.RegisterAsync("player"); var toVote = await client.PostAsync("/api/me/phase/next", JsonContent.Create(new { })); toVote.EnsureSuccessStatusCode(); var toResults = await client.PostAsync("/api/me/phase/next", JsonContent.Create(new { })); Assert.Equal(HttpStatusCode.BadRequest, toResults.StatusCode); } [Fact] public async Task Admin_opening_results_moves_players_to_results_phase() { using var factory = new TestWebApplicationFactory(); var admin = factory.CreateClientWithCookies(); await admin.RegisterAsync("admin", admin: true); var player = factory.CreateClientWithCookies(); await player.RegisterAsync("user"); var toggle = await admin.PostAsJsonAsync("/api/admin/results", new { resultsOpen = true }); toggle.EnsureSuccessStatusCode(); var state = await player.GetFromJsonAsync("/api/state"); Assert.Equal(Phase.Results.ToString(), state.GetProperty("currentPhase").GetString()); Assert.True(state.GetProperty("resultsOpen").GetBoolean()); } [Fact] public async Task Name_endpoint_trims_and_rejects_blank() { using var factory = new TestWebApplicationFactory(); var client = factory.CreateClientWithCookies(); await client.RegisterAsync("nametest"); var bad = await client.PostAsJsonAsync("/api/me/name", new { name = " " }); Assert.Equal(HttpStatusCode.BadRequest, bad.StatusCode); var ok = await client.PostAsJsonAsync("/api/me/name", new { name = " Alice " }); ok.EnsureSuccessStatusCode(); var me = await client.GetFromJsonAsync("/api/me"); Assert.Equal("Alice", me.GetProperty("displayName").GetString()); } [Fact] public async Task Phase_prev_admin_only() { using var factory = new TestWebApplicationFactory(); var player = factory.CreateClientWithCookies(); await player.RegisterAsync("phase"); var notAdmin = await player.PostAsJsonAsync("/api/me/phase/prev", new { }); Assert.Equal(HttpStatusCode.BadRequest, notAdmin.StatusCode); var admin = factory.CreateClientWithCookies(); await admin.RegisterAsync("admin", admin: true); await admin.PostAsJsonAsync("/api/me/phase/next", new { }); // to Vote var back = await admin.PostAsJsonAsync("/api/me/phase/prev", new { }); back.EnsureSuccessStatusCode(); var me = await admin.GetFromJsonAsync("/api/me"); Assert.Equal(Phase.Suggest.ToString(), me.GetProperty("currentPhase").GetString()); } [Fact] public async Task State_endpoint_requires_auth_and_counts() { using var factory = new TestWebApplicationFactory(); var anon = factory.CreateClient(); var unauthorized = await anon.GetAsync("/api/state"); Assert.NotEqual(HttpStatusCode.OK, unauthorized.StatusCode); var client = factory.CreateClientWithCookies(); await client.RegisterAsync("counting"); await client.CreateSuggestionAsync("One"); var state = await client.GetFromJsonAsync("/api/state"); Assert.True(state.TryGetProperty("Players", out var players) || state.TryGetProperty("players", out players)); Assert.True(players.GetInt32() >= 1); Assert.True(state.TryGetProperty("Suggestions", out var suggestions) || state.TryGetProperty("suggestions", out suggestions)); Assert.True(suggestions.GetInt32() >= 1); } [Fact] public async Task Health_endpoint_ok() { using var factory = new TestWebApplicationFactory(); var resp = await factory.CreateClient().GetFromJsonAsync("/health"); Assert.Equal("ok", resp.GetProperty("status").GetString()); } [Fact] public async Task GetPhase_aligns_to_results_when_open() { using var factory = new TestWebApplicationFactory(); await factory.WithDbContextAsync(async db => { var player = new Player { Id = Guid.NewGuid(), Username = "phase", NormalizedUsername = "phase", PasswordHash = new byte[] { 1 }, PasswordSalt = new byte[] { 1 }, DisplayName = "phase", CurrentPhase = Phase.Vote }; 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(); var playerId = await db.Players.Select(p => p.Id).FirstAsync(); var phase = await GameList.Endpoints.EndpointHelpers.GetPhase(db, playerId); Assert.Equal(Phase.Results, phase); } }