using NeonSprawl.Server.Game.Combat; namespace NeonSprawl.Server.Tests.Game.Combat; public sealed class CombatEntityHealthStoreTests { [Fact] public void TryGet_OnFirstAccess_ShouldLazyInitMeleeToCatalogMaxHp() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var found = store.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot); // Assert Assert.True(found); Assert.Equal(PrototypeNpcRegistry.PrototypeNpcMeleeId, snapshot.TargetId); Assert.Equal(100, snapshot.MaxHp); Assert.Equal(100, snapshot.CurrentHp); Assert.False(snapshot.Defeated); } [Fact] public void TryApplyDamage_ShouldReduceHp_WhenDamageIsApplied() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var applied = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 25, out var snapshot); // Assert Assert.True(applied); Assert.Equal(75, snapshot.CurrentHp); Assert.False(snapshot.Defeated); } [Fact] public void TryApplyDamage_RepeatedUntilZero_ShouldMarkDefeated() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var first = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 25, out _); var second = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 25, out _); var third = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 25, out _); var fourth = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 25, out var defeated); // Assert Assert.True(first); Assert.True(second); Assert.True(third); Assert.True(fourth); Assert.Equal(0, defeated.CurrentHp); Assert.True(defeated.Defeated); } [Fact] public void TryApplyDamage_OnDefeatedTarget_ShouldKeepHpAtZeroAndRemainDefeated() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); _ = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 100, out _); // Act var overkill = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 25, out var snapshot); // Assert Assert.True(overkill); Assert.Equal(0, snapshot.CurrentHp); Assert.True(snapshot.Defeated); } [Fact] public void TryResetToFull_AfterDefeat_ShouldRestoreFullHpAndClearDefeated() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); _ = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 100, out _); // Act var reset = store.TryResetToFull(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot); // Assert Assert.True(reset); Assert.Equal(100, snapshot.CurrentHp); Assert.False(snapshot.Defeated); } [Fact] public void TryGet_OnRanged_ShouldLazyInitIndependentlyFromMelee() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); _ = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, 40, out var meleeAfterDamage); // Act var found = store.TryGet(PrototypeNpcRegistry.PrototypeNpcRangedId, out var ranged); // Assert Assert.True(found); Assert.Equal(80, ranged.MaxHp); Assert.Equal(80, ranged.CurrentHp); Assert.False(ranged.Defeated); Assert.Equal(60, meleeAfterDamage.CurrentHp); } [Fact] public void TryGet_OnElite_ShouldLazyInitToTwoHundredMaxHp() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var found = store.TryGet(PrototypeNpcRegistry.PrototypeNpcEliteId, out var elite); // Assert Assert.True(found); Assert.Equal(200, elite.MaxHp); Assert.Equal(200, elite.CurrentHp); Assert.False(elite.Defeated); } [Fact] public void TryGet_ShouldReturnFalse_WhenTargetIdIsUnknown() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var found = store.TryGet("not_a_prototype_target", out var snapshot); // Assert Assert.False(found); Assert.Equal(default, snapshot); } [Fact] public void TryGet_ShouldReturnFalse_WhenTargetIdIsEmpty() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var found = store.TryGet(" ", out var snapshot); // Assert Assert.False(found); Assert.Equal(default, snapshot); } [Fact] public void TryApplyDamage_ShouldReturnFalse_WhenDamageIsNegative() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var applied = store.TryApplyDamage(PrototypeNpcRegistry.PrototypeNpcMeleeId, -1, out var snapshot); // Assert Assert.False(applied); Assert.Equal(default, snapshot); } [Fact] public void TryApplyDamage_ShouldReturnFalse_WhenTargetIdIsUnknown() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var applied = store.TryApplyDamage("not_a_prototype_target", 25, out var snapshot); // Assert Assert.False(applied); Assert.Equal(default, snapshot); } [Fact] public void TryApplyDamage_ShouldReturnFalse_WhenTargetIdIsEmpty() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var applied = store.TryApplyDamage(" ", 25, out var snapshot); // Assert Assert.False(applied); Assert.Equal(default, snapshot); } [Fact] public void TryGet_ShouldNormalizeCaseVariantTargetIds() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var found = store.TryGet(" Prototype_Npc_Melee ", out var snapshot); // Assert Assert.True(found); Assert.Equal(PrototypeNpcRegistry.PrototypeNpcMeleeId, snapshot.TargetId); Assert.Equal(100, snapshot.CurrentHp); } [Fact] public void TryGet_ShouldReturnFalse_ForLegacyAlphaDummyId() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var found = store.TryGet("prototype_target_alpha", out var snapshot); // Assert Assert.False(found); Assert.Equal(default, snapshot); } [Fact] public void TryResetToFull_ShouldReturnFalse_WhenTargetIdIsUnknown() { // Arrange var store = PrototypeNpcTestFixtures.CreateHealthStore(); // Act var reset = store.TryResetToFull("not_a_prototype_target", out var snapshot); // Assert Assert.False(reset); Assert.Equal(default, snapshot); } [Fact] public async Task Host_ShouldResolveCombatEntityHealthStoreFromDi_WhenStartupSucceeds() { // Arrange await using var factory = new InMemoryWebApplicationFactory(); using var client = factory.CreateClient(); _ = await client.GetAsync("/health"); // Act var store = factory.Services.GetRequiredService(); var found = store.TryGet(PrototypeNpcRegistry.PrototypeNpcMeleeId, out var snapshot); // Assert Assert.True(found); Assert.Equal(100, snapshot.CurrentHp); Assert.False(snapshot.Defeated); } }