mirror of
https://github.com/Shchoholiev/shopping-assistant-api.git
synced 2025-04-12 01:48:49 +00:00
Added models for product search.
This commit is contained in:
parent
9db3baca89
commit
fcc5f02c48
@ -1,6 +1,5 @@
|
|||||||
using System.Collections.ObjectModel;
|
using ShoppingAssistantApi.Application.Models.CreateDtos;
|
||||||
using ShoppingAssistantApi.Application.Models.Dtos;
|
using ShoppingAssistantApi.Application.Models.Dtos;
|
||||||
using ShoppingAssistantApi.Application.Models.OpenAi;
|
|
||||||
using ShoppingAssistantApi.Application.Models.ProductSearch;
|
using ShoppingAssistantApi.Application.Models.ProductSearch;
|
||||||
using ShoppingAssistantApi.Domain.Entities;
|
using ShoppingAssistantApi.Domain.Entities;
|
||||||
|
|
||||||
@ -10,6 +9,8 @@ public interface IProductService
|
|||||||
{
|
{
|
||||||
IAsyncEnumerable<(List<ProductName> ProductNames, WishlistDto Wishlist)> StartNewSearchAndReturnWishlist(Message message, CancellationToken cancellationToken);
|
IAsyncEnumerable<(List<ProductName> ProductNames, WishlistDto Wishlist)> StartNewSearchAndReturnWishlist(Message message, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
IAsyncEnumerable<ServerSentEvent> SearchProductAsync(string wishlistId, MessageCreateDto message, CancellationToken cancellationToken);
|
||||||
|
|
||||||
IAsyncEnumerable<string> GetProductFromSearch(Message message, CancellationToken cancellationToken);
|
IAsyncEnumerable<string> GetProductFromSearch(Message message, CancellationToken cancellationToken);
|
||||||
|
|
||||||
IAsyncEnumerable<string> GetRecommendationsForProductFromSearchStream(Message message,
|
IAsyncEnumerable<string> GetRecommendationsForProductFromSearchStream(Message message,
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace ShoppingAssistantApi.Application.Models.ProductSearch;
|
||||||
|
|
||||||
|
public class MessagePart
|
||||||
|
{
|
||||||
|
public string Text { get; set; }
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
using ShoppingAssistantApi.Domain.Enums;
|
||||||
|
|
||||||
|
namespace ShoppingAssistantApi.Application.Models.ProductSearch;
|
||||||
|
|
||||||
|
public class ServerSentEvent
|
||||||
|
{
|
||||||
|
public SearchEventType Event { get; set; }
|
||||||
|
|
||||||
|
public string Data { get; set; }
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
namespace ShoppingAssistantApi.Application.Models.ProductSearch;
|
||||||
|
|
||||||
|
public class Suggestion
|
||||||
|
{
|
||||||
|
public string Text { get; set; }
|
||||||
|
}
|
24
ShoppingAssistantApi.Domain/Enums/SearchEventType.cs
Normal file
24
ShoppingAssistantApi.Domain/Enums/SearchEventType.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
namespace ShoppingAssistantApi.Domain.Enums;
|
||||||
|
|
||||||
|
public enum SearchEventType
|
||||||
|
{
|
||||||
|
Wishlist = 0,
|
||||||
|
Message = 1,
|
||||||
|
Suggestion = 2,
|
||||||
|
Product = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SearchEventTypeExtensions
|
||||||
|
{
|
||||||
|
public static string ToSseEventString(this SearchEventType eventType)
|
||||||
|
{
|
||||||
|
return eventType switch
|
||||||
|
{
|
||||||
|
SearchEventType.Wishlist => "wishlist",
|
||||||
|
SearchEventType.Message => "message",
|
||||||
|
SearchEventType.Suggestion => "suggestion",
|
||||||
|
SearchEventType.Product => "product",
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(eventType), eventType, null),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,13 @@ public class ProductService : IProductService
|
|||||||
_wishlistsService = wishlistsService;
|
_wishlistsService = wishlistsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerable<ServerSentEvent> SearchProductAsync(string wishlistId, MessageCreateDto message, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// get all messages from wishlist
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public async IAsyncEnumerable<(List<ProductName> ProductNames, WishlistDto Wishlist)> StartNewSearchAndReturnWishlist(Message message, CancellationToken cancellationToken)
|
public async IAsyncEnumerable<(List<ProductName> ProductNames, WishlistDto Wishlist)> StartNewSearchAndReturnWishlist(Message message, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
List<OpenAiMessage> messages = new List<OpenAiMessage>()
|
List<OpenAiMessage> messages = new List<OpenAiMessage>()
|
||||||
|
@ -17,20 +17,43 @@ public class ProductTests
|
|||||||
{
|
{
|
||||||
private Mock<IOpenAiService> _openAiServiceMock;
|
private Mock<IOpenAiService> _openAiServiceMock;
|
||||||
|
|
||||||
private Mock<IProductService> _productServiceMock;
|
private IProductService _productService;
|
||||||
|
|
||||||
public Mock<IWishlistsService> _wishListServiceMock;
|
public Mock<IWishlistsService> _wishListServiceMock;
|
||||||
|
|
||||||
public ProductTests()
|
public ProductTests()
|
||||||
{
|
{
|
||||||
_openAiServiceMock = new Mock<IOpenAiService>();
|
_openAiServiceMock = new Mock<IOpenAiService>();
|
||||||
_productServiceMock = new Mock<IProductService>();
|
|
||||||
_wishListServiceMock = new Mock<IWishlistsService>();
|
_wishListServiceMock = new Mock<IWishlistsService>();
|
||||||
|
_productService = new ProductService(_openAiServiceMock.Object, _wishListServiceMock.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task StartNewSearchAndReturnWishlist_CreatesWishlistObject()
|
public async Task StartNewSearchAndReturnWishlist_CreatesWishlistObject()
|
||||||
{
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedOpenAiMessage = new OpenAiMessage
|
||||||
|
{
|
||||||
|
Role = OpenAiRole.User,
|
||||||
|
Content = "{ \"Name\": [{ \"Name\": \"NVIDIA GeForce RTX 3080\" }, { \"Name\": \"AMD Radeon RX 6900 XT\" }] }"
|
||||||
|
};
|
||||||
|
|
||||||
|
_openAiServiceMock.Setup(x => x.GetChatCompletionStream(It.IsAny<ChatCompletionRequest>(), CancellationToken.None))
|
||||||
|
.Returns((ChatCompletionRequest request, CancellationToken token) =>
|
||||||
|
{
|
||||||
|
var asyncEnumerable = new List<string> { expectedOpenAiMessage.Content }.ToAsyncEnumerable();
|
||||||
|
return asyncEnumerable;
|
||||||
|
});
|
||||||
|
|
||||||
|
_wishListServiceMock.Setup(x => x.StartPersonalWishlistAsync(It.IsAny<WishlistCreateDto>(), CancellationToken.None))
|
||||||
|
.ReturnsAsync(new WishlistDto
|
||||||
|
{
|
||||||
|
Id = "someID",
|
||||||
|
Name = "MacBook",
|
||||||
|
Type = "Product", // Use enum
|
||||||
|
CreatedById = "someId"
|
||||||
|
});
|
||||||
|
|
||||||
var message = new Message
|
var message = new Message
|
||||||
{
|
{
|
||||||
Id = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"),
|
Id = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"),
|
||||||
@ -38,45 +61,20 @@ public class ProductTests
|
|||||||
CreatedById = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"),
|
CreatedById = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab"),
|
||||||
Role = "user"
|
Role = "user"
|
||||||
};
|
};
|
||||||
var cancellationToken = CancellationToken.None;
|
|
||||||
|
|
||||||
var expectedOpenAiMessage = new OpenAiMessage
|
|
||||||
{
|
|
||||||
Role = OpenAiRole.User,
|
|
||||||
Content = "{ \"Name\": [{ \"Name\": \"NVIDIA GeForce RTX 3080\" }, { \"Name\": \"AMD Radeon RX 6900 XT\" }] }"
|
|
||||||
};
|
|
||||||
|
|
||||||
_openAiServiceMock.Setup(x => x.GetChatCompletionStream(It.IsAny<ChatCompletionRequest>(), cancellationToken))
|
|
||||||
.Returns((ChatCompletionRequest request, CancellationToken token) =>
|
|
||||||
{
|
|
||||||
var asyncEnumerable = new List<string> { expectedOpenAiMessage.Content }.ToAsyncEnumerable();
|
|
||||||
return asyncEnumerable;
|
|
||||||
});
|
|
||||||
|
|
||||||
_wishListServiceMock.Setup(x => x.StartPersonalWishlistAsync(It.IsAny<WishlistCreateDto>(), cancellationToken))
|
|
||||||
.ReturnsAsync(new WishlistDto
|
|
||||||
{
|
|
||||||
Id = "someID",
|
|
||||||
Name = "MacBook",
|
|
||||||
Type = "Product",
|
|
||||||
CreatedById = "someId"
|
|
||||||
});
|
|
||||||
|
|
||||||
var productService = new ProductService(_openAiServiceMock.Object, _wishListServiceMock.Object);
|
|
||||||
|
|
||||||
List<ProductName> productNames = null;
|
List<ProductName> productNames = null;
|
||||||
WishlistDto createdWishList = null;
|
WishlistDto createdWishList = null;
|
||||||
|
|
||||||
var result = productService.StartNewSearchAndReturnWishlist(message, cancellationToken);
|
// Act
|
||||||
|
var result = _productService.StartNewSearchAndReturnWishlist(message, CancellationToken.None);
|
||||||
|
|
||||||
await foreach (var (productList, wishlist) in result)
|
await foreach (var (productList, wishlist) in result)
|
||||||
{
|
{
|
||||||
productNames = productList;
|
productNames = productList;
|
||||||
createdWishList = wishlist;
|
createdWishList = wishlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
var openAiContent = JObject.Parse(expectedOpenAiMessage.Content);
|
|
||||||
|
|
||||||
|
// Assert
|
||||||
Assert.NotNull(createdWishList);
|
Assert.NotNull(createdWishList);
|
||||||
Assert.NotNull(productNames);
|
Assert.NotNull(productNames);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user