From 2d0687a0830ec304c249a1cb77fe71906c792571 Mon Sep 17 00:00:00 2001 From: Tim Krampitz Date: Sat, 3 Oct 2026 22:29:33 +0200 Subject: [PATCH] Lobby: include HostUserId in GameStateDto and let client derive host status; update tests --- SlipItIn.Server.Tests/GameHubTests.cs | 9 ++++++--- SlipItIn.Server.Tests/GameServiceTests.cs | 12 ++++++++++++ SlipItIn.Server/Services/GameService.cs | 1 + SlipItIn.Shared/DTOs/GameStateDto.cs | 2 ++ SlipItIn/ViewModels/LobbyViewModel.cs | 6 ++++++ 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/SlipItIn.Server.Tests/GameHubTests.cs b/SlipItIn.Server.Tests/GameHubTests.cs index 0b9ab7b..669a609 100644 --- a/SlipItIn.Server.Tests/GameHubTests.cs +++ b/SlipItIn.Server.Tests/GameHubTests.cs @@ -108,6 +108,7 @@ public class GameHubTests { GameId = game.Id, LobbyCode = game.LobbyCode, + HostUserId = game.HostId, Players = [new PlayerInfoDto { Username = user.Username }] }); @@ -151,7 +152,7 @@ public class GameHubTests var game = new Game { Id = 3, LobbyCode = "JOIN42", HostId = 99 }; _gameService.Setup(s => s.JoinGameAsync("JOIN42", user.Id, ConnectionId)).ReturnsAsync(game); - _gameService.Setup(s => s.GetGameStateAsync(game.Id)).ReturnsAsync(new GameStateDto { GameId = 3 }); + _gameService.Setup(s => s.GetGameStateAsync(game.Id)).ReturnsAsync(new GameStateDto { GameId = 3, HostUserId = 99 }); await _hub.JoinLobby("JOIN42"); @@ -205,7 +206,7 @@ public class GameHubTests _gameService.Setup(s => s.SetPlayerReadyAsync(game.Id, player.Id)) .ReturnsAsync(new Game { Id = game.Id, LobbyCode = game.LobbyCode }); - _gameService.Setup(s => s.GetGameStateAsync(game.Id)).ReturnsAsync(new GameStateDto { GameId = game.Id }); + _gameService.Setup(s => s.GetGameStateAsync(game.Id)).ReturnsAsync(new GameStateDto { GameId = game.Id, HostUserId = game.HostId }); await _hub.PlayerReady(game.Id, player.Id); @@ -540,7 +541,9 @@ public class GameHubTests SeedGameWithPlayers((user, ConnectionId)); var gameId = db.Games.Single().Id; - _gameService.Setup(s => s.GetGameStateAsync(gameId)).ReturnsAsync(new GameStateDto { GameId = gameId }); + var hostId = db.Games.Single().HostId; + + _gameService.Setup(s => s.GetGameStateAsync(gameId)).ReturnsAsync(new GameStateDto { GameId = gameId, HostUserId = hostId }); await _hub.RequestGameState(gameId); diff --git a/SlipItIn.Server.Tests/GameServiceTests.cs b/SlipItIn.Server.Tests/GameServiceTests.cs index a97b32d..f9fab2a 100644 --- a/SlipItIn.Server.Tests/GameServiceTests.cs +++ b/SlipItIn.Server.Tests/GameServiceTests.cs @@ -40,6 +40,18 @@ public class GameServiceTests await Assert.ThrowsAsync(() => _sut.CreateGameAsync(999)); } + [Fact] + public async Task GetGameStateAsync_IncludesHostUserId() + { + using var db = _factory.CreateDbContext(); + var host = TestDbHelper.SeedUser(db); + var (game, _) = TestDbHelper.SeedGame(db, host); + + var dto = await _sut.GetGameStateAsync(game.Id); + + Assert.Equal(game.HostId, dto.HostUserId); + } + // ---------- JoinGameAsync ---------- [Fact] diff --git a/SlipItIn.Server/Services/GameService.cs b/SlipItIn.Server/Services/GameService.cs index b57f4ff..50ee4a8 100644 --- a/SlipItIn.Server/Services/GameService.cs +++ b/SlipItIn.Server/Services/GameService.cs @@ -293,6 +293,7 @@ public class GameService : IGameService LobbyCode = game.LobbyCode, Status = game.Status.ToString(), Players = playerInfos, + HostUserId = game.HostId, CurrentRound = currentRound?.RoundNumber ?? 0, RoundTimeRemaining = roundTimeRemaining }; diff --git a/SlipItIn.Shared/DTOs/GameStateDto.cs b/SlipItIn.Shared/DTOs/GameStateDto.cs index 8bbccbb..7ca3424 100644 --- a/SlipItIn.Shared/DTOs/GameStateDto.cs +++ b/SlipItIn.Shared/DTOs/GameStateDto.cs @@ -6,6 +6,8 @@ public class GameStateDto public string LobbyCode { get; set; } = string.Empty; public string Status { get; set; } = string.Empty; public List Players { get; set; } = []; + // Host user id to let clients determine whether the current user is the host + public int HostUserId { get; set; } public int CurrentRound { get; set; } public int RoundTimeRemaining { get; set; } } diff --git a/SlipItIn/ViewModels/LobbyViewModel.cs b/SlipItIn/ViewModels/LobbyViewModel.cs index 87184f1..cb62a8d 100644 --- a/SlipItIn/ViewModels/LobbyViewModel.cs +++ b/SlipItIn/ViewModels/LobbyViewModel.cs @@ -144,8 +144,14 @@ public partial class LobbyViewModel : BaseViewModel, Players.Add(player); var currentUsername = _authSession.CurrentUser?.Username; + var currentUserId = _authSession.CurrentUser?.UserId ?? 0; + IsCurrentPlayerReady = message.Value.Players.Any(p => p.IsReady && string.Equals(p.Username, currentUsername, StringComparison.OrdinalIgnoreCase)); + + // Determine whether the current user is the host based on server-provided HostUserId + IsHost = currentUserId > 0 && message.Value.HostUserId > 0 && currentUserId == message.Value.HostUserId; + CanStartGame = message.Value.Players.Count >= 2 && message.Value.Players.All(p => p.IsReady); }); }