#nullable enable using SideScrollerGame.Content; using SideScrollerGame.Content.Samples; using SideScrollerGame.Hero.Rules; namespace SideScrollerGame.Content.Tests; public class HeroRuntimeServiceTests { [Fact] public void StartState_UsesDifficultyShieldsAndRetries() { HeroRuntimeService service = CreateService("difficulty.normal"); Assert.Equal(HeroLifeState.Alive, service.State.LifeState); Assert.Equal(3, service.State.ShieldCharges); Assert.Equal(3, service.State.RetryCount); Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[0]); Assert.Null(service.State.PrimaryWeaponSlots[1]); Assert.Equal("weapon.secondary.vertical", service.State.CurrentSecondaryWeaponId); } [Fact] public void ApplyHit_ConsumesShieldsBeforeDeath() { HeroRuntimeService service = CreateService(); service.ApplyHit(false); Assert.Equal(HeroLifeState.Alive, service.State.LifeState); Assert.Equal(2, service.State.ShieldCharges); } [Fact] public void ApplyHit_WithNoShieldsAndRetries_EntersDeadState() { HeroRuntimeService service = CreateService(); service.RemoveShieldCharge(3); service.ApplyHit(false); Assert.Equal(HeroLifeState.Dead, service.State.LifeState); Assert.Equal(3, service.State.RetryCount); } [Fact] public void Rebirth_ConsumesRetryAndRestoresDifficultyShields() { HeroRuntimeService service = CreateService(); service.Kill(); HeroRuleResult result = service.Rebirth(); Assert.True(result.Succeeded); Assert.Equal(HeroLifeState.Alive, service.State.LifeState); Assert.Equal(2, service.State.RetryCount); Assert.Equal(3, service.State.ShieldCharges); } [Fact] public void Kill_WithZeroRetries_EntersGameOver() { HeroRuntimeService service = CreateService(); service.SetRetryCount(0); service.Kill(); Assert.Equal(HeroLifeState.GameOver, service.State.LifeState); Assert.Equal(0, service.State.RetryCount); } [Fact] public void AddPoints_LevelsUpAndAddsShields() { HeroRuntimeService service = CreateService(); service.AddPoints(500); Assert.Equal(2, service.State.Level); Assert.Equal(500, service.State.Points); Assert.Equal(4, service.State.ShieldCharges); } [Fact] public void AddPoints_CanCrossMultipleThresholds() { HeroRuntimeService service = CreateService(); service.AddPoints(3000); Assert.Equal(4, service.State.Level); Assert.Equal(6, service.State.ShieldCharges); } [Fact] public void PrimaryPickup_FillsEmptySlotBeforeReplacingSelectedSlot() { HeroRuntimeService service = CreateService(); service.ApplyPrimaryWeaponPickup("weapon.primary.basic"); Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[1]); service.TogglePrimaryWeaponSlot(); service.ApplyPrimaryWeaponPickup("weapon.primary.basic"); Assert.Equal(1, service.State.SelectedPrimaryWeaponSlotIndex); Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[1]); } [Fact] public void TogglePrimaryWeaponSlot_ChangesSelectedSlot() { HeroRuntimeService service = CreateService(); service.TogglePrimaryWeaponSlot(); Assert.Equal(1, service.State.SelectedPrimaryWeaponSlotIndex); } [Fact] public void SecondaryPickup_ReplacesCurrentSecondary() { HeroRuntimeService service = CreateService(); service.ApplySecondaryWeaponPickup("weapon.secondary.vertical"); Assert.Equal("weapon.secondary.vertical", service.State.CurrentSecondaryWeaponId); } [Fact] public void SpecialAmmo_DoesNotDropBelowZero() { HeroRuntimeService service = CreateService(); service.AddSpecialAmmo(-100); Assert.Equal(0, service.State.SpecialAmmo); } [Fact] public void SquadronMatePickup_ChangesTypeAndCapsCount() { HeroRuntimeService service = CreateService(); for (int i = 0; i < 6; i++) { service.ApplySquadronMatePickup("squadron.orbit"); } Assert.Equal("squadron.orbit", service.State.SquadronMateTypeId); Assert.Equal(4, service.State.SquadronMateCount); } [Fact] public void ClearInventory_ResetsCollectibleDerivedState() { HeroRuntimeService service = CreateService(); service.TogglePrimaryWeaponSlot(); service.ApplyPrimaryWeaponPickup("weapon.primary.basic"); service.AddSpecialAmmo(3); service.ApplySquadronMatePickup("squadron.orbit"); service.ClearInventory(); Assert.Equal(0, service.State.SelectedPrimaryWeaponSlotIndex); Assert.Equal("weapon.primary.basic", service.State.PrimaryWeaponSlots[0]); Assert.Null(service.State.PrimaryWeaponSlots[1]); Assert.Equal("weapon.secondary.vertical", service.State.CurrentSecondaryWeaponId); Assert.Equal(12, service.State.SpecialAmmo); Assert.Equal(string.Empty, service.State.SquadronMateTypeId); Assert.Equal(0, service.State.SquadronMateCount); } [Fact] public void ApplyHit_WithInvulnerability_PreventsDamage() { HeroRuntimeService service = CreateService(); service.ApplyHit(true); Assert.Equal(HeroLifeState.Alive, service.State.LifeState); Assert.Equal(3, service.State.ShieldCharges); } private static HeroRuntimeService CreateService(string difficultyId = "difficulty.normal") { ContentRegistry registry = SampleContent.CreateRegistry(); return new HeroRuntimeService(registry, HeroRuleConfig.CreateDefault(), difficultyId); } }