using System; using System.Linq; using FluentAssertions; using TeleBot.Models; using Xunit; namespace TeleBot.Tests.Models { public class ShoppingCartVariantsTests { [Fact] public void AddItem_WithVariant_ShouldStoreVariantInfo() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); // Act cart.AddItem(productId, "T-Shirt", 25.00m, 1, null, "Red"); // Assert cart.Items.Should().HaveCount(1); var item = cart.Items.First(); item.SelectedVariant.Should().Be("Red"); item.ProductName.Should().Be("T-Shirt"); item.TotalPrice.Should().Be(25.00m); } [Fact] public void AddItem_WithMultiBuy_ShouldStoreMultiBuyInfo() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); var multiBuyId = Guid.NewGuid(); // Act cart.AddItem(productId, "Soap - 3 for £5", 5.00m, 3, multiBuyId, null); // Assert cart.Items.Should().HaveCount(1); var item = cart.Items.First(); item.MultiBuyId.Should().Be(multiBuyId); item.Quantity.Should().Be(3); item.UnitPrice.Should().Be(5.00m); item.TotalPrice.Should().Be(5.00m); // Total for the multi-buy, not per unit } [Fact] public void AddItem_WithMultiBuyAndVariant_ShouldStoreBoth() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); var multiBuyId = Guid.NewGuid(); // Act cart.AddItem(productId, "Candle - 3 for £25 - Vanilla", 25.00m, 3, multiBuyId, "Vanilla"); // Assert cart.Items.Should().HaveCount(1); var item = cart.Items.First(); item.MultiBuyId.Should().Be(multiBuyId); item.SelectedVariant.Should().Be("Vanilla"); item.ProductName.Should().Be("Candle - 3 for £25 - Vanilla"); item.Quantity.Should().Be(3); item.TotalPrice.Should().Be(25.00m); } [Fact] public void AddItem_SameProductDifferentVariants_ShouldAddSeparately() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); // Act cart.AddItem(productId, "T-Shirt - Red", 25.00m, 1, null, "Red"); cart.AddItem(productId, "T-Shirt - Blue", 25.00m, 2, null, "Blue"); // Assert cart.Items.Should().HaveCount(2); cart.Items.Should().Contain(i => i.SelectedVariant == "Red" && i.Quantity == 1); cart.Items.Should().Contain(i => i.SelectedVariant == "Blue" && i.Quantity == 2); cart.GetTotalAmount().Should().Be(75.00m); } [Fact] public void AddItem_SameProductSameVariant_ShouldIncreaseQuantity() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); // Act cart.AddItem(productId, "T-Shirt - Red", 25.00m, 1, null, "Red"); cart.AddItem(productId, "T-Shirt - Red", 25.00m, 2, null, "Red"); // Assert cart.Items.Should().HaveCount(1); cart.Items.First().Quantity.Should().Be(3); cart.Items.First().SelectedVariant.Should().Be("Red"); cart.GetTotalAmount().Should().Be(75.00m); } [Fact] public void AddItem_SameProductDifferentMultiBuys_ShouldAddSeparately() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); var multiBuyId1 = Guid.NewGuid(); var multiBuyId2 = Guid.NewGuid(); // Act cart.AddItem(productId, "Soap - Single", 2.00m, 1, null, null); cart.AddItem(productId, "Soap - 3 for £5", 5.00m, 3, multiBuyId1, null); cart.AddItem(productId, "Soap - 6 for £9", 9.00m, 6, multiBuyId2, null); // Assert cart.Items.Should().HaveCount(3); cart.GetTotalItems().Should().Be(10); // 1 + 3 + 6 cart.GetTotalAmount().Should().Be(16.00m); // 2 + 5 + 9 } [Fact] public void ComplexCart_WithMultiBuysAndVariants_ShouldCalculateCorrectly() { // Arrange var cart = new ShoppingCart(); // Different products var tshirtId = Guid.NewGuid(); var candleId = Guid.NewGuid(); var soapId = Guid.NewGuid(); // MultiBuy IDs var candleMultiBuyId = Guid.NewGuid(); var soapMultiBuyId = Guid.NewGuid(); // Act // T-Shirts with color variants (no multi-buy) cart.AddItem(tshirtId, "T-Shirt - Red", 25.00m, 2, null, "Red"); cart.AddItem(tshirtId, "T-Shirt - Blue", 25.00m, 1, null, "Blue"); // Candles with multi-buy and flavor variants cart.AddItem(candleId, "Candle 3-Pack - Vanilla", 20.00m, 3, candleMultiBuyId, "Vanilla"); cart.AddItem(candleId, "Candle 3-Pack - Lavender", 20.00m, 3, candleMultiBuyId, "Lavender"); // Soap with multi-buy, no variant cart.AddItem(soapId, "Soap 5-Pack", 8.00m, 5, soapMultiBuyId, null); // Assert cart.Items.Should().HaveCount(5); cart.GetTotalItems().Should().Be(14); // 2 + 1 + 3 + 3 + 5 cart.GetTotalAmount().Should().Be(123.00m); // (25*2) + (25*1) + 20 + 20 + 8 } [Fact] public void RemoveItem_WithVariant_ShouldOnlyRemoveSpecificVariant() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); cart.AddItem(productId, "T-Shirt - Red", 25.00m, 1, null, "Red"); cart.AddItem(productId, "T-Shirt - Blue", 25.00m, 1, null, "Blue"); // Act // Note: Current implementation removes all items with the same productId // This test documents the current behavior cart.RemoveItem(productId); // Assert cart.IsEmpty().Should().BeTrue(); // In a future enhancement, might want to remove by productId + variant combination } [Fact] public void CartItem_WithMultiBuy_TotalPriceCalculation() { // Arrange var item = new CartItem { ProductId = Guid.NewGuid(), MultiBuyId = Guid.NewGuid(), ProductName = "3 for £10 Deal", UnitPrice = 10.00m, // This is the multi-buy price, not per-unit Quantity = 3 }; // Act item.UpdateTotalPrice(); // Assert // For multi-buys, UnitPrice is the bundle price item.TotalPrice.Should().Be(10.00m); } [Theory] [InlineData("Red", "Blue", false)] [InlineData("Red", "Red", true)] [InlineData(null, null, true)] [InlineData("Red", null, false)] [InlineData(null, "Blue", false)] public void CartItem_VariantComparison_ShouldWorkCorrectly( string? variant1, string? variant2, bool shouldMatch) { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); // Act cart.AddItem(productId, "Product", 10.00m, 1, null, variant1); cart.AddItem(productId, "Product", 10.00m, 1, null, variant2); // Assert if (shouldMatch) { cart.Items.Should().HaveCount(1); cart.Items.First().Quantity.Should().Be(2); } else { cart.Items.Should().HaveCount(2); cart.Items.Sum(i => i.Quantity).Should().Be(2); } } [Fact] public void UpdateQuantity_WithVariant_ShouldUpdateCorrectItem() { // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); cart.AddItem(productId, "T-Shirt - Red", 25.00m, 1, null, "Red"); cart.AddItem(productId, "T-Shirt - Blue", 25.00m, 1, null, "Blue"); // Act // Note: Current implementation updates by productId only cart.UpdateQuantity(productId, 5); // Assert // This documents current behavior - it updates the first matching productId var firstItem = cart.Items.FirstOrDefault(i => i.ProductId == productId); firstItem?.Quantity.Should().Be(5); } [Fact] public void Cart_Serialization_WithVariantsAndMultiBuys() { // This test ensures the cart can be properly serialized/deserialized // which is important for session storage // Arrange var cart = new ShoppingCart(); var productId = Guid.NewGuid(); var multiBuyId = Guid.NewGuid(); cart.AddItem(productId, "Complex Product", 50.00m, 3, multiBuyId, "Premium"); // Act var json = System.Text.Json.JsonSerializer.Serialize(cart); var deserializedCart = System.Text.Json.JsonSerializer.Deserialize(json); // Assert deserializedCart.Should().NotBeNull(); deserializedCart!.Items.Should().HaveCount(1); var item = deserializedCart.Items.First(); item.ProductId.Should().Be(productId); item.MultiBuyId.Should().Be(multiBuyId); item.SelectedVariant.Should().Be("Premium"); item.Quantity.Should().Be(3); item.UnitPrice.Should().Be(50.00m); } } }