From 4e53ff8a37ecad1edcd59e7ed8742303bca41736 Mon Sep 17 00:00:00 2001 From: Khwezi Mngoma Date: Thu, 28 May 2026 17:28:33 +0200 Subject: [PATCH] ProductService tested and stable --- ...eCharms.Features.MidrandBooks.Tests.csproj | 1 + .../ProductServiceFeatureTest.cs | 54 ++++++++++++++++++- .../Products/ProductService.cs | 23 ++++---- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/LiteCharms.Features.MidrandBooks.Tests/LiteCharms.Features.MidrandBooks.Tests.csproj b/LiteCharms.Features.MidrandBooks.Tests/LiteCharms.Features.MidrandBooks.Tests.csproj index 9eba9bd..3b0e796 100644 --- a/LiteCharms.Features.MidrandBooks.Tests/LiteCharms.Features.MidrandBooks.Tests.csproj +++ b/LiteCharms.Features.MidrandBooks.Tests/LiteCharms.Features.MidrandBooks.Tests.csproj @@ -39,6 +39,7 @@ + diff --git a/LiteCharms.Features.MidrandBooks.Tests/ProductServiceFeatureTest.cs b/LiteCharms.Features.MidrandBooks.Tests/ProductServiceFeatureTest.cs index 3c41d55..c498909 100644 --- a/LiteCharms.Features.MidrandBooks.Tests/ProductServiceFeatureTest.cs +++ b/LiteCharms.Features.MidrandBooks.Tests/ProductServiceFeatureTest.cs @@ -1,7 +1,6 @@ using LiteCharms.Features.MidrandBooks.Products; using LiteCharms.Features.MidrandBooks.Products.Models; using LiteCharms.Features.Models; -using System.Text.Json; namespace LiteCharms.Features.MidrandBooks.Tests; @@ -9,6 +8,59 @@ public class ProductServiceFeatureTest(Fixture fixture, ITestOutputHelper output { private readonly ProductService productService = fixture.Services.GetRequiredService(); + [IntegrationFact] + public async Task GetProductPriceAsync_ShouldReturn_RetultOneProductPrice() + { + var result = await productService.GetProductPriceAsync(2, fixture.CancellationToken); + + Assert.True(result.IsSuccess); + Assert.NotNull(result.Value); + + output.WriteLine(JsonSerializer.Serialize(result.Value)); + } + + [IntegrationFact] + public async Task GetProductPricesAsync_ShouldReturn_RetultProductPriceList() + { + var result = await productService.GetProductPricesAsync(2, fixture.CancellationToken); + + Assert.True(result.IsSuccess); + Assert.NotEmpty(result.Value); + + output.WriteLine(JsonSerializer.Serialize(result.Value)); + } + + [IntegrationFact] + public async Task SearchProductsAsync_ShouldReturn_RetultMatchingProducts() + { + var filter = new ProductFilter + { + Name = "system", + Manufacturer = "techwave", + SerialNumber = "2024", + MinPrice = 10, + MaxPrice = 30 + }; + + var result = await productService.SearchProductsAsync(filter, fixture.CancellationToken); + + Assert.True(result.IsSuccess); + Assert.NotEmpty(result.Value); + + output.WriteLine(JsonSerializer.Serialize(result.Value)); + } + + [IntegrationFact] + public async Task GetProductAsync_ShouldReturn_RetultOneProduct() + { + var result = await productService.GetProductAsync(2, fixture.CancellationToken); + + Assert.True(result.IsSuccess); + Assert.NotNull(result.Value); + + output.WriteLine(JsonSerializer.Serialize(result.Value)); + } + [IntegrationFact] public async Task GetProductsAsync_ShouldReturn_RetultProducts() { diff --git a/LiteCharms.Features.MidrandBooks/Products/ProductService.cs b/LiteCharms.Features.MidrandBooks/Products/ProductService.cs index a43e489..aef7710 100644 --- a/LiteCharms.Features.MidrandBooks/Products/ProductService.cs +++ b/LiteCharms.Features.MidrandBooks/Products/ProductService.cs @@ -64,17 +64,22 @@ public sealed class ProductService(IDbContextFactory cont var query = context.Products.AsQueryable(); + var cultureInfo = CultureInfo.InvariantCulture; + + if (!string.IsNullOrWhiteSpace(filter.Name)) + query = query.Where(p => EF.Functions.ILike(p.Name!, $"%{filter.Name}%")); + if (!string.IsNullOrWhiteSpace(filter.Title)) - query = query.Where(p => p.Name!.Contains(filter.Title)); + query = query.Where(p => EF.Functions.ILike(p.Name!, $"%{filter.Title}%")); if (!string.IsNullOrWhiteSpace(filter.Category)) - query = query.Where(p => p.Categories!.Any(c => c == filter.Category)); + query = query.Where(p => p.Categories.Contains(filter.Category)); if (!string.IsNullOrWhiteSpace(filter.Manufacturer)) - query = query.Where(p => p.Metadata!.Manufacturer == filter.Manufacturer); + query = query.Where(p => EF.Functions.ILike(p.Metadata!.Manufacturer!, $"%{filter.Manufacturer}%")); if (!string.IsNullOrWhiteSpace(filter.SerialNumber)) - query = query.Where(p => p.Metadata!.SerialNumber == filter.SerialNumber); + query = query.Where(p => EF.Functions.ILike(p.Metadata!.SerialNumber!, $"%{filter.SerialNumber}%")); if (filter.MinPrice > 0) query = query.Where(p => p.Prices!.Any(pr => pr.Amount >= filter.MinPrice && pr.Amount <= filter.MaxPrice)); @@ -165,7 +170,7 @@ public sealed class ProductService(IDbContextFactory cont } } - public async ValueTask> GetProductPriceAsync(long productId, CancellationToken cancellationToken = default) + public async ValueTask> GetProductPriceAsync(long productId, CancellationToken cancellationToken = default) { try { @@ -175,16 +180,16 @@ public sealed class ProductService(IDbContextFactory cont .AsNoTracking() .OrderByDescending(p => p.CreatedAt) .ThenBy(p => p.UpdatedAt) - .FirstOrDefaultAsync(p => p.ProductId == productId, cancellationToken); + .FirstOrDefaultAsync(p => p.ProductId == productId && p.Enabled, cancellationToken); return product is not null - ? Result.Ok(new[] { product.ToModel() }) - : Result.Fail(new Error($"No price found for product with ID {productId}")); + ? Result.Ok(product.ToModel()) + : Result.Fail(new Error($"No price found for product with ID {productId}")); } catch (Exception ex) { - return Result.Fail(new Error(ex.Message).CausedBy(ex)); + return Result.Fail(new Error(ex.Message).CausedBy(ex)); } }