diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d9b3819..af0c041 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,5 +22,16 @@ jobs: - name: Restore run: dotnet restore SlipItIn.slnx - - name: Build - run: dotnet build SlipItIn.slnx --no-restore --configuration Release + - name: Build Server-Stack + run: | + dotnet build SlipItIn.Shared/SlipItIn.Shared.csproj --no-restore --configuration Release + dotnet build SlipItIn.ServiceDefaults/SlipItIn.ServiceDefaults.csproj --no-restore --configuration Release + dotnet build SlipItIn.Server/SlipItIn.Server.csproj --no-restore --configuration Release + dotnet build SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj --no-restore --configuration Release + dotnet build SlipItIn.AppHost/SlipItIn.AppHost.csproj --no-restore --configuration Release + + - name: Build MAUI Client + run: dotnet build SlipItIn/SlipItIn.csproj --no-restore --configuration Debug + + - name: Run Server Tests + run: dotnet test SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj --no-restore --configuration Release diff --git a/SlipItIN.slnx b/SlipItIN.slnx deleted file mode 100644 index 9e6f1b4..0000000 --- a/SlipItIN.slnx +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/SlipItIn.Server.Tests/AuthControllerTests.cs b/SlipItIn.Server.Tests/AuthControllerTests.cs index 8043746..7f0acca 100644 --- a/SlipItIn.Server.Tests/AuthControllerTests.cs +++ b/SlipItIn.Server.Tests/AuthControllerTests.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using SlipItIn.Server.Controllers; using SlipItIn.Server.Data; using SlipItIn.Shared.DTOs; @@ -26,7 +27,15 @@ public class AuthControllerTests ["Jwt:ExpirationMinutes"] = "60" }) .Build(); - _sut = new AuthController(_factory, config); + _sut = new AuthController(_factory, config, new TestHostEnvironment()); + } + + private sealed class TestHostEnvironment : IHostEnvironment + { + public string EnvironmentName { get; set; } = Environments.Development; + public string ApplicationName { get; set; } = "SlipItIn.Server.Tests"; + public string ContentRootPath { get; set; } = AppContext.BaseDirectory; + public Microsoft.Extensions.FileProviders.IFileProvider ContentRootFileProvider { get; set; } = null!; } // ---------- Register ---------- diff --git a/SlipItIn.Server.Tests/GameServiceTests.cs b/SlipItIn.Server.Tests/GameServiceTests.cs index 33e5b67..e2d2ad7 100644 --- a/SlipItIn.Server.Tests/GameServiceTests.cs +++ b/SlipItIn.Server.Tests/GameServiceTests.cs @@ -117,7 +117,10 @@ public class GameServiceTests { using var db = _factory.CreateDbContext(); var host = TestDbHelper.SeedUser(db); + var other = TestDbHelper.SeedUser(db, "other", "other@t.local"); var (game, _) = TestDbHelper.SeedGame(db, host); + db.Players.Add(new Player { UserId = other.Id, GameId = game.Id }); + await db.SaveChangesAsync(); var result = await _sut.StartGameAsync(game.Id); @@ -216,7 +219,7 @@ public class GameServiceTests { using var db = _factory.CreateDbContext(); var host = TestDbHelper.SeedUser(db); - var (game, hostPlayer) = TestDbHelper.SeedGame(db, host); + var (game, hostPlayer) = TestDbHelper.SeedGame(db, host, GameStatus.InProgress); var round = new GameRound { GameId = game.Id, RoundNumber = 1, Status = RoundStatus.Active }; db.GameRounds.Add(round); var phrase = TestDbHelper.SeedPhrases(db, 1).Single(); @@ -234,7 +237,11 @@ public class GameServiceTests [Fact] public async Task SubmitSlipAsync_Throws_WhenCardNotFound() { - await Assert.ThrowsAsync(() => _sut.SubmitSlipAsync(1, 1, 999)); + using var db = _factory.CreateDbContext(); + var host = TestDbHelper.SeedUser(db); + var (game, _) = TestDbHelper.SeedGame(db, host, GameStatus.InProgress); + + await Assert.ThrowsAsync(() => _sut.SubmitSlipAsync(game.Id, 1, 999)); } [Fact] @@ -243,7 +250,7 @@ public class GameServiceTests using var db = _factory.CreateDbContext(); var host = TestDbHelper.SeedUser(db, "host", "host@t.local"); var other = TestDbHelper.SeedUser(db, "other", "other@t.local"); - var (game, hostPlayer) = TestDbHelper.SeedGame(db, host); + var (game, hostPlayer) = TestDbHelper.SeedGame(db, host, GameStatus.InProgress); var otherPlayer = new Player { UserId = other.Id, GameId = game.Id }; db.Players.Add(otherPlayer); var round = new GameRound { GameId = game.Id, RoundNumber = 1, Status = RoundStatus.Active }; @@ -271,7 +278,7 @@ public class GameServiceTests var round = new GameRound { GameId = game.Id, RoundNumber = 1, Status = RoundStatus.Active }; db.GameRounds.Add(round); var phrase = TestDbHelper.SeedPhrases(db, 1).Single(); - var card = new PlayerCard { PlayerId = otherPlayer.Id, PhraseId = phrase.Id, GameRoundId = round.Id }; + var card = new PlayerCard { PlayerId = otherPlayer.Id, PhraseId = phrase.Id, GameRoundId = round.Id, IsUsed = true }; db.PlayerCards.Add(card); await db.SaveChangesAsync(); @@ -309,7 +316,7 @@ public class GameServiceTests // ---------- ResolveChallengeAsync ---------- [Fact] - public async Task ResolveChallengeAsync_Approved_KeepsCardWithTargetPlayer() + public async Task ResolveChallengeAsync_Approved_TransfersCardToChallenger() { using var db = _factory.CreateDbContext(); var host = TestDbHelper.SeedUser(db, "host", "host@t.local"); @@ -320,7 +327,7 @@ public class GameServiceTests var round = new GameRound { GameId = game.Id, RoundNumber = 1, Status = RoundStatus.Active }; db.GameRounds.Add(round); var phrase = TestDbHelper.SeedPhrases(db, 1).Single(); - var card = new PlayerCard { PlayerId = otherPlayer.Id, PhraseId = phrase.Id, GameRoundId = round.Id }; + var card = new PlayerCard { PlayerId = otherPlayer.Id, PhraseId = phrase.Id, GameRoundId = round.Id, IsUsed = true }; db.PlayerCards.Add(card); var challenge = new SlipChallenge { @@ -337,13 +344,13 @@ public class GameServiceTests Assert.Equal(ChallengeStatus.Approved, result.Status); Assert.NotNull(result.ResolvedAt); - // Karte bleibt beim Beschuldigten + // Berechtigte Beschuldigung: Karte geht an den Beschuldiger using var verify = _factory.CreateDbContext(); - Assert.Equal(otherPlayer.Id, verify.PlayerCards.Single(c => c.Id == card.Id).PlayerId); + Assert.Equal(hostPlayer.Id, verify.PlayerCards.Single(c => c.Id == card.Id).PlayerId); } [Fact] - public async Task ResolveChallengeAsync_Rejected_TransfersCardToChallenger() + public async Task ResolveChallengeAsync_Rejected_KeepsCardWithTargetPlayer() { using var db = _factory.CreateDbContext(); var host = TestDbHelper.SeedUser(db, "host", "host@t.local"); @@ -354,7 +361,7 @@ public class GameServiceTests var round = new GameRound { GameId = game.Id, RoundNumber = 1, Status = RoundStatus.Active }; db.GameRounds.Add(round); var phrase = TestDbHelper.SeedPhrases(db, 1).Single(); - var card = new PlayerCard { PlayerId = otherPlayer.Id, PhraseId = phrase.Id, GameRoundId = round.Id }; + var card = new PlayerCard { PlayerId = otherPlayer.Id, PhraseId = phrase.Id, GameRoundId = round.Id, IsUsed = true }; db.PlayerCards.Add(card); var challenge = new SlipChallenge { @@ -371,9 +378,9 @@ public class GameServiceTests Assert.Equal(ChallengeStatus.Rejected, result.Status); Assert.NotNull(result.ResolvedAt); - // Karte geht an den Beschuldiger + // Falsche Beschuldigung: Karte bleibt beim Beschuldigten using var verify = _factory.CreateDbContext(); - Assert.Equal(hostPlayer.Id, verify.PlayerCards.Single(c => c.Id == card.Id).PlayerId); + Assert.Equal(otherPlayer.Id, verify.PlayerCards.Single(c => c.Id == card.Id).PlayerId); } [Fact] @@ -458,7 +465,7 @@ public class GameServiceTests using var db = _factory.CreateDbContext(); var host = TestDbHelper.SeedUser(db); var (game, hostPlayer) = TestDbHelper.SeedGame(db, host); - var round = new GameRound { GameId = game.Id, RoundNumber = 1 }; + var round = new GameRound { GameId = game.Id, RoundNumber = 1, Status = RoundStatus.Active }; db.GameRounds.Add(round); var phrases = TestDbHelper.SeedPhrases(db, 2); db.PlayerCards.Add(new PlayerCard { PlayerId = hostPlayer.Id, PhraseId = phrases[0].Id, GameRoundId = round.Id }); diff --git a/SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj b/SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj index ec94e49..51f93bd 100644 --- a/SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj +++ b/SlipItIn.Server.Tests/SlipItIn.Server.Tests.csproj @@ -12,7 +12,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/SlipItIn.Server/Hubs/GameHub.cs b/SlipItIn.Server/Hubs/GameHub.cs index 2072514..e81758d 100644 --- a/SlipItIn.Server/Hubs/GameHub.cs +++ b/SlipItIn.Server/Hubs/GameHub.cs @@ -243,11 +243,6 @@ public class GameHub : Hub { await Clients.Caller.SendAsync("Error", new { Message = ex.Message }); } - catch (InvalidOperationException ex) - { - // Geprüfte Fachfehler (z. B. "Round is not active") dürfen an den Client. - await Clients.Caller.SendAsync("Error", new { Message = ex.Message }); - } catch (Exception ex) { _logger.LogError(ex, "Error submitting slip"); @@ -294,11 +289,6 @@ public class GameHub : Hub { await Clients.Caller.SendAsync("Error", new { Message = ex.Message }); } - catch (InvalidOperationException ex) - { - // Geprüfte Fachfehler (z. B. "Card does not belong to the active round") dürfen an den Client. - await Clients.Caller.SendAsync("Error", new { Message = ex.Message }); - } catch (Exception ex) { _logger.LogError(ex, "Error challenging slip");