/ 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  }