using CartWise.Domain.Entities; using CartWise.Domain.Enums; using System.Reflection; namespace CartWise.Domain.Tests; public class PriceObservationTests { private static readonly DateTime Now = new(2026, 8, 10, 12, 0, 0, DateTimeKind.Utc); [Fact] public void Constructor_SetsDefaultCurrencyCode() { var observation = new PriceObservation(Guid.NewGuid(), 3.99m, Now, PriceObservationSourceType.UserEntered, 1m, Now); Assert.Equal("USD", observation.CurrencyCode); } [Fact] public void Constructor_ThrowsWhenProductIdIsEmpty() { Assert.Throws(() => new PriceObservation(Guid.Empty, 3.99m, Now, PriceObservationSourceType.UserEntered, 1m, Now)); } [Fact] public void Constructor_ThrowsWhenPriceIsNegative() { Assert.Throws(() => new PriceObservation(Guid.NewGuid(), -1m, Now, PriceObservationSourceType.UserEntered, 1m, Now)); } [Theory] [InlineData(-0.01)] [InlineData(1.01)] public void Constructor_ThrowsWhenConfidenceScoreIsOutOfRange(decimal confidence) { Assert.Throws(() => new PriceObservation(Guid.NewGuid(), 3.99m, Now, PriceObservationSourceType.UserEntered, confidence, Now)); } [Fact] public void Constructor_ThrowsWhenCurrencyCodeIsNotThreeLetters() { Assert.Throws(() => new PriceObservation(Guid.NewGuid(), 3.99m, Now, PriceObservationSourceType.UserEntered, 1m, Now, currencyCode: "US")); } [Fact] public void Type_HasNoPublicMutationMethods() { // Append-only enforcement: nothing beyond the constructor may change an existing // observation's state. If this test ever needs updating, the append-only invariant // has likely been broken. var publicMethods = typeof(PriceObservation) .GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(m => !m.IsSpecialName) // exclude property getters .ToList(); Assert.Empty(publicMethods); } }