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");