diff --git a/ShoppingAssistantApi.Api/Mutations/WishlistsMutation.cs b/ShoppingAssistantApi.Api/Mutations/WishlistsMutation.cs index c4dde4c..f3ff806 100644 --- a/ShoppingAssistantApi.Api/Mutations/WishlistsMutation.cs +++ b/ShoppingAssistantApi.Api/Mutations/WishlistsMutation.cs @@ -8,14 +8,18 @@ namespace ShoppingAssistantApi.Api.Mutations; public class WishlistsMutation { public Task StartPersonalWishlistAsync(WishlistCreateDto dto, CancellationToken cancellationToken, - [Service] IWishlistsService wishlistsService) + [Service] IWishlistsService wishlistsService) => wishlistsService.StartPersonalWishlistAsync(dto, cancellationToken); public Task AddMessageToPersonalWishlistAsync(string wishlistId, MessageCreateDto dto, CancellationToken cancellationToken, - [Service] IWishlistsService wishlistsService) + [Service] IWishlistsService wishlistsService) => wishlistsService.AddMessageToPersonalWishlistAsync(wishlistId, dto, cancellationToken); + public Task AddProductToPersonalWishlistAsync(string wishlistId, ProductCreateDto dto, CancellationToken cancellationToken, + [Service] IWishlistsService wishlistsService) + => wishlistsService.AddProductToPersonalWishlistAsync(wishlistId, dto, cancellationToken); + public Task DeletePersonalWishlistAsync(string wishlistId, CancellationToken cancellationToken, - [Service] IWishlistsService wishlistsService) + [Service] IWishlistsService wishlistsService) => wishlistsService.DeletePersonalWishlistAsync(wishlistId, cancellationToken); } diff --git a/ShoppingAssistantApi.Api/Queries/WishlistsQuery.cs b/ShoppingAssistantApi.Api/Queries/WishlistsQuery.cs index 086be2e..d3d36be 100644 --- a/ShoppingAssistantApi.Api/Queries/WishlistsQuery.cs +++ b/ShoppingAssistantApi.Api/Queries/WishlistsQuery.cs @@ -11,20 +11,20 @@ public class WishlistsQuery [Authorize] public Task> GetPersonalWishlistsPageAsync(int pageNumber, int pageSize, CancellationToken cancellationToken, [Service] IWishlistsService wishlistsService) - => wishlistsService.GetPersonalWishlistsPageAsync(pageNumber, pageSize, cancellationToken); + => wishlistsService.GetPersonalWishlistsPageAsync(pageNumber, pageSize, cancellationToken); [Authorize] public Task GetPersonalWishlistAsync(string wishlistId, CancellationToken cancellationToken, [Service] IWishlistsService wishlistsService) - => wishlistsService.GetPersonalWishlistAsync(wishlistId, cancellationToken); + => wishlistsService.GetPersonalWishlistAsync(wishlistId, cancellationToken); [Authorize] public Task> GetMessagesPageFromPersonalWishlistAsync(string wishlistId, int pageNumber, int pageSize, CancellationToken cancellationToken, [Service] IWishlistsService wishlistsService) - => wishlistsService.GetMessagesPageFromPersonalWishlistAsync(wishlistId, pageNumber, pageSize, cancellationToken); + => wishlistsService.GetMessagesPageFromPersonalWishlistAsync(wishlistId, pageNumber, pageSize, cancellationToken); [Authorize] public Task> GetProductsPageFromPersonalWishlistAsync(string wishlistId, int pageNumber, int pageSize, CancellationToken cancellationToken, [Service] IWishlistsService wishlistsService) - => wishlistsService.GetProductsPageFromPersonalWishlistAsync(wishlistId, pageNumber, pageSize, cancellationToken); + => wishlistsService.GetProductsPageFromPersonalWishlistAsync(wishlistId, pageNumber, pageSize, cancellationToken); } diff --git a/ShoppingAssistantApi.Application/IServices/IWishlistService.cs b/ShoppingAssistantApi.Application/IServices/IWishlistService.cs index b34e985..d95a874 100644 --- a/ShoppingAssistantApi.Application/IServices/IWishlistService.cs +++ b/ShoppingAssistantApi.Application/IServices/IWishlistService.cs @@ -16,6 +16,8 @@ public interface IWishlistsService Task> GetMessagesPageFromPersonalWishlistAsync(string wishlistId, int pageNumber, int pageSize, CancellationToken cancellationToken); + Task AddProductToPersonalWishlistAsync(string wishlistId, ProductCreateDto dto, CancellationToken cancellationToken); + Task> GetProductsPageFromPersonalWishlistAsync(string wishlistId, int pageNumber, int pageSize, CancellationToken cancellationToken); Task DeletePersonalWishlistAsync(string wishlistId, CancellationToken cancellationToken); diff --git a/ShoppingAssistantApi.Application/Models/CreateDtos/ProductCreateDto.cs b/ShoppingAssistantApi.Application/Models/CreateDtos/ProductCreateDto.cs index 56687e1..015706c 100644 --- a/ShoppingAssistantApi.Application/Models/CreateDtos/ProductCreateDto.cs +++ b/ShoppingAssistantApi.Application/Models/CreateDtos/ProductCreateDto.cs @@ -13,6 +13,4 @@ public class ProductCreateDto public required string[] ImagesUrls { get; set; } public required bool WasOpened { get; set; } - - public required string WishlistId { get; set; } } diff --git a/ShoppingAssistantApi.Infrastructure/Services/WishlistsService.cs b/ShoppingAssistantApi.Infrastructure/Services/WishlistsService.cs index 1a91f55..5dd2ae7 100644 --- a/ShoppingAssistantApi.Infrastructure/Services/WishlistsService.cs +++ b/ShoppingAssistantApi.Infrastructure/Services/WishlistsService.cs @@ -18,7 +18,7 @@ public class WishlistsService : IWishlistsService private readonly IMessagesRepository _messagesRepository; - private readonly IProductsRepository _productRepository; + private readonly IProductsRepository _productsRepository; private readonly IMapper _mapper; @@ -26,7 +26,7 @@ public class WishlistsService : IWishlistsService { _wishlistsRepository = wishlistRepository; _messagesRepository = messageRepository; - _productRepository = productRepository; + _productsRepository = productRepository; _mapper = mapper; } @@ -116,6 +116,26 @@ public class WishlistsService : IWishlistsService return new PagedList(dtos, pageNumber, pageSize, count); } + public async Task AddProductToPersonalWishlistAsync(string wishlistId, ProductCreateDto dto, CancellationToken cancellationToken) + { + var newProduct = _mapper.Map(dto); + + if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) + { + throw new InvalidDataException("Provided id is invalid."); + } + + await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); + + newProduct.CreatedById = (ObjectId) GlobalUser.Id; + newProduct.CreatedDateUtc = DateTime.UtcNow; + newProduct.WishlistId = wishlistObjectId; + + var createdProduct = await _productsRepository.AddAsync(newProduct, cancellationToken); + + return _mapper.Map(createdProduct); + } + public async Task> GetProductsPageFromPersonalWishlistAsync(string wishlistId, int pageNumber, int pageSize, CancellationToken cancellationToken) { if (!ObjectId.TryParse(wishlistId, out var wishlistObjectId)) @@ -125,15 +145,10 @@ public class WishlistsService : IWishlistsService await TryGetPersonalWishlist(wishlistObjectId, cancellationToken); - var entities = await _productRepository.GetPageAsync(pageNumber, pageSize, x => x.WishlistId == wishlistObjectId, cancellationToken); - - foreach (var e in entities) - { - Console.WriteLine(e.Name); - } + var entities = await _productsRepository.GetPageAsync(pageNumber, pageSize, x => x.WishlistId == wishlistObjectId, cancellationToken); var dtos = _mapper.Map>(entities); - var count = await _productRepository.GetCountAsync(x => x.WishlistId == wishlistObjectId, cancellationToken); + var count = await _productsRepository.GetCountAsync(x => x.WishlistId == wishlistObjectId, cancellationToken); return new PagedList(dtos, pageNumber, pageSize, count); } diff --git a/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs b/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs index 6f22fe7..eab15fa 100644 --- a/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs +++ b/ShoppingAssistantApi.Tests/Tests/WishlistsTests.cs @@ -221,6 +221,51 @@ public class WishlistsTests : IClassFixture> Assert.Equal(user.Id, (string) firstMessageInPage.createdById); } + [Fact] + public async Task AddProductToPersonalWishlist_ValidMessageModel_ReturnsNewProductModel() + { + var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); + var user = await UserExtention.GetCurrentUser(_httpClient); + + var mutation = new + { + query = "mutation addProductToPersonalWishlist($wishlistId: String!, $dto: ProductCreateDtoInput!) { addProductToPersonalWishlist (wishlistId: $wishlistId, dto: $dto) { url, name, description, rating, imagesUrls, wasOpened } }", + variables = new + { + wishlistId = WISHLIST_TESTING_VALID_WISHLIST_ID, + dto = new + { + url = "https://www.amazon.com/url", + name = "Generic name", + description = "Generic description", + rating = 4.8, + imagesUrls = new string[] + { + "https://www.amazon.com/image-url-1", + "https://www.amazon.com/image-url-2" + }, + wasOpened = false + } + } + }; + + var jsonPayload = JsonConvert.SerializeObject(mutation); + var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + + using var response = await _httpClient.PostAsync("graphql", content); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var responseString = await response.Content.ReadAsStringAsync(); + var document = JsonConvert.DeserializeObject(responseString); + + Assert.Equal("https://www.amazon.com/url", (string) document.data.addProductToPersonalWishlist.url); + Assert.Equal("Generic name", (string) document.data.addProductToPersonalWishlist.name); + Assert.Equal("Generic description", (string) document.data.addProductToPersonalWishlist.description); + Assert.Equal(4.8, (double) document.data.addProductToPersonalWishlist.rating); + Assert.Equal("https://www.amazon.com/image-url-1", (string) document.data.addProductToPersonalWishlist.imagesUrls[0]); + } + [Fact] public async Task GetProductsPageFromPersonalWishlist_ValidPageNumberAndSizeValidWishlistIdOrAuthorizedAccess_ReturnsPage() { @@ -435,7 +480,7 @@ public class WishlistsTests : IClassFixture> } [Fact] - public async Task AddMessageToPersonalWishlist_InvalidMessageModel_ReturnsInternalServerError() + public async Task AddMessageToPersonalWishlist_InvalidWishlistId_ReturnsInternalServerError() { var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); @@ -463,6 +508,35 @@ public class WishlistsTests : IClassFixture> Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); } + [Fact] + public async Task AddMessageToPersonalWishlist_UnAuthorizedAccess_ReturnsInternalServerError() + { + var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); + var user = await UserExtention.GetCurrentUser(_httpClient); + + const string MESSAGE_TEXT = "Second Message"; + + var mutation = new + { + query = "mutation addMessageToPersonalWishlist($wishlistId: String!, $dto: MessageCreateDtoInput!) { addMessageToPersonalWishlist (wishlistId: $wishlistId, dto: $dto) { role, text, createdById } }", + variables = new + { + wishlistId = WISHLIST_TESTING_OTHER_USER_WISHLIST_ID, + dto = new + { + text = MESSAGE_TEXT, + } + } + }; + + var jsonPayload = JsonConvert.SerializeObject(mutation); + var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + + using var response = await _httpClient.PostAsync("graphql", content); + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + } + [Fact] public async Task GetMessagesPageFromPersonalWishlist_InValidPageNumber_ReturnsEmptyList() { @@ -587,6 +661,78 @@ public class WishlistsTests : IClassFixture> Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); } + [Fact] + public async Task AddProductToPersonalWishlist_InValidWishlistId_RturnsInternalServerError() + { + var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); + var user = await UserExtention.GetCurrentUser(_httpClient); + + var mutation = new + { + query = "mutation addProductToPersonalWishlist($wishlistId: String!, $dto: ProductCreateDtoInput!) { addProductToPersonalWishlist (wishlistId: $wishlistId, dto: $dto) { url, name, description, rating, imagesUrls, wasOpened } }", + variables = new + { + wishlistId = WISHLIST_TESTING_INVALID_WISHLIST_ID, + dto = new + { + url = "https://www.amazon.com/url", + name = "Generic name", + description = "Generic description", + rating = 4.8, + imagesUrls = new string[] + { + "https://www.amazon.com/image-url-1", + "https://www.amazon.com/image-url-2" + }, + wasOpened = false + } + } + }; + + var jsonPayload = JsonConvert.SerializeObject(mutation); + var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + + using var response = await _httpClient.PostAsync("graphql", content); + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + } + + [Fact] + public async Task AddProductToPersonalWishlist_UnAuthorizedAccess_RturnsInternalServerError() + { + var tokensModel = await AccessExtention.Login(WISHLIST_TESTING_USER_EMAIL, WISHLIST_TESTING_USER_PASSWORD, _httpClient); + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokensModel.AccessToken); + var user = await UserExtention.GetCurrentUser(_httpClient); + + var mutation = new + { + query = "mutation addProductToPersonalWishlist($wishlistId: String!, $dto: ProductCreateDtoInput!) { addProductToPersonalWishlist (wishlistId: $wishlistId, dto: $dto) { url, name, description, rating, imagesUrls, wasOpened } }", + variables = new + { + wishlistId = WISHLIST_TESTING_OTHER_USER_WISHLIST_ID, + dto = new + { + url = "https://www.amazon.com/url", + name = "Generic name", + description = "Generic description", + rating = 4.8, + imagesUrls = new string[] + { + "https://www.amazon.com/image-url-1", + "https://www.amazon.com/image-url-2" + }, + wasOpened = false + } + } + }; + + var jsonPayload = JsonConvert.SerializeObject(mutation); + var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + + using var response = await _httpClient.PostAsync("graphql", content); + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + } + [Fact] public async Task GetProductsPageFromPersonalWishlist_InValidPageNumber_ReturnsInternalServerError() {