|
- using CartWise.Application.Services;
- using CartWise.Domain.Enums;
- using CartWise.Infrastructure.Data;
- using Microsoft.EntityFrameworkCore;
-
- namespace CartWise.Application.Tests;
-
- public class PriceServiceTests : IDisposable
- {
- private static readonly DateTime Now = new(2026, 8, 10, 12, 0, 0, DateTimeKind.Utc);
-
- private readonly CartWiseDbContext _db;
- private readonly PriceService _sut;
-
- public PriceServiceTests()
- {
- var options = new DbContextOptionsBuilder<CartWiseDbContext>()
- .UseInMemoryDatabase(Guid.NewGuid().ToString())
- .Options;
-
- _db = new CartWiseDbContext(options);
- _sut = new PriceService(_db, TimeProvider.System);
- }
-
- public void Dispose()
- {
- _db.Dispose();
- GC.SuppressFinalize(this);
- }
-
- [Fact]
- public async Task GetHouseholdPriceInsightAsync_ReturnsNullWhenNoObservationsExist()
- {
- var insight = await _sut.GetHouseholdPriceInsightAsync(Guid.NewGuid(), Guid.NewGuid());
-
- Assert.Null(insight);
- }
-
- [Fact]
- public async Task RecordObservationAsync_ThenGetInsight_ReturnsLatestAverageMedianAndLowest()
- {
- var householdId = Guid.NewGuid();
- var productId = Guid.NewGuid();
-
- await _sut.RecordObservationAsync(productId, 3.00m, Now.AddDays(-2), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
- await _sut.RecordObservationAsync(productId, 5.00m, Now.AddDays(-1), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
- await _sut.RecordObservationAsync(productId, 4.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
-
- var insight = await _sut.GetHouseholdPriceInsightAsync(householdId, productId);
-
- Assert.NotNull(insight);
- Assert.Equal(3, insight!.ObservationCount);
- Assert.Equal(4.00m, insight.LatestPrice);
- Assert.Equal(Now, insight.LatestObservedUtc);
- Assert.Equal(4.00m, insight.AveragePrice);
- Assert.Equal(4.00m, insight.MedianPrice);
- Assert.Equal(3.00m, insight.LowestPrice);
- }
-
- [Fact]
- public async Task GetHouseholdPriceInsightAsync_ComputesMedianForEvenCount()
- {
- var householdId = Guid.NewGuid();
- var productId = Guid.NewGuid();
-
- await _sut.RecordObservationAsync(productId, 2.00m, Now.AddDays(-1), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
- await _sut.RecordObservationAsync(productId, 4.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
-
- var insight = await _sut.GetHouseholdPriceInsightAsync(householdId, productId);
-
- Assert.Equal(3.00m, insight!.MedianPrice);
- }
-
- [Fact]
- public async Task GetHouseholdPriceInsightAsync_DoesNotMixDifferentHouseholds()
- {
- var productId = Guid.NewGuid();
- await _sut.RecordObservationAsync(productId, 3.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: Guid.NewGuid());
-
- var insight = await _sut.GetHouseholdPriceInsightAsync(Guid.NewGuid(), productId);
-
- Assert.Null(insight);
- }
-
- [Fact]
- public async Task GetHouseholdPriceHistoryAsync_ReturnsNewestFirst()
- {
- var householdId = Guid.NewGuid();
- var productId = Guid.NewGuid();
- await _sut.RecordObservationAsync(productId, 3.00m, Now.AddDays(-1), PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
- await _sut.RecordObservationAsync(productId, 4.00m, Now, PriceObservationSourceType.UserEntered, 1m, householdId: householdId);
-
- var history = await _sut.GetHouseholdPriceHistoryAsync(householdId, productId);
-
- Assert.Equal(2, history.Count);
- Assert.Equal(4.00m, history[0].Price);
- Assert.Equal(3.00m, history[1].Price);
- }
- }
|