using GitConverter.Lib.Models; namespace GitConverter.TestsApp.Models { /// /// Unit tests for . /// /// /// - Verifies factory helpers, timestamp behavior and logical equality semantics (IEquatable). /// - Equality is defined by Status + Message only; TimestampUtc is diagnostic metadata and excluded. /// - Timestamp assertions use a small tolerant window to avoid flakes on slow CI agents. /// public class ConversionResultTests { [Fact(DisplayName = "Success factory creates success result")] public void Success_CreatesSuccessResult() { var msg = "Converted successfully"; var result = ConversionResult.Success(msg); Assert.True(result.IsSuccess); Assert.Equal(ConversionStatus.Success, result.Status); Assert.Equal(msg, result.Message); Assert.Equal(DateTimeKind.Utc, result.TimestampUtc.Kind); } [Fact(DisplayName = "Failure factory creates failure result")] public void Failure_CreatesFailureResult() { var msg = "Something went wrong"; var result = ConversionResult.Failure(msg); Assert.False(result.IsSuccess); Assert.Equal(ConversionStatus.Failure, result.Status); Assert.Equal(msg, result.Message); Assert.Equal(DateTimeKind.Utc, result.TimestampUtc.Kind); } [Fact(DisplayName = "Null message is converted to empty string")] public void NullMessage_BecomesEmptyString() { var r1 = ConversionResult.Success(null); var r2 = ConversionResult.Failure(null); Assert.NotNull(r1.Message); Assert.Equal(string.Empty, r1.Message); Assert.NotNull(r2.Message); Assert.Equal(string.Empty, r2.Message); } [Fact(DisplayName = "TimestampUtc is recent and UTC")] public void TimestampUtc_IsRecentAndUtc() { var before = DateTime.UtcNow; var result = ConversionResult.Success("x"); var after = DateTime.UtcNow; Assert.Equal(DateTimeKind.Utc, result.TimestampUtc.Kind); // Allow a small tolerance window to avoid CI flakiness Assert.True(result.TimestampUtc >= before.AddSeconds(-1), $"Timestamp {result.TimestampUtc:o} is earlier than expected (before={before:o})"); Assert.True(result.TimestampUtc <= after.AddSeconds(1), $"Timestamp {result.TimestampUtc:o} is later than expected (after={after:o})"); } [Fact(DisplayName = "Multiple creations produce non-decreasing timestamps")] public void MultipleCreations_TimestampsNonDecreasing() { var a = ConversionResult.Success("a"); Thread.Sleep(5); var b = ConversionResult.Success("b"); Assert.True(b.TimestampUtc >= a.TimestampUtc, $"Expected second timestamp >= first timestamp ({b.TimestampUtc:o} >= {a.TimestampUtc:o})"); } [Fact(DisplayName = "ToString returns 'Status: Message'")] public void ToString_FormatsStatusAndMessage() { var success = ConversionResult.Success("ok"); var failure = ConversionResult.Failure("bad"); Assert.Equal($"{ConversionStatus.Success}: ok", success.ToString()); Assert.Equal($"{ConversionStatus.Failure}: bad", failure.ToString()); } [Fact(DisplayName = "Equality: same status and message are equal despite different timestamps")] public void Equality_SameStatusAndMessage_AreEqual() { var a = ConversionResult.Success("same"); Thread.Sleep(10); var b = ConversionResult.Success("same"); Assert.Equal(a, b); // Equals Assert.True(a == b); // operator == Assert.False(a != b); Assert.Equal(a.GetHashCode(), b.GetHashCode()); } [Fact(DisplayName = "Equality: different messages are not equal")] public void Equality_DifferentMessage_NotEqual() { var a = ConversionResult.Success("one"); var b = ConversionResult.Success("two"); Assert.NotEqual(a, b); Assert.False(a == b); Assert.True(a != b); } [Fact(DisplayName = "Equality: different status with same message are not equal")] public void Equality_DifferentStatus_NotEqual() { var a = ConversionResult.Success("m"); var b = ConversionResult.Failure("m"); Assert.NotEqual(a, b); Assert.False(a == b); Assert.True(a != b); } [Fact(DisplayName = "Equals handles null and other types safely")] public void Equals_NullAndOtherType() { var a = ConversionResult.Success("x"); Assert.False(a.Equals(null)); Assert.False(a.Equals((object)"not a conversion result")); } } }