diff --git a/SimplCommerce.sln b/SimplCommerce.sln index 658e554ae..4e2b14bc6 100644 --- a/SimplCommerce.sln +++ b/SimplCommerce.sln @@ -136,6 +136,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimplCommerce.Module.Paymen EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimplCommerce.Module.Checkouts", "src\Modules\SimplCommerce.Module.Checkouts\SimplCommerce.Module.Checkouts.csproj", "{4473538D-2BFA-4C53-B642-0D0DC4F16863}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimplCommerce.Module.ProductComparison.Tests", "test\SimplCommerce.Module.ProductComparison.Tests\SimplCommerce.Module.ProductComparison.Tests.csproj", "{EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimplCommerce.Module.ShippingFree.Tests", "test\SimplCommerce.Module.ShippingFree.Tests\SimplCommerce.Module.ShippingFree.Tests.csproj", "{16BB6B44-3300-4C22-A37B-D9CD7A4EA300}" EndProject Global @@ -712,6 +713,18 @@ Global {4473538D-2BFA-4C53-B642-0D0DC4F16863}.Release|x64.Build.0 = Release|Any CPU {4473538D-2BFA-4C53-B642-0D0DC4F16863}.Release|x86.ActiveCfg = Release|Any CPU {4473538D-2BFA-4C53-B642-0D0DC4F16863}.Release|x86.Build.0 = Release|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Debug|x64.ActiveCfg = Debug|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Debug|x64.Build.0 = Debug|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Debug|x86.ActiveCfg = Debug|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Debug|x86.Build.0 = Debug|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Release|Any CPU.Build.0 = Release|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Release|x64.ActiveCfg = Release|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Release|x64.Build.0 = Release|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Release|x86.ActiveCfg = Release|Any CPU + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7}.Release|x86.Build.0 = Release|Any CPU {16BB6B44-3300-4C22-A37B-D9CD7A4EA300}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16BB6B44-3300-4C22-A37B-D9CD7A4EA300}.Debug|Any CPU.Build.0 = Debug|Any CPU {16BB6B44-3300-4C22-A37B-D9CD7A4EA300}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -779,6 +792,7 @@ Global {14586564-62CC-4117-AC1B-858ED53C2D6C} = {7EFA2FA7-32DD-4047-B021-50E77A83D714} {E30CF10F-FABF-4917-8BEB-CB81E4CE2C92} = {7EFA2FA7-32DD-4047-B021-50E77A83D714} {4473538D-2BFA-4C53-B642-0D0DC4F16863} = {7EFA2FA7-32DD-4047-B021-50E77A83D714} + {EEC02E89-E89A-4871-8C3E-4BABA1E56CA7} = {D9FD9ABA-AE5E-4427-AA6B-6285BE2E212D} {16BB6B44-3300-4C22-A37B-D9CD7A4EA300} = {D9FD9ABA-AE5E-4427-AA6B-6285BE2E212D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/test/SimplCommerce.Module.ProductComparison.Tests/Controllers/ComparingProductControllerTests.cs b/test/SimplCommerce.Module.ProductComparison.Tests/Controllers/ComparingProductControllerTests.cs new file mode 100644 index 000000000..83ab908e0 --- /dev/null +++ b/test/SimplCommerce.Module.ProductComparison.Tests/Controllers/ComparingProductControllerTests.cs @@ -0,0 +1,282 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Moq; +using SimplCommerce.Infrastructure.Data; +using SimplCommerce.Module.Catalog.Models; +using SimplCommerce.Module.Catalog.Services; +using SimplCommerce.Module.Core.Extensions; +using SimplCommerce.Module.Core.Models; +using SimplCommerce.Module.Core.Services; +using SimplCommerce.Module.ProductComparison.Areas.ProductComparison.Controllers; +using SimplCommerce.Module.ProductComparison.Areas.ProductComparison.ViewModels; +using SimplCommerce.Module.ProductComparison.Models; +using SimplCommerce.Module.ProductComparison.Services; +using Xunit; + +namespace SimplCommerce.Module.ProductComparison.Tests.Controllers +{ + public class ComparingProductControllerTests + { + [Fact] + public async Task AddToComparison_SuccessfullyAddsProduct() + { + // Arrange + var userId = 1; // Use a unique user id + var productId = 1001; + var model = new AddToComparisonModel { ProductId = productId }; + var repositoryMock = new Mock>(); + var comparingProductServiceMock = new Mock(); + var productPricingServiceMock = new Mock(); + var mediaServiceMock = new Mock(); + var contentLocalizationServiceMock = new Mock(); + var workContextMock = new Mock(); + var userManagerMock = new Mock>( + Mock.Of>(), null, null, null, null, null, null, null, null); + var controller = new ComparingProductController( + userManagerMock.Object, + repositoryMock.Object, + comparingProductServiceMock.Object, + productPricingServiceMock.Object, + mediaServiceMock.Object, + contentLocalizationServiceMock.Object, + workContextMock.Object + ); + var user = new User() + { + Id = userId, + UserName = "TestUser" + }; + workContextMock.Setup(repo => repo.GetCurrentUser()).ReturnsAsync(user); + + // Act + var result = await controller.AddToComparison(model); + + // Assert + comparingProductServiceMock.Verify(s => s.AddToComparison(userId, productId), Times.Once); + Assert.IsType(result); + } + + [Fact] + public async Task Remove_ValidProduct_RemovesProduct() + { + // Arrange + var userId = 1; + var productId = 1001; + var repositoryMock = new Mock>(); + repositoryMock.Setup(r => r.Query()).Returns(new[] + { + new ComparingProduct { UserId = userId, ProductId = productId } + }.AsQueryable()); + var comparingProductServiceMock = new Mock(); + var productPricingServiceMock = new Mock(); + var mediaServiceMock = new Mock(); + var contentLocalizationServiceMock = new Mock(); + var workContextMock = new Mock(); + var userManagerMock = new Mock>( + Mock.Of>(), null, null, null, null, null, null, null, null); + var controller = new ComparingProductController( + userManagerMock.Object, + repositoryMock.Object, + comparingProductServiceMock.Object, + productPricingServiceMock.Object, + mediaServiceMock.Object, + contentLocalizationServiceMock.Object, + workContextMock.Object + ); + var user = new User() + { + Id = userId, + UserName = "TestUser" + }; + workContextMock.Setup(repo => repo.GetCurrentUser()).ReturnsAsync(user); + + // Act + var result = await controller.Remove(productId); + + // Assert + repositoryMock.Verify(r => r.Remove(It.IsAny()), Times.Once); + repositoryMock.Verify(r => r.SaveChanges(), Times.Once); + Assert.IsType(result); + } + + [Fact] + public async Task Index_ReturnsValidViewModel() + { + // Arrange + var userId = 1; // Use a unique user id + var comparingProducts = new List() + { + new ComparingProduct + { + UserId = userId, + ProductId = 1001, + CreatedOn = DateTime.Now, + Product=new Product + { + AttributeValues={ new ProductAttributeValue() + { + AttributeId=1, + Attribute= new ProductAttribute(){Name="test1"} + }, + new ProductAttributeValue() + { + AttributeId=2, + Attribute= new ProductAttribute(){Name="test2"} + }, + new ProductAttributeValue() + { + AttributeId=3, + Attribute= new ProductAttribute(){Name="test3"} + },} + } + }, + new ComparingProduct + { + UserId = userId, + ProductId = 1002 , + CreatedOn = DateTime.Now, + Product=new Product + { + AttributeValues={ + new ProductAttributeValue() + { + AttributeId=1, + Attribute= new ProductAttribute(){Name="test1"} + }, + new ProductAttributeValue() + { + AttributeId=2, + Attribute= new ProductAttribute(){Name="test2"} + }, + new ProductAttributeValue() + { + AttributeId=3, + Attribute= new ProductAttribute(){Name="test3"} + }, + } + } + }, + }; + var repositoryMock = new Mock>(); + repositoryMock.Setup(r => r.Query()).Returns(comparingProducts.AsQueryable()); + var comparingProductServiceMock = new Mock(); + var productPricingServiceMock = new Mock(); + var mediaServiceMock = new Mock(); + var contentLocalizationServiceMock = new Mock(); + contentLocalizationServiceMock.Setup(s => s.GetLocalizedProperty(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((obj, propertyName, defaultValue) => defaultValue); + var workContextMock = new Mock(); + var userManagerMock = new Mock>( + Mock.Of>(), null, null, null, null, null, null, null, null); + workContextMock.Setup(w => w.GetCurrentUser()).ReturnsAsync(new User { Id = userId }); + var controller = new ComparingProductController( + userManagerMock.Object, + repositoryMock.Object, + comparingProductServiceMock.Object, + productPricingServiceMock.Object, + mediaServiceMock.Object, + contentLocalizationServiceMock.Object, + workContextMock.Object + ); + + // Act + var result = await controller.Index(); + + // Assert + var viewResult = Assert.IsType(result); + var viewModel = Assert.IsType(viewResult.Model); + Assert.Equal(comparingProducts.Count, viewModel.Products.Count); + Assert.NotEmpty(viewModel.Attributes); + } + + [Fact] + public async Task AddToComparison_TooManyComparingProducts_ReturnsErrorMessage() + { + // Arrange + var userId = 1; + var productId = 1001; + var model = new AddToComparisonModel { ProductId = productId }; + var repositoryMock = new Mock>(); + var comparingProductServiceMock = new Mock(); + comparingProductServiceMock.Setup(s => s.AddToComparison(userId, productId)) + .Throws(new TooManyComparingProductException(4)); + var productPricingServiceMock = new Mock(); + var mediaServiceMock = new Mock(); + var contentLocalizationServiceMock = new Mock(); + var workContextMock = new Mock(); + var userManagerMock = new Mock>( + Mock.Of>(), null, null, null, null, null, null, null, null); + var controller = new ComparingProductController( + userManagerMock.Object, + repositoryMock.Object, + comparingProductServiceMock.Object, + productPricingServiceMock.Object, + mediaServiceMock.Object, + contentLocalizationServiceMock.Object, + workContextMock.Object + ); + var user = new User() + { + Id = userId, + UserName = "TestUser" + }; + workContextMock.Setup(repo => repo.GetCurrentUser()).ReturnsAsync(user); + + // Act + var result = await controller.AddToComparison(model); + + // Assert + comparingProductServiceMock.Verify(s => s.AddToComparison(It.IsAny(), It.IsAny()), Times.Once); + var viewResult = Assert.IsType(result); + var viewModel = Assert.IsType(viewResult.Model); + Assert.Contains("Can not add to comparison items", viewModel.Message); + } + + [Fact] + public async Task Remove_InvalidProduct_ReturnsNotFound() + { + // Arrange + var userId = 1; + var productId = 1001; + var repositoryMock = new Mock>(); + repositoryMock.Setup(r => r.Query()).Returns(new[] + { + new ComparingProduct { UserId = userId, ProductId = 999 } + }.AsQueryable()); + var comparingProductServiceMock = new Mock(); + var productPricingServiceMock = new Mock(); + var mediaServiceMock = new Mock(); + var contentLocalizationServiceMock = new Mock(); + var workContextMock = new Mock(); + var userManagerMock = new Mock>( + Mock.Of>(), null, null, null, null, null, null, null, null); + var controller = new ComparingProductController( + userManagerMock.Object, + repositoryMock.Object, + comparingProductServiceMock.Object, + productPricingServiceMock.Object, + mediaServiceMock.Object, + contentLocalizationServiceMock.Object, + workContextMock.Object + ); + var user = new User() + { + Id = userId, + UserName = "TestUser" + }; + workContextMock.Setup(repo => repo.GetCurrentUser()).ReturnsAsync(user); + + // Act + var result = await controller.Remove(productId); + + // Assert + repositoryMock.Verify(r => r.Remove(It.IsAny()), Times.Never); + repositoryMock.Verify(r => r.SaveChanges(), Times.Never); + Assert.IsType(result); + } + } +} diff --git a/test/SimplCommerce.Module.ProductComparison.Tests/Services/ComparingProductServiceTests.cs b/test/SimplCommerce.Module.ProductComparison.Tests/Services/ComparingProductServiceTests.cs new file mode 100644 index 000000000..2a2adeb60 --- /dev/null +++ b/test/SimplCommerce.Module.ProductComparison.Tests/Services/ComparingProductServiceTests.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Moq; +using SimplCommerce.Infrastructure.Data; +using SimplCommerce.Module.Catalog.Models; +using SimplCommerce.Module.ProductComparison.Models; +using SimplCommerce.Module.ProductComparison.Services; +using Xunit; + +namespace SimplCommerce.Module.ProductComparison.Tests.Services +{ + public class ComparingProductServiceTests + { + [Fact] + public void AddToComparison_SuccessfullyAddsProduct() + { + // Arrange + var userId = 1; + var productId = 1001; + var repositoryMock = new Mock>(); + var service = new ComparingProductService(repositoryMock.Object); + + // Act + service.AddToComparison(userId, productId); + + // Assert + repositoryMock.Verify(r => r.Add(It.IsAny()), Times.Once); + repositoryMock.Verify(r => r.SaveChanges(), Times.Once); + } + + [Fact] + public void MigrateComparingProduct_SuccessfullyMigratesProducts() + { + // Arrange + var fromUserId = 1; + var toUserId = 2; + var repositoryMock = new Mock>(); + var comparingProducts = new List() + { + new ComparingProduct { UserId = fromUserId, ProductId = 1001 }, + new ComparingProduct { UserId = fromUserId, ProductId = 1002 }, + }; + repositoryMock.Setup(r => r.Query()).Returns(comparingProducts.AsQueryable()); + var service = new ComparingProductService(repositoryMock.Object); + + // Act + service.MigrateComparingProduct(fromUserId, toUserId); + + // Assert + repositoryMock.Verify(r => r.SaveChanges(), Times.Once); + Assert.All(comparingProducts, cp => Assert.Equal(toUserId, cp.UserId)); + } + + [Fact] + public void AddToComparison_TooManyComparingProducts_ThrowsException() + { + // Arrange + var userId = 1; + var productId = 1001; + var repositoryMock = new Mock>(); + var listComparingProducts = new List() + { + new ComparingProduct() + { + ProductId = 1001, + Product=new Product() + { + Name="TestProduct" + }, + CreatedOn = DateTime.Now, + UserId=1 + }, + new ComparingProduct() + { + ProductId = 1002, + Product=new Product() + { + Name="TestProduct1" + }, + CreatedOn = DateTime.Now, + UserId=1 + }, + new ComparingProduct() + { + ProductId = 1003, + Product=new Product() + { + Name="TestProduct2" + }, + CreatedOn = DateTime.Now, + UserId=1 + }, + new ComparingProduct() + { + ProductId = 1004, + Product=new Product() + { + Name="TestProduct3" + }, + CreatedOn = DateTime.Now, + UserId=1 + }, + }; + repositoryMock.Setup(r => r.Query()).Returns(listComparingProducts.AsQueryable); + var service = new ComparingProductService(repositoryMock.Object); + + // Act & Assert + Assert.Throws(() => service.AddToComparison(userId, productId)); + } + + [Fact] + public void AddToComparison_ProductAlreadyExists_DoesNotAddAgain() + { + // Arrange + var comparingProduct = new ComparingProduct() + { + ProductId = 1001, + Product = new Product() + { + Name = "TestProduct" + }, + CreatedOn = DateTime.Now, + UserId = 1 + }; + var userId = 1; + var productId = 1001; + var repositoryMock = new Mock>(); + repositoryMock.Setup(r => r.Query()).Returns(new List { comparingProduct }.AsQueryable); + var service = new ComparingProductService(repositoryMock.Object); + + // Act + service.AddToComparison(userId, productId); + + // Assert + repositoryMock.Verify(r => r.Add(comparingProduct), Times.Never); + repositoryMock.Verify(r => r.SaveChanges(), Times.Never); + } + } +} diff --git a/test/SimplCommerce.Module.ProductComparison.Tests/SimplCommerce.Module.ProductComparison.Tests.csproj b/test/SimplCommerce.Module.ProductComparison.Tests/SimplCommerce.Module.ProductComparison.Tests.csproj new file mode 100644 index 000000000..91821828c --- /dev/null +++ b/test/SimplCommerce.Module.ProductComparison.Tests/SimplCommerce.Module.ProductComparison.Tests.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + +