From 7b2e8d1645fb44a6753faa8dca0a2eb35f3e304e Mon Sep 17 00:00:00 2001 From: stasex Date: Thu, 19 Oct 2023 15:58:05 +0300 Subject: [PATCH] added new tests for product search, namely for checking recommendations and creating a wishlist --- .../IServices/IProductService.cs | 2 + .../Tests/ProductTests.cs | 102 +++++++++++++++--- 2 files changed, 89 insertions(+), 15 deletions(-) diff --git a/ShoppingAssistantApi.Application/IServices/IProductService.cs b/ShoppingAssistantApi.Application/IServices/IProductService.cs index 6be1f0d..89ce557 100644 --- a/ShoppingAssistantApi.Application/IServices/IProductService.cs +++ b/ShoppingAssistantApi.Application/IServices/IProductService.cs @@ -9,4 +9,6 @@ public interface IProductService Task> StartNewSearchAndReturnWishlist(Message message, CancellationToken cancellationToken); Task> GetProductFromSearch(Message message, CancellationToken cancellationToken); + + Task> GetRecommendationsForProductFromSearch(Message message, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/ShoppingAssistantApi.Tests/Tests/ProductTests.cs b/ShoppingAssistantApi.Tests/Tests/ProductTests.cs index d5b786c..458169a 100644 --- a/ShoppingAssistantApi.Tests/Tests/ProductTests.cs +++ b/ShoppingAssistantApi.Tests/Tests/ProductTests.cs @@ -1,16 +1,12 @@ -using System.Collections.ObjectModel; -using Microsoft.VisualBasic; -using MongoDB.Bson; +using MongoDB.Bson; using Moq; -using Newtonsoft.Json; -using ShoppingAssistantApi.Application.Models.Dtos; +using Newtonsoft.Json.Linq; using ShoppingAssistantApi.Application.IServices; using ShoppingAssistantApi.Application.Models.OpenAi; using ShoppingAssistantApi.Application.Models.ProductSearch; using ShoppingAssistantApi.Domain.Entities; using ShoppingAssistantApi.Domain.Enums; using ShoppingAssistantApi.Tests.TestExtentions; -using ShoppingAssistantApi.Infrastructure.Services; namespace ShoppingAssistantApi.Tests.Tests; @@ -26,6 +22,54 @@ public class ProductTests : TestsBase _productServiceMock = new Mock(); } + [Fact] + public async Task StartNewSearchAndReturnWishlist_CreatesWishlistObject() + { + var message = new Message + { + Id = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"), + Text = "what are the best graphics cards you know?", + CreatedById = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"), + Role = "user" + }; + var cancellationToken = CancellationToken.None; + + var expectedProductList = new List { "NVIDIA GeForce RTX 3080", "AMD Radeon RX 6900 XT" }; + _productServiceMock.Setup(x => x.GetProductFromSearch(message, cancellationToken)) + .ReturnsAsync(expectedProductList); + + Wishlist createdWishList = null; + var expectedOpenAiMessage = new OpenAiMessage + { + Role = OpenAiRole.User, + Content = "{ \"Name\": [{ \"Name\": \"NVIDIA GeForce RTX 3080\" }, { \"Name\": \"AMD Radeon RX 6900 XT\" }] }" + }; + _openAiServiceMock.Setup(x => x.GetChatCompletion(It.IsAny(), cancellationToken)) + .ReturnsAsync(expectedOpenAiMessage); + _productServiceMock + .Setup(x => x.StartNewSearchAndReturnWishlist(It.IsAny(), cancellationToken)) + .ReturnsAsync(() => + { + createdWishList = new Wishlist + { + Name = "Test Wishlist", + CreatedById = ObjectId.GenerateNewId(), + Id = ObjectId.GenerateNewId(), + Type = "Test Type" + }; + return new List(); + }); + + await _productServiceMock.Object.StartNewSearchAndReturnWishlist(message, cancellationToken); + + var openAiContent = JObject.Parse(expectedOpenAiMessage.Content); + var productNames = openAiContent["Name"].ToObject>(); + var productList = productNames.Select(info => info.Name).ToList(); + + Assert.Equal(expectedProductList, productList); + Assert.True(openAiContent.ContainsKey("Name")); + Assert.NotNull(createdWishList); + } [Fact] public async Task GetProductFromSearch_ReturnsProductList() @@ -38,24 +82,52 @@ public class ProductTests : TestsBase Role = "user" }; var cancellationToken = CancellationToken.None; - - var productServiceMock = new Mock(); + var expectedProductList = new List { "NVIDIA GeForce RTX 3080", "AMD Radeon RX 6900 XT" }; - productServiceMock.Setup(x => x.GetProductFromSearch(message, cancellationToken)) + _productServiceMock.Setup(x => x.GetProductFromSearch(message, cancellationToken)) .ReturnsAsync(expectedProductList); - - var openAiServiceMock = new Mock(); + var expectedOpenAiMessage = new OpenAiMessage { Role = OpenAiRole.User, - Content = "[\n { \"Name\": \"NVIDIA GeForce RTX 3080\" },\n { \"Name\": \"AMD Radeon RX 6900 XT\" }\n]" + Content = "{ \"Name\": [{ \"Name\": \"NVIDIA GeForce RTX 3080\" }, { \"Name\": \"AMD Radeon RX 6900 XT\" }] }" }; - openAiServiceMock.Setup(x => x.GetChatCompletion(It.IsAny(), cancellationToken)) + _openAiServiceMock.Setup(x => x.GetChatCompletion(It.IsAny(), cancellationToken)) .ReturnsAsync(expectedOpenAiMessage); - var productList = JsonConvert.DeserializeObject>(expectedOpenAiMessage.Content).Select(info => info.Name).ToList(); - + var openAiContent = JObject.Parse(expectedOpenAiMessage.Content); + var productNames = openAiContent["Name"].ToObject>(); + var productList = productNames.Select(info => info.Name).ToList(); + Assert.Equal(expectedProductList, productList); + Assert.True(openAiContent.ContainsKey("Name")); } + [Fact] + public async Task GetRecommendationsForProductFromSearch_ReturnsRecommendations() + { + var message = new Message + { + Id = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"), + Text = "get recommendations for this product", + CreatedById = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"), + Role = "user" + }; + var cancellationToken = CancellationToken.None; + + var expectedOpenAiMessage = new OpenAiMessage + { + Role = OpenAiRole.User, + Content = "{ \"Recommendation\": [\"Recommendation 1\", \"Recommendation 2\"] }" + }; + _openAiServiceMock.Setup(x => x.GetChatCompletion(It.IsAny(), cancellationToken)) + .ReturnsAsync(expectedOpenAiMessage); + + var recommendations = await _productServiceMock.Object.GetRecommendationsForProductFromSearch(message, cancellationToken); + + var openAiContent = JObject.Parse(expectedOpenAiMessage.Content); + Assert.NotNull(openAiContent); + Assert.True(openAiContent.ContainsKey("Recommendation")); + + } } \ No newline at end of file