Browse Source
* Initial update endpoint working * Updated CatalogItem to support more updates; added tests * Got MediatR domain events working to check for duplicate item names * Adding reference link * Remove domain events spike code * clean up usingsmain
committed by
GitHub
13 changed files with 205 additions and 7 deletions
@ -0,0 +1,14 @@ |
|||
using System; |
|||
|
|||
namespace Microsoft.eShopWeb.ApplicationCore.Exceptions |
|||
{ |
|||
public class DuplicateCatalogItemNameException : Exception |
|||
{ |
|||
public DuplicateCatalogItemNameException(string message, int duplicateItemId) : base(message) |
|||
{ |
|||
DuplicateItemId = duplicateItemId; |
|||
} |
|||
|
|||
public int DuplicateItemId { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints |
|||
{ |
|||
public class UpdateCatalogItemRequest : BaseRequest |
|||
{ |
|||
[Range(1, 10000)] |
|||
public int Id { get; set; } |
|||
[Range(1, 10000)] |
|||
public int CatalogBrandId { get; set; } |
|||
[Range(1, 10000)] |
|||
public int CatalogTypeId { get; set; } |
|||
[Required] |
|||
public string Description { get; set; } |
|||
[Required] |
|||
public string Name { get; set; } |
|||
public string PictureUri { get; set; } |
|||
[Range(0.01, 10000)] |
|||
public decimal Price { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
|
|||
namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints |
|||
{ |
|||
public class UpdateCatalogItemResponse : BaseResponse |
|||
{ |
|||
public UpdateCatalogItemResponse(Guid correlationId) : base(correlationId) |
|||
{ |
|||
} |
|||
|
|||
public UpdateCatalogItemResponse() |
|||
{ |
|||
} |
|||
|
|||
public CatalogItemDto CatalogItem { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
using Ardalis.ApiEndpoints; |
|||
using Microsoft.AspNetCore.Authentication.JwtBearer; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.eShopWeb.ApplicationCore.Constants; |
|||
using Microsoft.eShopWeb.ApplicationCore.Entities; |
|||
using Microsoft.eShopWeb.ApplicationCore.Exceptions; |
|||
using Microsoft.eShopWeb.ApplicationCore.Interfaces; |
|||
using Swashbuckle.AspNetCore.Annotations; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints |
|||
{ |
|||
[Authorize(Roles = AuthorizationConstants.Roles.ADMINISTRATORS, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] |
|||
public class Update : BaseAsyncEndpoint<UpdateCatalogItemRequest, UpdateCatalogItemResponse> |
|||
{ |
|||
private readonly IAsyncRepository<CatalogItem> _itemRepository; |
|||
|
|||
public Update(IAsyncRepository<CatalogItem> itemRepository) |
|||
{ |
|||
_itemRepository = itemRepository; |
|||
} |
|||
|
|||
[HttpPut("api/catalog-items")] |
|||
[SwaggerOperation( |
|||
Summary = "Updates a Catalog Item", |
|||
Description = "Updates a Catalog Item", |
|||
OperationId = "catalog-items.update", |
|||
Tags = new[] { "CatalogItemEndpoints" }) |
|||
] |
|||
public override async Task<ActionResult<UpdateCatalogItemResponse>> HandleAsync(UpdateCatalogItemRequest request) |
|||
{ |
|||
var response = new UpdateCatalogItemResponse(request.CorrelationId()); |
|||
|
|||
var existingItem = await _itemRepository.GetByIdAsync(request.Id); |
|||
|
|||
existingItem.UpdateDetails(request.Name, request.Description, request.Price); |
|||
existingItem.UpdateBrand(request.CatalogBrandId); |
|||
existingItem.UpdateType(request.CatalogTypeId); |
|||
|
|||
await _itemRepository.UpdateAsync(existingItem); |
|||
|
|||
var dto = new CatalogItemDto |
|||
{ |
|||
Id = existingItem.Id, |
|||
CatalogBrandId = existingItem.CatalogBrandId, |
|||
CatalogTypeId = existingItem.CatalogTypeId, |
|||
Description = existingItem.Description, |
|||
Name = existingItem.Name, |
|||
PictureUri = existingItem.PictureUri, |
|||
Price = existingItem.Price |
|||
}; |
|||
response.CatalogItem = dto; |
|||
return response; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
using Xunit; |
|||
using Microsoft.eShopWeb.ApplicationCore.Entities; |
|||
using System; |
|||
|
|||
namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Entities.CatalogItemTests |
|||
{ |
|||
public class UpdateDetails |
|||
{ |
|||
private CatalogItem _testItem; |
|||
private int _validTypeId = 1; |
|||
private int _validBrandId = 2; |
|||
private string _validDescription = "test description"; |
|||
private string _validName = "test name"; |
|||
private decimal _validPrice = 1.23m; |
|||
private string _validUri = "/123"; |
|||
|
|||
public UpdateDetails() |
|||
{ |
|||
_testItem = new CatalogItem(_validTypeId, _validBrandId, _validDescription, _validName, _validPrice, _validUri); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ThrowsArgumentExceptionGivenEmptyName() |
|||
{ |
|||
string newValue = ""; |
|||
Assert.Throws<ArgumentException>(() => _testItem.UpdateDetails(newValue, _validDescription, _validPrice)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ThrowsArgumentExceptionGivenEmptyDescription() |
|||
{ |
|||
string newValue = ""; |
|||
Assert.Throws<ArgumentException>(() => _testItem.UpdateDetails(_validName, newValue, _validPrice)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ThrowsArgumentNullExceptionGivenNullName() |
|||
{ |
|||
Assert.Throws<ArgumentNullException>(() => _testItem.UpdateDetails(null, _validDescription, _validPrice)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ThrowsArgumentNullExceptionGivenNullDescription() |
|||
{ |
|||
Assert.Throws<ArgumentNullException>(() => _testItem.UpdateDetails(_validName, null, _validPrice)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0)] |
|||
[InlineData(-1.23)] |
|||
public void ThrowsArgumentExceptionGivenNonPositivePrice(decimal newPrice) |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => _testItem.UpdateDetails(_validName, _validDescription, newPrice)); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue