using Microsoft.Extensions.Logging; using NeonSprawl.Server.Game.Gigs; namespace NeonSprawl.Server.Tests.Game.Gigs; /// NEO-44: combat defeat hook → breach gig XP via dedicated store (not E2.M2). public sealed class CombatDefeatGigXpGrantTests { [Fact] public async Task GrantOnCombatDefeat_WhenPlayerKnown_ShouldIncreaseBreachXp() { // Arrange await using var factory = new InMemoryWebApplicationFactory(); _ = factory.CreateClient(); using var scope = factory.Services.CreateScope(); var gigStore = scope.ServiceProvider.GetRequiredService(); // Act CombatDefeatGigXpGrant.GrantOnCombatDefeat("dev-local-1", gigStore); // Assert var totals = gigStore.GetXpTotals("dev-local-1"); Assert.True(totals.TryGetValue(GigProgressionConstants.PrototypeMainGigId, out var xp)); Assert.Equal(GigProgressionConstants.CombatDefeatXpAmount, xp); } [Fact] public async Task GrantOnCombatDefeat_WhenPlayerUnknown_ShouldNotThrow() { // Arrange await using var factory = new InMemoryWebApplicationFactory(); _ = factory.CreateClient(); using var scope = factory.Services.CreateScope(); var gigStore = scope.ServiceProvider.GetRequiredService(); // Act var exception = Record.Exception(() => CombatDefeatGigXpGrant.GrantOnCombatDefeat("missing-player", gigStore)); // Assert Assert.Null(exception); Assert.Empty(gigStore.GetXpTotals("missing-player")); } [Fact] public async Task GrantOnCombatDefeat_WhenPlayerUnknown_ShouldNotThrow_WithLogger() { // Arrange await using var factory = new InMemoryWebApplicationFactory(); _ = factory.CreateClient(); using var scope = factory.Services.CreateScope(); var gigStore = scope.ServiceProvider.GetRequiredService(); var logger = scope.ServiceProvider.GetRequiredService() .CreateLogger(nameof(CombatDefeatGigXpGrant)); // Act var exception = Record.Exception(() => CombatDefeatGigXpGrant.GrantOnCombatDefeat("missing-player", gigStore, logger)); // Assert Assert.Null(exception); } }