Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

160 řádky
5.1KB

  1. using CartWise.Application.DTOs;
  2. using CartWise.Application.Services;
  3. using CartWise.Domain.Entities;
  4. using CartWise.Domain.Enums;
  5. using CartWise.Infrastructure.Data;
  6. using Microsoft.EntityFrameworkCore;
  7. namespace CartWise.Application.Tests;
  8. public class ProductServiceTests : IDisposable
  9. {
  10. private static readonly DateTime Now = new(2026, 8, 10, 12, 0, 0, DateTimeKind.Utc);
  11. private readonly CartWiseDbContext _db;
  12. private readonly ProductService _sut;
  13. public ProductServiceTests()
  14. {
  15. var options = new DbContextOptionsBuilder<CartWiseDbContext>()
  16. .UseInMemoryDatabase(Guid.NewGuid().ToString())
  17. .Options;
  18. _db = new CartWiseDbContext(options);
  19. _sut = new ProductService(_db, [], TimeProvider.System);
  20. }
  21. public void Dispose()
  22. {
  23. _db.Dispose();
  24. GC.SuppressFinalize(this);
  25. }
  26. [Fact]
  27. public async Task SearchAsync_ReturnsMatchingProductsWithBrandName()
  28. {
  29. var brand = new Brand("Jif");
  30. var product = new Product("Jif Creamy Peanut Butter", ProductSourceType.Manual, Now, brandId: brand.BrandId, sizeValue: 16m, sizeUnit: "oz");
  31. _db.Brands.Add(brand);
  32. _db.Products.Add(product);
  33. await _db.SaveChangesAsync();
  34. var results = await _sut.SearchAsync("peanut");
  35. var result = Assert.Single(results);
  36. Assert.Equal("Jif Creamy Peanut Butter", result.Name);
  37. Assert.Equal("Jif", result.BrandName);
  38. Assert.Equal("16 oz", result.PackageDisplay);
  39. }
  40. [Fact]
  41. public async Task SearchAsync_ReturnsEmptyForBlankQuery()
  42. {
  43. var results = await _sut.SearchAsync(" ");
  44. Assert.Empty(results);
  45. }
  46. [Fact]
  47. public async Task SearchAsync_ReturnsEmptyWhenNothingMatches()
  48. {
  49. _db.Products.Add(new Product("Whole Milk", ProductSourceType.Manual, Now));
  50. await _db.SaveChangesAsync();
  51. var results = await _sut.SearchAsync("cereal");
  52. Assert.Empty(results);
  53. }
  54. [Fact]
  55. public async Task GetDetailsAsync_ReturnsNullWhenProductDoesNotExist()
  56. {
  57. var details = await _sut.GetDetailsAsync(Guid.NewGuid());
  58. Assert.Null(details);
  59. }
  60. [Fact]
  61. public async Task GetDetailsAsync_ReturnsBrandConceptAndIdentifiers()
  62. {
  63. var brand = new Brand("Jif");
  64. var concept = new GroceryConcept("Peanut Butter", Now);
  65. var product = new Product("Jif Creamy 16 oz", ProductSourceType.Manual, Now, groceryConceptId: concept.GroceryConceptId, brandId: brand.BrandId);
  66. product.AddIdentifier(ProductIdentifierType.UpcA, "051500255516");
  67. _db.Brands.Add(brand);
  68. _db.GroceryConcepts.Add(concept);
  69. _db.Products.Add(product);
  70. await _db.SaveChangesAsync();
  71. var details = await _sut.GetDetailsAsync(product.ProductId);
  72. Assert.NotNull(details);
  73. Assert.Equal("Jif", details!.BrandName);
  74. Assert.Equal("Peanut Butter", details.ConceptName);
  75. Assert.Equal("051500255516", Assert.Single(details.BarcodeIdentifiers));
  76. }
  77. [Fact]
  78. public async Task ResolveBarcodeAsync_ReturnsLocalProductWithoutCallingProvider()
  79. {
  80. var product = new Product("Whole Milk", ProductSourceType.Manual, Now);
  81. product.AddIdentifier(ProductIdentifierType.UpcA, "111111111111");
  82. _db.Products.Add(product);
  83. await _db.SaveChangesAsync();
  84. var sut = new ProductService(_db, [], TimeProvider.System);
  85. var result = await sut.ResolveBarcodeAsync("111111111111");
  86. Assert.True(result.IsSuccess);
  87. Assert.Equal("Whole Milk", result.Value!.Name);
  88. }
  89. [Fact]
  90. public async Task ResolveBarcodeAsync_FallsBackToProviderAndPersistsResult()
  91. {
  92. var provider = new FakeProductDataProvider(new Dictionary<string, ProductLookupResult>
  93. {
  94. ["222222222222"] = new ProductLookupResult
  95. {
  96. Name = "Imported Cereal",
  97. BrandName = "Acme",
  98. SizeValue = 12m,
  99. SizeUnit = "oz",
  100. SourceExternalId = "off-123"
  101. }
  102. });
  103. var sut = new ProductService(_db, [provider], TimeProvider.System);
  104. var result = await sut.ResolveBarcodeAsync("222222222222");
  105. Assert.True(result.IsSuccess);
  106. Assert.Equal("Imported Cereal", result.Value!.Name);
  107. Assert.Equal("Acme", result.Value.BrandName);
  108. var persisted = await _db.Products.AsNoTracking().SingleAsync();
  109. Assert.Equal(ProductSourceType.OpenFoodFacts, persisted.SourceType);
  110. Assert.Equal("off-123", persisted.SourceExternalId);
  111. }
  112. [Fact]
  113. public async Task ResolveBarcodeAsync_FailsWhenNoLocalMatchAndNoProviderResult()
  114. {
  115. var provider = new FakeProductDataProvider(new Dictionary<string, ProductLookupResult>());
  116. var sut = new ProductService(_db, [provider], TimeProvider.System);
  117. var result = await sut.ResolveBarcodeAsync("999999999999");
  118. Assert.False(result.IsSuccess);
  119. }
  120. [Fact]
  121. public async Task ResolveBarcodeAsync_FailsWhenBarcodeIsMissing()
  122. {
  123. var result = await _sut.ResolveBarcodeAsync(" ");
  124. Assert.False(result.IsSuccess);
  125. }
  126. }

Powered by TurnKey Linux.