/ GUNRPG.Tests / OperatorStatusViewTests.cs
OperatorStatusViewTests.cs
1 using GUNRPG.Core.VirtualPet; 2 using Xunit; 3 4 namespace GUNRPG.Tests; 5 6 public class OperatorStatusViewTests 7 { 8 [Fact] 9 public void From_CreatesView_WithAllPhysicalAttributes() 10 { 11 // Arrange 12 var petState = new PetState( 13 OperatorId: Guid.NewGuid(), 14 Health: 75.0f, 15 Fatigue: 30.0f, 16 Injury: 10.0f, 17 Stress: 40.0f, 18 Morale: 80.0f, 19 Hunger: 25.0f, 20 Hydration: 60.0f, 21 LastUpdated: DateTimeOffset.UtcNow 22 ); 23 24 // Act 25 var view = OperatorStatusView.From(petState); 26 27 // Assert - Physical 28 Assert.Equal(75.0f, view.Health); 29 Assert.Equal(10.0f, view.Injury); 30 Assert.Equal(30.0f, view.Fatigue); 31 } 32 33 [Fact] 34 public void From_CreatesView_WithAllMentalAttributes() 35 { 36 // Arrange 37 var petState = new PetState( 38 OperatorId: Guid.NewGuid(), 39 Health: 75.0f, 40 Fatigue: 30.0f, 41 Injury: 10.0f, 42 Stress: 40.0f, 43 Morale: 80.0f, 44 Hunger: 25.0f, 45 Hydration: 60.0f, 46 LastUpdated: DateTimeOffset.UtcNow 47 ); 48 49 // Act 50 var view = OperatorStatusView.From(petState); 51 52 // Assert - Mental 53 Assert.Equal(40.0f, view.Stress); 54 Assert.Equal(80.0f, view.Morale); 55 } 56 57 [Fact] 58 public void From_CreatesView_WithAllCareAttributes() 59 { 60 // Arrange 61 var petState = new PetState( 62 OperatorId: Guid.NewGuid(), 63 Health: 75.0f, 64 Fatigue: 30.0f, 65 Injury: 10.0f, 66 Stress: 40.0f, 67 Morale: 80.0f, 68 Hunger: 25.0f, 69 Hydration: 60.0f, 70 LastUpdated: DateTimeOffset.UtcNow 71 ); 72 73 // Act 74 var view = OperatorStatusView.From(petState); 75 76 // Assert - Care 77 Assert.Equal(25.0f, view.Hunger); 78 Assert.Equal(60.0f, view.Hydration); 79 } 80 81 [Fact] 82 public void From_SetsCombatReadiness_ToNull() 83 { 84 // Arrange 85 var petState = new PetState( 86 OperatorId: Guid.NewGuid(), 87 Health: 100.0f, 88 Fatigue: 0.0f, 89 Injury: 0.0f, 90 Stress: 0.0f, 91 Morale: 100.0f, 92 Hunger: 0.0f, 93 Hydration: 100.0f, 94 LastUpdated: DateTimeOffset.UtcNow 95 ); 96 97 // Act 98 var view = OperatorStatusView.From(petState); 99 100 // Assert 101 Assert.Null(view.CombatReadiness); 102 } 103 104 [Fact] 105 public void From_IsDeterministic_ProducesSameOutput() 106 { 107 // Arrange 108 var petState = new PetState( 109 OperatorId: Guid.NewGuid(), 110 Health: 50.0f, 111 Fatigue: 60.0f, 112 Injury: 20.0f, 113 Stress: 70.0f, 114 Morale: 40.0f, 115 Hunger: 80.0f, 116 Hydration: 30.0f, 117 LastUpdated: DateTimeOffset.UtcNow 118 ); 119 120 // Act 121 var view1 = OperatorStatusView.From(petState); 122 var view2 = OperatorStatusView.From(petState); 123 124 // Assert - Multiple calls produce equal results 125 Assert.Equal(view1, view2); 126 Assert.Equal(view1.Health, view2.Health); 127 Assert.Equal(view1.Injury, view2.Injury); 128 Assert.Equal(view1.Fatigue, view2.Fatigue); 129 Assert.Equal(view1.Stress, view2.Stress); 130 Assert.Equal(view1.Morale, view2.Morale); 131 Assert.Equal(view1.Hunger, view2.Hunger); 132 Assert.Equal(view1.Hydration, view2.Hydration); 133 Assert.Equal(view1.CombatReadiness, view2.CombatReadiness); 134 } 135 136 [Fact] 137 public void From_HandlesMinimumValues() 138 { 139 // Arrange 140 var petState = new PetState( 141 OperatorId: Guid.Empty, 142 Health: 0.0f, 143 Fatigue: 0.0f, 144 Injury: 0.0f, 145 Stress: 0.0f, 146 Morale: 0.0f, 147 Hunger: 0.0f, 148 Hydration: 0.0f, 149 LastUpdated: DateTimeOffset.MinValue 150 ); 151 152 // Act 153 var view = OperatorStatusView.From(petState); 154 155 // Assert 156 Assert.Equal(0.0f, view.Health); 157 Assert.Equal(0.0f, view.Injury); 158 Assert.Equal(0.0f, view.Fatigue); 159 Assert.Equal(0.0f, view.Stress); 160 Assert.Equal(0.0f, view.Morale); 161 Assert.Equal(0.0f, view.Hunger); 162 Assert.Equal(0.0f, view.Hydration); 163 } 164 165 [Fact] 166 public void From_HandlesMaximumValues() 167 { 168 // Arrange 169 var petState = new PetState( 170 OperatorId: Guid.NewGuid(), 171 Health: 100.0f, 172 Fatigue: 100.0f, 173 Injury: 100.0f, 174 Stress: 100.0f, 175 Morale: 100.0f, 176 Hunger: 100.0f, 177 Hydration: 100.0f, 178 LastUpdated: DateTimeOffset.MaxValue 179 ); 180 181 // Act 182 var view = OperatorStatusView.From(petState); 183 184 // Assert 185 Assert.Equal(100.0f, view.Health); 186 Assert.Equal(100.0f, view.Injury); 187 Assert.Equal(100.0f, view.Fatigue); 188 Assert.Equal(100.0f, view.Stress); 189 Assert.Equal(100.0f, view.Morale); 190 Assert.Equal(100.0f, view.Hunger); 191 Assert.Equal(100.0f, view.Hydration); 192 } 193 194 [Fact] 195 public void OperatorStatusView_SupportsValueEquality() 196 { 197 // Arrange 198 var view1 = new OperatorStatusView( 199 Health: 100.0f, 200 Injury: 0.0f, 201 Fatigue: 0.0f, 202 Stress: 0.0f, 203 Morale: 100.0f, 204 Hunger: 0.0f, 205 Hydration: 100.0f, 206 CombatReadiness: null 207 ); 208 209 var view2 = new OperatorStatusView( 210 Health: 100.0f, 211 Injury: 0.0f, 212 Fatigue: 0.0f, 213 Stress: 0.0f, 214 Morale: 100.0f, 215 Hunger: 0.0f, 216 Hydration: 100.0f, 217 CombatReadiness: null 218 ); 219 220 // Assert 221 Assert.Equal(view1, view2); 222 Assert.True(view1 == view2); 223 } 224 225 [Fact] 226 public void OperatorStatusView_IsImmutable() 227 { 228 // Arrange 229 var view = new OperatorStatusView( 230 Health: 100.0f, 231 Injury: 0.0f, 232 Fatigue: 0.0f, 233 Stress: 0.0f, 234 Morale: 100.0f, 235 Hunger: 0.0f, 236 Hydration: 100.0f, 237 CombatReadiness: null 238 ); 239 240 // Act - Verify we can only create new instances with 'with' expression 241 var newView = view with { Health = 50.0f }; 242 243 // Assert 244 Assert.Equal(100.0f, view.Health); 245 Assert.Equal(50.0f, newView.Health); 246 } 247 248 [Fact] 249 public void OperatorStatusView_DoesNotIncludeOperatorId() 250 { 251 // Arrange 252 var petState = new PetState( 253 OperatorId: Guid.NewGuid(), 254 Health: 100.0f, 255 Fatigue: 0.0f, 256 Injury: 0.0f, 257 Stress: 0.0f, 258 Morale: 100.0f, 259 Hunger: 0.0f, 260 Hydration: 100.0f, 261 LastUpdated: DateTimeOffset.UtcNow 262 ); 263 264 // Act 265 OperatorStatusView.From(petState); 266 267 // Assert - View should not expose OperatorId (presentation layer concern) 268 var properties = typeof(OperatorStatusView).GetProperties(); 269 Assert.DoesNotContain(properties, p => p.Name == "OperatorId"); 270 } 271 272 [Fact] 273 public void OperatorStatusView_DoesNotIncludeTimestamp() 274 { 275 // Arrange 276 var petState = new PetState( 277 OperatorId: Guid.NewGuid(), 278 Health: 100.0f, 279 Fatigue: 0.0f, 280 Injury: 0.0f, 281 Stress: 0.0f, 282 Morale: 100.0f, 283 Hunger: 0.0f, 284 Hydration: 100.0f, 285 LastUpdated: DateTimeOffset.UtcNow 286 ); 287 288 // Act 289 OperatorStatusView.From(petState); 290 291 // Assert - View should not expose timestamp (presentation layer concern) 292 var properties = typeof(OperatorStatusView).GetProperties(); 293 Assert.DoesNotContain(properties, p => p.Name == "LastUpdated"); 294 } 295 }