IntentValidationTests.cs
1 using GUNRPG.Core; 2 using GUNRPG.Core.Intents; 3 using GUNRPG.Core.Operators; 4 5 namespace GUNRPG.Tests.Core; 6 7 /// <summary> 8 /// Domain-level tests for intent validation logic. 9 /// These tests focus on the core domain rules without application or API concerns. 10 /// </summary> 11 public class IntentValidationTests 12 { 13 [Fact] 14 public void FireWeaponIntent_RequiresAmmo() 15 { 16 var op = CreateOperator(); 17 op.CurrentAmmo = 0; 18 19 var intent = new FireWeaponIntent(op.Id); 20 var (isValid, errorMessage) = intent.Validate(op); 21 22 Assert.False(isValid); 23 Assert.Contains("no ammo", errorMessage, StringComparison.OrdinalIgnoreCase); 24 } 25 26 [Fact] 27 public void FireWeaponIntent_ValidWithAmmo() 28 { 29 var op = CreateOperator(); 30 op.CurrentAmmo = 10; 31 32 var intent = new FireWeaponIntent(op.Id); 33 var (isValid, errorMessage) = intent.Validate(op); 34 35 Assert.True(isValid); 36 Assert.Null(errorMessage); 37 } 38 39 [Fact] 40 public void ReloadIntent_FailsWhenMagazineFull() 41 { 42 var op = CreateOperator(); 43 op.CurrentAmmo = op.EquippedWeapon!.MagazineSize; 44 45 var intent = new ReloadIntent(op.Id); 46 var (isValid, errorMessage) = intent.Validate(op); 47 48 Assert.False(isValid); 49 Assert.Contains("full", errorMessage, StringComparison.OrdinalIgnoreCase); 50 } 51 52 [Fact] 53 public void ReloadIntent_ValidWhenNotFull() 54 { 55 var op = CreateOperator(); 56 op.CurrentAmmo = 5; 57 58 var intent = new ReloadIntent(op.Id); 59 var (isValid, errorMessage) = intent.Validate(op); 60 61 Assert.True(isValid); 62 Assert.Null(errorMessage); 63 } 64 65 [Fact] 66 public void SprintIntent_RequiresStamina() 67 { 68 var op = CreateOperator(); 69 op.Stamina = 0; 70 71 var intent = new SprintIntent(op.Id, towardOpponent: true); 72 var (isValid, errorMessage) = intent.Validate(op); 73 74 Assert.False(isValid); 75 Assert.Contains("stamina", errorMessage, StringComparison.OrdinalIgnoreCase); 76 } 77 78 [Fact] 79 public void SprintIntent_ValidWithStamina() 80 { 81 var op = CreateOperator(); 82 op.Stamina = 50; 83 84 var intent = new SprintIntent(op.Id, towardOpponent: true); 85 var (isValid, errorMessage) = intent.Validate(op); 86 87 Assert.True(isValid); 88 Assert.Null(errorMessage); 89 } 90 91 [Fact] 92 public void EnterADSIntent_FailsWhenAlreadyInADS() 93 { 94 var op = CreateOperator(); 95 op.AimState = AimState.ADS; 96 97 var intent = new EnterADSIntent(op.Id); 98 var (isValid, errorMessage) = intent.Validate(op); 99 100 Assert.False(isValid); 101 Assert.Contains("already", errorMessage, StringComparison.OrdinalIgnoreCase); 102 } 103 104 [Fact] 105 public void EnterADSIntent_ValidWhenInHipFire() 106 { 107 var op = CreateOperator(); 108 op.AimState = AimState.Hip; 109 110 var intent = new EnterADSIntent(op.Id); 111 var (isValid, errorMessage) = intent.Validate(op); 112 113 Assert.True(isValid); 114 Assert.Null(errorMessage); 115 } 116 117 private static Operator CreateOperator() 118 { 119 return new Operator("TestOperator") 120 { 121 EquippedWeapon = WeaponFactory.CreateSokol545(), 122 CurrentAmmo = 30, 123 Stamina = 100 124 }; 125 } 126 }