Lobby: include HostUserId in GameStateDto and let client derive host status; update tests #7

Merged
tim merged 6 commits from feature/host-userid-lobby-start into master 2026-10-04 16:12:24 +00:00
5 changed files with 27 additions and 3 deletions
Showing only changes of commit 2d0687a083 - Show all commits

View File

@@ -108,6 +108,7 @@ public class GameHubTests
{ {
GameId = game.Id, GameId = game.Id,
LobbyCode = game.LobbyCode, LobbyCode = game.LobbyCode,
HostUserId = game.HostId,
Players = [new PlayerInfoDto { Username = user.Username }] Players = [new PlayerInfoDto { Username = user.Username }]
}); });
@@ -151,7 +152,7 @@ public class GameHubTests
var game = new Game { Id = 3, LobbyCode = "JOIN42", HostId = 99 }; 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.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"); await _hub.JoinLobby("JOIN42");
@@ -205,7 +206,7 @@ public class GameHubTests
_gameService.Setup(s => s.SetPlayerReadyAsync(game.Id, player.Id)) _gameService.Setup(s => s.SetPlayerReadyAsync(game.Id, player.Id))
.ReturnsAsync(new Game { Id = game.Id, LobbyCode = game.LobbyCode }); .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); await _hub.PlayerReady(game.Id, player.Id);
@@ -540,7 +541,9 @@ public class GameHubTests
SeedGameWithPlayers((user, ConnectionId)); SeedGameWithPlayers((user, ConnectionId));
var gameId = db.Games.Single().Id; 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); await _hub.RequestGameState(gameId);

View File

@@ -40,6 +40,18 @@ public class GameServiceTests
await Assert.ThrowsAsync<InvalidOperationException>(() => _sut.CreateGameAsync(999)); await Assert.ThrowsAsync<InvalidOperationException>(() => _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 ---------- // ---------- JoinGameAsync ----------
[Fact] [Fact]

View File

@@ -293,6 +293,7 @@ public class GameService : IGameService
LobbyCode = game.LobbyCode, LobbyCode = game.LobbyCode,
Status = game.Status.ToString(), Status = game.Status.ToString(),
Players = playerInfos, Players = playerInfos,
HostUserId = game.HostId,
CurrentRound = currentRound?.RoundNumber ?? 0, CurrentRound = currentRound?.RoundNumber ?? 0,
RoundTimeRemaining = roundTimeRemaining RoundTimeRemaining = roundTimeRemaining
}; };

View File

@@ -6,6 +6,8 @@ public class GameStateDto
public string LobbyCode { get; set; } = string.Empty; public string LobbyCode { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty; public string Status { get; set; } = string.Empty;
public List<PlayerInfoDto> Players { get; set; } = []; public List<PlayerInfoDto> 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 CurrentRound { get; set; }
public int RoundTimeRemaining { get; set; } public int RoundTimeRemaining { get; set; }
} }

View File

@@ -144,8 +144,14 @@ public partial class LobbyViewModel : BaseViewModel,
Players.Add(player); Players.Add(player);
var currentUsername = _authSession.CurrentUser?.Username; var currentUsername = _authSession.CurrentUser?.Username;
var currentUserId = _authSession.CurrentUser?.UserId ?? 0;
IsCurrentPlayerReady = message.Value.Players.Any(p => IsCurrentPlayerReady = message.Value.Players.Any(p =>
p.IsReady && string.Equals(p.Username, currentUsername, StringComparison.OrdinalIgnoreCase)); 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); CanStartGame = message.Value.Players.Count >= 2 && message.Value.Players.All(p => p.IsReady);
}); });
} }