neon-sprawl/server/NeonSprawl.Server.Tests/Game/Combat/PlayerCombatHealthStoreTest...

119 lines
3.6 KiB
C#

using Microsoft.Extensions.DependencyInjection;
using NeonSprawl.Server.Game.Combat;
using NeonSprawl.Server.Tests;
using Xunit;
namespace NeonSprawl.Server.Tests.Game.Combat;
public sealed class PlayerCombatHealthStoreTests
{
[Fact]
public void TryGet_ShouldLazyInitToMaxHp_OnFirstAccess()
{
// Arrange
var store = new InMemoryPlayerCombatHealthStore();
// Act
var ok = store.TryGet("dev-local-1", out var snapshot);
// Assert
Assert.True(ok);
Assert.Equal("dev-local-1", snapshot.PlayerId);
Assert.Equal(PlayerCombatHealthDefaults.MaxHp, snapshot.MaxHp);
Assert.Equal(PlayerCombatHealthDefaults.MaxHp, snapshot.CurrentHp);
Assert.False(snapshot.Defeated);
}
[Fact]
public void TryApplyDamage_ShouldDecreaseHp_AndFloorAtZero()
{
// Arrange
var store = new InMemoryPlayerCombatHealthStore();
// Act
var ok = store.TryApplyDamage("dev-local-1", 15, out var snapshot);
// Assert
Assert.True(ok);
Assert.Equal(85, snapshot.CurrentHp);
Assert.False(snapshot.Defeated);
}
[Fact]
public void TryApplyDamage_ShouldMarkDefeated_WhenHpReachesZero()
{
// Arrange
var store = new InMemoryPlayerCombatHealthStore();
// Act
var ok = store.TryApplyDamage("dev-local-1", 100, out var snapshot);
// Assert
Assert.True(ok);
Assert.Equal(0, snapshot.CurrentHp);
Assert.True(snapshot.Defeated);
}
[Fact]
public void TryApplyDamage_ShouldKeepHpAtZero_WhenAlreadyDefeated()
{
// Arrange
var store = new InMemoryPlayerCombatHealthStore();
_ = store.TryApplyDamage("dev-local-1", 100, out _);
// Act
var ok = store.TryApplyDamage("dev-local-1", 25, out var snapshot);
// Assert
Assert.True(ok);
Assert.Equal(0, snapshot.CurrentHp);
Assert.True(snapshot.Defeated);
}
[Fact]
public void TryResetToFull_ShouldRestoreMaxHp()
{
// Arrange
var store = new InMemoryPlayerCombatHealthStore();
_ = store.TryApplyDamage("dev-local-1", 40, out _);
// Act
var ok = store.TryResetToFull("dev-local-1", out var snapshot);
// Assert
Assert.True(ok);
Assert.Equal(PlayerCombatHealthDefaults.MaxHp, snapshot.CurrentHp);
Assert.False(snapshot.Defeated);
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void TryGet_ShouldReturnFalse_WhenPlayerIdInvalid(string? playerId)
{
// Arrange
var store = new InMemoryPlayerCombatHealthStore();
// Act
var ok = store.TryGet(playerId, out var snapshot);
// Assert
Assert.False(ok);
Assert.Equal(default, snapshot);
}
[Fact]
public void TryApplyDamage_ShouldReturnFalse_WhenDamageNegative()
{
// Arrange
var store = new InMemoryPlayerCombatHealthStore();
// Act
var ok = store.TryApplyDamage("dev-local-1", -1, out var snapshot);
// Assert
Assert.False(ok);
Assert.Equal(default, snapshot);
}
[Fact]
public async Task Host_ShouldResolvePlayerCombatHealthStoreFromDi_WhenStartupSucceeds()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
// Act
var store = factory.Services.GetRequiredService<IPlayerCombatHealthStore>();
// Assert
Assert.NotNull(store);
Assert.True(store.TryGet("dev-local-1", out var snapshot));
Assert.Equal(PlayerCombatHealthDefaults.MaxHp, snapshot.CurrentHp);
}
}