diff --git a/src/ApplicationCore/ApplicationCore.csproj b/src/ApplicationCore/ApplicationCore.csproj
index 9a54122..2d2c5cd 100644
--- a/src/ApplicationCore/ApplicationCore.csproj
+++ b/src/ApplicationCore/ApplicationCore.csproj
@@ -3,10 +3,12 @@
net6.0
Microsoft.eShopWeb.ApplicationCore
+ enable
+
diff --git a/src/ApplicationCore/CatalogSettings.cs b/src/ApplicationCore/CatalogSettings.cs
index 5ea8bd2..bd5a0b6 100644
--- a/src/ApplicationCore/CatalogSettings.cs
+++ b/src/ApplicationCore/CatalogSettings.cs
@@ -2,5 +2,5 @@
public class CatalogSettings
{
- public string CatalogBaseUrl { get; set; }
+ public string? CatalogBaseUrl { get; set; }
}
diff --git a/src/ApplicationCore/Entities/BasketAggregate/Basket.cs b/src/ApplicationCore/Entities/BasketAggregate/Basket.cs
index 71ab4ee..c49bae4 100644
--- a/src/ApplicationCore/Entities/BasketAggregate/Basket.cs
+++ b/src/ApplicationCore/Entities/BasketAggregate/Basket.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
+using Ardalis.GuardClauses;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
namespace Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
@@ -25,7 +26,7 @@ public class Basket : BaseEntity, IAggregateRoot
_items.Add(new BasketItem(catalogItemId, quantity, unitPrice));
return;
}
- var existingItem = Items.FirstOrDefault(i => i.CatalogItemId == catalogItemId);
+ var existingItem = Items.First(i => i.CatalogItemId == catalogItemId);
existingItem.AddQuantity(quantity);
}
diff --git a/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs b/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs
index 72f7f1a..8a553f1 100644
--- a/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs
+++ b/src/ApplicationCore/Entities/BuyerAggregate/Buyer.cs
@@ -12,10 +12,8 @@ public class Buyer : BaseEntity, IAggregateRoot
public IEnumerable PaymentMethods => _paymentMethods.AsReadOnly();
- private Buyer()
- {
- // required by EF
- }
+ #pragma warning disable CS8618 // Required by Entity Framework
+ private Buyer() { }
public Buyer(string identity) : this()
{
diff --git a/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs b/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs
index f4d2e54..97ed93d 100644
--- a/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs
+++ b/src/ApplicationCore/Entities/BuyerAggregate/PaymentMethod.cs
@@ -2,7 +2,7 @@
public class PaymentMethod : BaseEntity
{
- public string Alias { get; private set; }
- public string CardId { get; private set; } // actual card data must be stored in a PCI compliant system, like Stripe
- public string Last4 { get; private set; }
+ public string? Alias { get; private set; }
+ public string? CardId { get; private set; } // actual card data must be stored in a PCI compliant system, like Stripe
+ public string? Last4 { get; private set; }
}
diff --git a/src/ApplicationCore/Entities/CatalogItem.cs b/src/ApplicationCore/Entities/CatalogItem.cs
index abf5a02..1b9534d 100644
--- a/src/ApplicationCore/Entities/CatalogItem.cs
+++ b/src/ApplicationCore/Entities/CatalogItem.cs
@@ -11,9 +11,9 @@ public class CatalogItem : BaseEntity, IAggregateRoot
public decimal Price { get; private set; }
public string PictureUri { get; private set; }
public int CatalogTypeId { get; private set; }
- public CatalogType CatalogType { get; private set; }
+ public CatalogType? CatalogType { get; private set; }
public int CatalogBrandId { get; private set; }
- public CatalogBrand CatalogBrand { get; private set; }
+ public CatalogBrand? CatalogBrand { get; private set; }
public CatalogItem(int catalogTypeId,
int catalogBrandId,
@@ -30,15 +30,15 @@ public class CatalogItem : BaseEntity, IAggregateRoot
PictureUri = pictureUri;
}
- public void UpdateDetails(string name, string description, decimal price)
+ public void UpdateDetails(CatalogItemDetails details)
{
- Guard.Against.NullOrEmpty(name, nameof(name));
- Guard.Against.NullOrEmpty(description, nameof(description));
- Guard.Against.NegativeOrZero(price, nameof(price));
+ Guard.Against.NullOrEmpty(details.Name, nameof(details.Name));
+ Guard.Against.NullOrEmpty(details.Description, nameof(details.Description));
+ Guard.Against.NegativeOrZero(details.Price, nameof(details.Price));
- Name = name;
- Description = description;
- Price = price;
+ Name = details.Name;
+ Description = details.Description;
+ Price = details.Price;
}
public void UpdateBrand(int catalogBrandId)
@@ -62,4 +62,18 @@ public class CatalogItem : BaseEntity, IAggregateRoot
}
PictureUri = $"images\\products\\{pictureName}?{new DateTime().Ticks}";
}
+
+ public readonly record struct CatalogItemDetails
+ {
+ public string? Name { get; }
+ public string? Description { get; }
+ public decimal Price { get; }
+
+ public CatalogItemDetails(string? name, string? description, decimal price)
+ {
+ Name = name;
+ Description = description;
+ Price = price;
+ }
+ }
}
diff --git a/src/ApplicationCore/Entities/OrderAggregate/Address.cs b/src/ApplicationCore/Entities/OrderAggregate/Address.cs
index 65bd261..8b651cd 100644
--- a/src/ApplicationCore/Entities/OrderAggregate/Address.cs
+++ b/src/ApplicationCore/Entities/OrderAggregate/Address.cs
@@ -12,6 +12,7 @@ public class Address // ValueObject
public string ZipCode { get; private set; }
+ #pragma warning disable CS8618 // Required by Entity Framework
private Address() { }
public Address(string street, string city, string state, string country, string zipcode)
diff --git a/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs b/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs
index 98cce22..59d1adb 100644
--- a/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs
+++ b/src/ApplicationCore/Entities/OrderAggregate/CatalogItemOrdered.cs
@@ -19,10 +19,8 @@ public class CatalogItemOrdered // ValueObject
PictureUri = pictureUri;
}
- private CatalogItemOrdered()
- {
- // required by EF
- }
+ #pragma warning disable CS8618 // Required by Entity Framework
+ private CatalogItemOrdered() {}
public int CatalogItemId { get; private set; }
public string ProductName { get; private set; }
diff --git a/src/ApplicationCore/Entities/OrderAggregate/Order.cs b/src/ApplicationCore/Entities/OrderAggregate/Order.cs
index 53c587e..ca9a86e 100644
--- a/src/ApplicationCore/Entities/OrderAggregate/Order.cs
+++ b/src/ApplicationCore/Entities/OrderAggregate/Order.cs
@@ -7,16 +7,12 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
public class Order : BaseEntity, IAggregateRoot
{
- private Order()
- {
- // required by EF
- }
+ #pragma warning disable CS8618 // Required by Entity Framework
+ private Order() {}
public Order(string buyerId, Address shipToAddress, List items)
{
Guard.Against.NullOrEmpty(buyerId, nameof(buyerId));
- Guard.Against.Null(shipToAddress, nameof(shipToAddress));
- Guard.Against.Null(items, nameof(items));
BuyerId = buyerId;
ShipToAddress = shipToAddress;
diff --git a/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs b/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs
index fec2582..43054d1 100644
--- a/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs
+++ b/src/ApplicationCore/Entities/OrderAggregate/OrderItem.cs
@@ -6,10 +6,8 @@ public class OrderItem : BaseEntity
public decimal UnitPrice { get; private set; }
public int Units { get; private set; }
- private OrderItem()
- {
- // required by EF
- }
+ #pragma warning disable CS8618 // Required by Entity Framework
+ private OrderItem() {}
public OrderItem(CatalogItemOrdered itemOrdered, decimal unitPrice, int units)
{
diff --git a/src/ApplicationCore/Extensions/GuardExtensions.cs b/src/ApplicationCore/Extensions/GuardExtensions.cs
index 06a781a..138602f 100644
--- a/src/ApplicationCore/Extensions/GuardExtensions.cs
+++ b/src/ApplicationCore/Extensions/GuardExtensions.cs
@@ -7,12 +7,6 @@ namespace Ardalis.GuardClauses;
public static class BasketGuards
{
- public static void NullBasket(this IGuardClause guardClause, int basketId, Basket basket)
- {
- if (basket == null)
- throw new BasketNotFoundException(basketId);
- }
-
public static void EmptyBasketOnCheckout(this IGuardClause guardClause, IReadOnlyCollection basketItems)
{
if (!basketItems.Any())
diff --git a/src/ApplicationCore/Extensions/JsonExtensions.cs b/src/ApplicationCore/Extensions/JsonExtensions.cs
index 1a2b8e0..622bcc9 100644
--- a/src/ApplicationCore/Extensions/JsonExtensions.cs
+++ b/src/ApplicationCore/Extensions/JsonExtensions.cs
@@ -9,7 +9,7 @@ public static class JsonExtensions
PropertyNameCaseInsensitive = true
};
- public static T FromJson(this string json) =>
+ public static T? FromJson(this string json) =>
JsonSerializer.Deserialize(json, _jsonOptions);
public static string ToJson(this T obj) =>
diff --git a/src/ApplicationCore/Interfaces/IBasketService.cs b/src/ApplicationCore/Interfaces/IBasketService.cs
index 4dbdf9f..204f5f1 100644
--- a/src/ApplicationCore/Interfaces/IBasketService.cs
+++ b/src/ApplicationCore/Interfaces/IBasketService.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Ardalis.Result;
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces;
@@ -8,6 +9,6 @@ public interface IBasketService
{
Task TransferBasketAsync(string anonymousId, string userName);
Task AddItemToBasket(string username, int catalogItemId, decimal price, int quantity = 1);
- Task SetQuantities(int basketId, Dictionary quantities);
+ Task> SetQuantities(int basketId, Dictionary quantities);
Task DeleteBasketAsync(int basketId);
}
diff --git a/src/ApplicationCore/Services/BasketService.cs b/src/ApplicationCore/Services/BasketService.cs
index 167c1cb..ec810f3 100644
--- a/src/ApplicationCore/Services/BasketService.cs
+++ b/src/ApplicationCore/Services/BasketService.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Ardalis.GuardClauses;
+using Ardalis.Result;
using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.ApplicationCore.Specifications;
@@ -22,7 +23,7 @@ public class BasketService : IBasketService
public async Task AddItemToBasket(string username, int catalogItemId, decimal price, int quantity = 1)
{
var basketSpec = new BasketWithItemsSpecification(username);
- var basket = await _basketRepository.GetBySpecAsync(basketSpec);
+ var basket = await _basketRepository.FirstOrDefaultAsync(basketSpec);
if (basket == null)
{
@@ -39,15 +40,15 @@ public class BasketService : IBasketService
public async Task DeleteBasketAsync(int basketId)
{
var basket = await _basketRepository.GetByIdAsync(basketId);
+ Guard.Against.Null(basket, nameof(basket));
await _basketRepository.DeleteAsync(basket);
}
- public async Task SetQuantities(int basketId, Dictionary quantities)
+ public async Task> SetQuantities(int basketId, Dictionary quantities)
{
- Guard.Against.Null(quantities, nameof(quantities));
var basketSpec = new BasketWithItemsSpecification(basketId);
- var basket = await _basketRepository.GetBySpecAsync(basketSpec);
- Guard.Against.NullBasket(basketId, basket);
+ var basket = await _basketRepository.FirstOrDefaultAsync(basketSpec);
+ if (basket == null) return Result.NotFound();
foreach (var item in basket.Items)
{
@@ -64,13 +65,11 @@ public class BasketService : IBasketService
public async Task TransferBasketAsync(string anonymousId, string userName)
{
- Guard.Against.NullOrEmpty(anonymousId, nameof(anonymousId));
- Guard.Against.NullOrEmpty(userName, nameof(userName));
var anonymousBasketSpec = new BasketWithItemsSpecification(anonymousId);
- var anonymousBasket = await _basketRepository.GetBySpecAsync(anonymousBasketSpec);
+ var anonymousBasket = await _basketRepository.FirstOrDefaultAsync(anonymousBasketSpec);
if (anonymousBasket == null) return;
var userBasketSpec = new BasketWithItemsSpecification(userName);
- var userBasket = await _basketRepository.GetBySpecAsync(userBasketSpec);
+ var userBasket = await _basketRepository.FirstOrDefaultAsync(userBasketSpec);
if (userBasket == null)
{
userBasket = new Basket(userName);
diff --git a/src/ApplicationCore/Services/OrderService.cs b/src/ApplicationCore/Services/OrderService.cs
index 1f38523..3bc88f1 100644
--- a/src/ApplicationCore/Services/OrderService.cs
+++ b/src/ApplicationCore/Services/OrderService.cs
@@ -30,9 +30,9 @@ public class OrderService : IOrderService
public async Task CreateOrderAsync(int basketId, Address shippingAddress)
{
var basketSpec = new BasketWithItemsSpecification(basketId);
- var basket = await _basketRepository.GetBySpecAsync(basketSpec);
+ var basket = await _basketRepository.FirstOrDefaultAsync(basketSpec);
- Guard.Against.NullBasket(basketId, basket);
+ Guard.Against.Null(basket, nameof(basket));
Guard.Against.EmptyBasketOnCheckout(basket.Items);
var catalogItemsSpecification = new CatalogItemsSpecification(basket.Items.Select(item => item.CatalogItemId).ToArray());
diff --git a/src/Infrastructure/Data/CatalogContext.cs b/src/Infrastructure/Data/CatalogContext.cs
index f9f340a..fc2e4b6 100644
--- a/src/Infrastructure/Data/CatalogContext.cs
+++ b/src/Infrastructure/Data/CatalogContext.cs
@@ -8,9 +8,8 @@ namespace Microsoft.eShopWeb.Infrastructure.Data;
public class CatalogContext : DbContext
{
- public CatalogContext(DbContextOptions options) : base(options)
- {
- }
+ #pragma warning disable CS8618 // Required by Entity Framework
+ public CatalogContext(DbContextOptions options) : base(options) {}
public DbSet Baskets { get; set; }
public DbSet CatalogItems { get; set; }
diff --git a/src/Infrastructure/Data/Config/BasketConfiguration.cs b/src/Infrastructure/Data/Config/BasketConfiguration.cs
index d66fcf4..96c3e07 100644
--- a/src/Infrastructure/Data/Config/BasketConfiguration.cs
+++ b/src/Infrastructure/Data/Config/BasketConfiguration.cs
@@ -9,7 +9,7 @@ public class BasketConfiguration : IEntityTypeConfiguration
public void Configure(EntityTypeBuilder builder)
{
var navigation = builder.Metadata.FindNavigation(nameof(Basket.Items));
- navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
+ navigation?.SetPropertyAccessMode(PropertyAccessMode.Field);
builder.Property(b => b.BuyerId)
.IsRequired()
diff --git a/src/Infrastructure/Data/Config/OrderConfiguration.cs b/src/Infrastructure/Data/Config/OrderConfiguration.cs
index 3b5a8c3..b169237 100644
--- a/src/Infrastructure/Data/Config/OrderConfiguration.cs
+++ b/src/Infrastructure/Data/Config/OrderConfiguration.cs
@@ -10,7 +10,7 @@ public class OrderConfiguration : IEntityTypeConfiguration
{
var navigation = builder.Metadata.FindNavigation(nameof(Order.OrderItems));
- navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
+ navigation?.SetPropertyAccessMode(PropertyAccessMode.Field);
builder.Property(b => b.BuyerId)
.IsRequired()
diff --git a/src/Infrastructure/Data/FileItem.cs b/src/Infrastructure/Data/FileItem.cs
index 0229b88..329c041 100644
--- a/src/Infrastructure/Data/FileItem.cs
+++ b/src/Infrastructure/Data/FileItem.cs
@@ -2,10 +2,10 @@
public class FileItem
{
- public string FileName { get; set; }
- public string Url { get; set; }
+ public string? FileName { get; set; }
+ public string? Url { get; set; }
public long Size { get; set; }
- public string Ext { get; set; }
- public string Type { get; set; }
- public string DataBase64 { get; set; }
+ public string? Ext { get; set; }
+ public string? Type { get; set; }
+ public string? DataBase64 { get; set; }
}
diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj
index 4672210..a0be8bb 100644
--- a/src/Infrastructure/Infrastructure.csproj
+++ b/src/Infrastructure/Infrastructure.csproj
@@ -3,6 +3,7 @@
net6.0
Microsoft.eShopWeb.Infrastructure
+ enable
diff --git a/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs
index 7bc715b..2ce0e6c 100644
--- a/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs
+++ b/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs
@@ -41,8 +41,9 @@ public class UpdateCatalogItemEndpoint : IEndpoint5b662463-1efd-4bae-bde4-befe0be3e8ff
Linux
..\..
+ enable
diff --git a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs
index 87f7962..fdf4b1f 100644
--- a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs
+++ b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs
@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
+using Ardalis.GuardClauses;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
@@ -73,17 +74,17 @@ public class LoginModel : PageModel
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
//var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
- var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, false, true);
+ var result = await _signInManager.PasswordSignInAsync(Input?.Email, Input?.Password, false, true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
- await TransferAnonymousBasketToUserAsync(Input.Email);
+ await TransferAnonymousBasketToUserAsync(Input?.Email);
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
- return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
+ return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input?.RememberMe });
}
if (result.IsLockedOut)
{
@@ -108,6 +109,7 @@ public class LoginModel : PageModel
var anonymousId = Request.Cookies[Constants.BASKET_COOKIENAME];
if (Guid.TryParse(anonymousId, out var _))
{
+ Guard.Against.NullOrEmpty(userName, nameof(userName));
await _basketService.TransferBasketAsync(anonymousId, userName);
}
Response.Cookies.Delete(Constants.BASKET_COOKIENAME);
diff --git a/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs b/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs
index 5991039..ce66e9e 100644
--- a/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs
+++ b/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
+using Ardalis.GuardClauses;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
@@ -67,8 +68,8 @@ public class RegisterModel : PageModel
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
- var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email };
- var result = await _userManager.CreateAsync(user, Input.Password);
+ var user = new ApplicationUser { UserName = Input?.Email, Email = Input?.Email };
+ var result = await _userManager.CreateAsync(user, Input?.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
@@ -80,7 +81,8 @@ public class RegisterModel : PageModel
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
- await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
+ Guard.Against.Null(callbackUrl, nameof(callbackUrl));
+ await _emailSender.SendEmailAsync(Input?.Email, "Confirm your email",
$"Please confirm your account by clicking here.");
await _signInManager.SignInAsync(user, isPersistent: false);
diff --git a/src/Web/Configuration/RevokeAuthenticationEvents.cs b/src/Web/Configuration/RevokeAuthenticationEvents.cs
index 0e29163..09ba74a 100644
--- a/src/Web/Configuration/RevokeAuthenticationEvents.cs
+++ b/src/Web/Configuration/RevokeAuthenticationEvents.cs
@@ -22,12 +22,12 @@ public class RevokeAuthenticationEvents : CookieAuthenticationEvents
public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
- var userId = context.Principal.Claims.First(c => c.Type == ClaimTypes.Name);
+ var userId = context.Principal?.Claims.First(c => c.Type == ClaimTypes.Name);
var identityKey = context.Request.Cookies[ConfigureCookieSettings.IdentifierCookieName];
- if (_cache.TryGetValue($"{userId.Value}:{identityKey}", out var revokeKeys))
+ if (_cache.TryGetValue($"{userId?.Value}:{identityKey}", out var revokeKeys))
{
- _logger.LogDebug($"Access has been revoked for: {userId.Value}.");
+ _logger.LogDebug($"Access has been revoked for: {userId?.Value}.");
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
diff --git a/src/Web/Controllers/ManageController.cs b/src/Web/Controllers/ManageController.cs
index 8bf6d28..779fa36 100644
--- a/src/Web/Controllers/ManageController.cs
+++ b/src/Web/Controllers/ManageController.cs
@@ -1,5 +1,6 @@
using System.Text;
using System.Text.Encodings.Web;
+using Ardalis.GuardClauses;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
@@ -119,6 +120,7 @@ public class ManageController : Controller
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
+ Guard.Against.Null(callbackUrl, nameof(callbackUrl));
var email = user.Email;
await _emailSender.SendEmailConfirmationAsync(email, callbackUrl);
@@ -405,7 +407,7 @@ public class ManageController : Controller
}
// Strip spaces and hypens
- var verificationCode = model.Code.Replace(" ", string.Empty).Replace("-", string.Empty);
+ var verificationCode = model.Code?.Replace(" ", string.Empty).Replace("-", string.Empty);
var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync(
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);
diff --git a/src/Web/Controllers/OrderController.cs b/src/Web/Controllers/OrderController.cs
index f8e4093..5a2e1e1 100644
--- a/src/Web/Controllers/OrderController.cs
+++ b/src/Web/Controllers/OrderController.cs
@@ -1,4 +1,5 @@
-using MediatR;
+using Ardalis.GuardClauses;
+using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopWeb.Web.Features.MyOrders;
@@ -20,7 +21,8 @@ public class OrderController : Controller
[HttpGet]
public async Task MyOrders()
- {
+ {
+ Guard.Against.Null(User?.Identity?.Name, nameof(User.Identity.Name));
var viewModel = await _mediator.Send(new GetMyOrders(User.Identity.Name));
return View(viewModel);
@@ -29,6 +31,7 @@ public class OrderController : Controller
[HttpGet("{orderId}")]
public async Task Detail(int orderId)
{
+ Guard.Against.Null(User?.Identity?.Name, nameof(User.Identity.Name));
var viewModel = await _mediator.Send(new GetOrderDetails(User.Identity.Name, orderId));
if (viewModel == null)
diff --git a/src/Web/Controllers/UserController.cs b/src/Web/Controllers/UserController.cs
index 6ce1818..05d55c2 100644
--- a/src/Web/Controllers/UserController.cs
+++ b/src/Web/Controllers/UserController.cs
@@ -28,7 +28,7 @@ public class UserController : ControllerBase
private async Task CreateUserInfo(ClaimsPrincipal claimsPrincipal)
{
- if (!claimsPrincipal.Identity.IsAuthenticated)
+ if (claimsPrincipal.Identity == null || claimsPrincipal.Identity.Name == null || !claimsPrincipal.Identity.IsAuthenticated)
{
return UserInfo.Anonymous;
}
diff --git a/src/Web/Extensions/UrlHelperExtensions.cs b/src/Web/Extensions/UrlHelperExtensions.cs
index 75ea598..e643e69 100644
--- a/src/Web/Extensions/UrlHelperExtensions.cs
+++ b/src/Web/Extensions/UrlHelperExtensions.cs
@@ -2,7 +2,7 @@
public static class UrlHelperExtensions
{
- public static string EmailConfirmationLink(this IUrlHelper urlHelper, string userId, string code, string scheme)
+ public static string? EmailConfirmationLink(this IUrlHelper urlHelper, string userId, string code, string scheme)
{
return urlHelper.Action(
action: "GET",
diff --git a/src/Web/Features/MyOrders/GetMyOrdersHandler.cs b/src/Web/Features/MyOrders/GetMyOrdersHandler.cs
index a22961f..6cd64af 100644
--- a/src/Web/Features/MyOrders/GetMyOrdersHandler.cs
+++ b/src/Web/Features/MyOrders/GetMyOrdersHandler.cs
@@ -28,7 +28,7 @@ public class GetMyOrdersHandler : IRequestHandler new OrderViewModel
{
OrderDate = o.OrderDate,
- OrderItems = o.OrderItems?.Select(oi => new OrderItemViewModel()
+ OrderItems = o.OrderItems.Select(oi => new OrderItemViewModel()
{
PictureUrl = oi.ItemOrdered.PictureUri,
ProductId = oi.ItemOrdered.CatalogItemId,
diff --git a/src/Web/Features/OrderDetails/GetOrderDetailsHandler.cs b/src/Web/Features/OrderDetails/GetOrderDetailsHandler.cs
index 4fa7e54..dab5050 100644
--- a/src/Web/Features/OrderDetails/GetOrderDetailsHandler.cs
+++ b/src/Web/Features/OrderDetails/GetOrderDetailsHandler.cs
@@ -9,7 +9,7 @@ using Microsoft.eShopWeb.Web.ViewModels;
namespace Microsoft.eShopWeb.Web.Features.OrderDetails;
-public class GetOrderDetailsHandler : IRequestHandler
+public class GetOrderDetailsHandler : IRequestHandler
{
private readonly IReadRepository _orderRepository;
@@ -18,11 +18,11 @@ public class GetOrderDetailsHandler : IRequestHandler Handle(GetOrderDetails request,
+ public async Task Handle(GetOrderDetails request,
CancellationToken cancellationToken)
{
var spec = new OrderWithItemsByIdSpec(request.OrderId);
- var order = await _orderRepository.GetBySpecAsync(spec, cancellationToken);
+ var order = await _orderRepository.FirstOrDefaultAsync(spec, cancellationToken);
if (order == null)
{
diff --git a/src/Web/HealthChecks/HomePageHealthCheck.cs b/src/Web/HealthChecks/HomePageHealthCheck.cs
index 0579dd7..0896954 100644
--- a/src/Web/HealthChecks/HomePageHealthCheck.cs
+++ b/src/Web/HealthChecks/HomePageHealthCheck.cs
@@ -19,8 +19,8 @@ public class HomePageHealthCheck : IHealthCheck
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
- var request = _httpContextAccessor.HttpContext.Request;
- string myUrl = request.Scheme + "://" + request.Host.ToString();
+ var request = _httpContextAccessor.HttpContext?.Request;
+ string myUrl = request?.Scheme + "://" + request?.Host.ToString();
var client = new HttpClient();
var response = await client.GetAsync(myUrl);
diff --git a/src/Web/Pages/Basket/Checkout.cshtml.cs b/src/Web/Pages/Basket/Checkout.cshtml.cs
index 37d00a7..ee54592 100644
--- a/src/Web/Pages/Basket/Checkout.cshtml.cs
+++ b/src/Web/Pages/Basket/Checkout.cshtml.cs
@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Authorization;
+using Ardalis.GuardClauses;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
@@ -68,6 +69,7 @@ public class CheckoutModel : PageModel
private async Task SetBasketModelAsync()
{
+ Guard.Against.Null(User?.Identity?.Name, nameof(User.Identity.Name));
if (_signInManager.IsSignedIn(HttpContext.User))
{
BasketModel = await _basketViewModelService.GetOrCreateBasketForUser(User.Identity.Name);
@@ -75,7 +77,7 @@ public class CheckoutModel : PageModel
else
{
GetOrSetBasketCookieAndUserName();
- BasketModel = await _basketViewModelService.GetOrCreateBasketForUser(_username);
+ BasketModel = await _basketViewModelService.GetOrCreateBasketForUser(_username!);
}
}
diff --git a/src/Web/Pages/Basket/Index.cshtml.cs b/src/Web/Pages/Basket/Index.cshtml.cs
index 4eea893..11e7a69 100644
--- a/src/Web/Pages/Basket/Index.cshtml.cs
+++ b/src/Web/Pages/Basket/Index.cshtml.cs
@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Mvc;
+using Ardalis.GuardClauses;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
@@ -66,11 +67,13 @@ public class IndexModel : PageModel
private string GetOrSetBasketCookieAndUserName()
{
+ Guard.Against.Null(Request.HttpContext.User.Identity, nameof(Request.HttpContext.User.Identity));
string? userName = null;
if (Request.HttpContext.User.Identity.IsAuthenticated)
{
- return Request.HttpContext.User.Identity.Name;
+ Guard.Against.Null(Request.HttpContext.User.Identity.Name, nameof(Request.HttpContext.User.Identity.Name));
+ return Request.HttpContext.User.Identity.Name!;
}
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME))
diff --git a/src/Web/Pages/Shared/Components/BasketComponent/Basket.cs b/src/Web/Pages/Shared/Components/BasketComponent/Basket.cs
index 519a335..986c7b8 100644
--- a/src/Web/Pages/Shared/Components/BasketComponent/Basket.cs
+++ b/src/Web/Pages/Shared/Components/BasketComponent/Basket.cs
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
+using Ardalis.GuardClauses;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopWeb.Infrastructure.Identity;
@@ -33,17 +34,18 @@ public class Basket : ViewComponent
{
if (_signInManager.IsSignedIn(HttpContext.User))
{
+ Guard.Against.Null(User?.Identity?.Name, nameof(User.Identity.Name));
return await _basketService.CountTotalBasketItems(User.Identity.Name);
}
- string anonymousId = GetAnnonymousIdFromCookie();
+ string? anonymousId = GetAnnonymousIdFromCookie();
if (anonymousId == null)
return 0;
return await _basketService.CountTotalBasketItems(anonymousId);
}
- private string GetAnnonymousIdFromCookie()
+ private string? GetAnnonymousIdFromCookie()
{
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME))
{
diff --git a/src/Web/Services/BasketViewModelService.cs b/src/Web/Services/BasketViewModelService.cs
index e07ca61..658d571 100644
--- a/src/Web/Services/BasketViewModelService.cs
+++ b/src/Web/Services/BasketViewModelService.cs
@@ -28,7 +28,7 @@ public class BasketViewModelService : IBasketViewModelService
public async Task GetOrCreateBasketForUser(string userName)
{
var basketSpec = new BasketWithItemsSpecification(userName);
- var basket = (await _basketRepository.GetBySpecAsync(basketSpec));
+ var basket = (await _basketRepository.FirstOrDefaultAsync(basketSpec));
if (basket == null)
{
diff --git a/src/Web/Services/CatalogItemViewModelService.cs b/src/Web/Services/CatalogItemViewModelService.cs
index 7c66d61..4b63ad0 100644
--- a/src/Web/Services/CatalogItemViewModelService.cs
+++ b/src/Web/Services/CatalogItemViewModelService.cs
@@ -1,4 +1,4 @@
-using System.Threading.Tasks;
+using Ardalis.GuardClauses;
using Microsoft.eShopWeb.ApplicationCore.Entities;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.Web.Interfaces;
@@ -18,7 +18,11 @@ public class CatalogItemViewModelService : ICatalogItemViewModelService
public async Task UpdateCatalogItem(CatalogItemViewModel viewModel)
{
var existingCatalogItem = await _catalogItemRepository.GetByIdAsync(viewModel.Id);
- existingCatalogItem.UpdateDetails(viewModel.Name, existingCatalogItem.Description, viewModel.Price);
+
+ Guard.Against.Null(existingCatalogItem, nameof(existingCatalogItem));
+
+ CatalogItem.CatalogItemDetails details = new(viewModel.Name, existingCatalogItem.Description, viewModel.Price);
+ existingCatalogItem.UpdateDetails(details);
await _catalogItemRepository.UpdateAsync(existingCatalogItem);
}
}
diff --git a/src/Web/SlugifyParameterTransformer.cs b/src/Web/SlugifyParameterTransformer.cs
index 3946970..d2d1c56 100644
--- a/src/Web/SlugifyParameterTransformer.cs
+++ b/src/Web/SlugifyParameterTransformer.cs
@@ -5,11 +5,13 @@ namespace Microsoft.eShopWeb.Web;
public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
- public string? TransformOutbound(object value)
+ public string? TransformOutbound(object? value)
{
if (value == null) { return null; }
+ string? str = value.ToString();
+ if (string.IsNullOrEmpty(str)) { return null; }
// Slugify value
- return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
+ return Regex.Replace(str, "([a-z])([A-Z])", "$1-$2").ToLower();
}
}
diff --git a/tests/FunctionalTests/Web/Pages/HomePageOnGet.cs b/tests/FunctionalTests/Web/Pages/HomePageOnGet.cs
index 76cc135..635d87b 100644
--- a/tests/FunctionalTests/Web/Pages/HomePageOnGet.cs
+++ b/tests/FunctionalTests/Web/Pages/HomePageOnGet.cs
@@ -1,6 +1,4 @@
-using System.Net.Http;
-using System.Threading.Tasks;
-using Microsoft.eShopWeb.FunctionalTests.Web;
+using Microsoft.eShopWeb.FunctionalTests.Web;
using Xunit;
namespace Microsoft.eShopWeb.FunctionalTests.WebRazorPages;
diff --git a/tests/IntegrationTests/Repositories/OrderRepositoryTests/GetByIdWithItemsAsync.cs b/tests/IntegrationTests/Repositories/OrderRepositoryTests/GetByIdWithItemsAsync.cs
index a7d3e56..77e9190 100644
--- a/tests/IntegrationTests/Repositories/OrderRepositoryTests/GetByIdWithItemsAsync.cs
+++ b/tests/IntegrationTests/Repositories/OrderRepositoryTests/GetByIdWithItemsAsync.cs
@@ -49,7 +49,7 @@ public class GetByIdWithItemsAsync
//Act
var spec = new OrderWithItemsByIdSpec(secondOrderId);
- var orderFromRepo = await _orderRepository.GetBySpecAsync(spec);
+ var orderFromRepo = await _orderRepository.FirstOrDefaultAsync(spec);
//Assert
Assert.Equal(secondOrderId, orderFromRepo.Id);
diff --git a/tests/UnitTests/ApplicationCore/Entities/CatalogItemTests/UpdateDetails.cs b/tests/UnitTests/ApplicationCore/Entities/CatalogItemTests/UpdateDetails.cs
deleted file mode 100644
index edc6f2b..0000000
--- a/tests/UnitTests/ApplicationCore/Entities/CatalogItemTests/UpdateDetails.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System;
-using Microsoft.eShopWeb.ApplicationCore.Entities;
-using Xunit;
-
-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(() => _testItem.UpdateDetails(newValue, _validDescription, _validPrice));
- }
-
- [Fact]
- public void ThrowsArgumentExceptionGivenEmptyDescription()
- {
- string newValue = "";
- Assert.Throws(() => _testItem.UpdateDetails(_validName, newValue, _validPrice));
- }
-
- [Fact]
- public void ThrowsArgumentNullExceptionGivenNullName()
- {
- Assert.Throws(() => _testItem.UpdateDetails(null, _validDescription, _validPrice));
- }
-
- [Fact]
- public void ThrowsArgumentNullExceptionGivenNullDescription()
- {
- Assert.Throws(() => _testItem.UpdateDetails(_validName, null, _validPrice));
- }
-
- [Theory]
- [InlineData(0)]
- [InlineData(-1.23)]
- public void ThrowsArgumentExceptionGivenNonPositivePrice(decimal newPrice)
- {
- Assert.Throws(() => _testItem.UpdateDetails(_validName, _validDescription, newPrice));
- }
-}
diff --git a/tests/UnitTests/ApplicationCore/Extensions/TestParent.cs b/tests/UnitTests/ApplicationCore/Extensions/TestParent.cs
index bd20e36..ec791b4 100644
--- a/tests/UnitTests/ApplicationCore/Extensions/TestParent.cs
+++ b/tests/UnitTests/ApplicationCore/Extensions/TestParent.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Extensions;
@@ -9,12 +6,22 @@ public class TestParent : IEquatable
{
public int Id { get; set; }
- public string Name { get; set; }
+ public string? Name { get; set; }
- public IEnumerable Children { get; set; }
+ public IEnumerable? Children { get; set; }
- public bool Equals([AllowNull] TestParent other) =>
- other?.Id == Id && other?.Name == Name &&
- (other?.Children is null && Children is null ||
- (other?.Children?.Zip(Children)?.All(t => t.First?.Equals(t.Second) ?? false) ?? false));
+ public bool Equals([AllowNull] TestParent other)
+ {
+ if (other?.Id == Id && other?.Name == Name)
+ {
+ if (Children is null)
+ {
+ return other?.Children is null;
+ }
+
+ return other?.Children?.Zip(Children).All(t => t.First?.Equals(t.Second) ?? false) ?? false;
+ }
+
+ return false;
+ }
}
diff --git a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/AddItemToBasket.cs b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/AddItemToBasket.cs
index 7937d08..9f11114 100644
--- a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/AddItemToBasket.cs
+++ b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/AddItemToBasket.cs
@@ -12,19 +12,20 @@ public class AddItemToBasket
{
private readonly string _buyerId = "Test buyerId";
private readonly Mock> _mockBasketRepo = new();
+ private readonly Mock> _mockLogger = new();
[Fact]
public async Task InvokesBasketRepositoryGetBySpecAsyncOnce()
{
var basket = new Basket(_buyerId);
basket.AddItem(1, It.IsAny(), It.IsAny());
- _mockBasketRepo.Setup(x => x.GetBySpecAsync(It.IsAny(), default)).ReturnsAsync(basket);
+ _mockBasketRepo.Setup(x => x.FirstOrDefaultAsync(It.IsAny(), default)).ReturnsAsync(basket);
- var basketService = new BasketService(_mockBasketRepo.Object, null);
+ var basketService = new BasketService(_mockBasketRepo.Object, _mockLogger.Object);
await basketService.AddItemToBasket(basket.BuyerId, 1, 1.50m);
- _mockBasketRepo.Verify(x => x.GetBySpecAsync(It.IsAny(), default), Times.Once);
+ _mockBasketRepo.Verify(x => x.FirstOrDefaultAsync(It.IsAny(), default), Times.Once);
}
[Fact]
@@ -32,9 +33,9 @@ public class AddItemToBasket
{
var basket = new Basket(_buyerId);
basket.AddItem(1, It.IsAny(), It.IsAny());
- _mockBasketRepo.Setup(x => x.GetBySpecAsync(It.IsAny(), default)).ReturnsAsync(basket);
+ _mockBasketRepo.Setup(x => x.FirstOrDefaultAsync(It.IsAny(), default)).ReturnsAsync(basket);
- var basketService = new BasketService(_mockBasketRepo.Object, null);
+ var basketService = new BasketService(_mockBasketRepo.Object, _mockLogger.Object);
await basketService.AddItemToBasket(basket.BuyerId, 1, 1.50m);
diff --git a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs
index 01eff04..cd94c3a 100644
--- a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs
+++ b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/DeleteBasket.cs
@@ -11,6 +11,7 @@ public class DeleteBasket
{
private readonly string _buyerId = "Test buyerId";
private readonly Mock> _mockBasketRepo = new();
+ private readonly Mock> _mockLogger = new();
[Fact]
public async Task ShouldInvokeBasketRepositoryDeleteAsyncOnce()
@@ -20,7 +21,7 @@ public class DeleteBasket
basket.AddItem(2, It.IsAny(), It.IsAny());
_mockBasketRepo.Setup(x => x.GetByIdAsync(It.IsAny(), default))
.ReturnsAsync(basket);
- var basketService = new BasketService(_mockBasketRepo.Object, null);
+ var basketService = new BasketService(_mockBasketRepo.Object, _mockLogger.Object);
await basketService.DeleteBasketAsync(It.IsAny());
diff --git a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/SetQuantities.cs b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/SetQuantities.cs
deleted file mode 100644
index 57d4d6c..0000000
--- a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/SetQuantities.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using Microsoft.eShopWeb.ApplicationCore.Entities.BasketAggregate;
-using Microsoft.eShopWeb.ApplicationCore.Exceptions;
-using Microsoft.eShopWeb.ApplicationCore.Interfaces;
-using Microsoft.eShopWeb.ApplicationCore.Services;
-using Moq;
-using Xunit;
-
-namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Services.BasketServiceTests;
-
-public class SetQuantities
-{
- private readonly int _invalidId = -1;
- private readonly Mock> _mockBasketRepo = new();
-
- [Fact]
- public async Task ThrowsGivenInvalidBasketId()
- {
- var basketService = new BasketService(_mockBasketRepo.Object, null);
-
- await Assert.ThrowsAsync(async () =>
- await basketService.SetQuantities(_invalidId, new System.Collections.Generic.Dictionary()));
- }
-
- [Fact]
- public async Task ThrowsGivenNullQuantities()
- {
- var basketService = new BasketService(null, null);
-
- await Assert.ThrowsAsync(async () =>
- await basketService.SetQuantities(123, null));
- }
-}
diff --git a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/TransferBasket.cs b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/TransferBasket.cs
index 390e9eb..c82c18d 100644
--- a/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/TransferBasket.cs
+++ b/tests/UnitTests/ApplicationCore/Services/BasketServiceTests/TransferBasket.cs
@@ -16,34 +16,19 @@ public class TransferBasket
private readonly string _nonexistentUserBasketBuyerId = "newuser@microsoft.com";
private readonly string _existentUserBasketBuyerId = "testuser@microsoft.com";
private readonly Mock> _mockBasketRepo = new();
-
- [Fact]
- public async Task ThrowsGivenNullAnonymousId()
- {
- var basketService = new BasketService(null, null);
-
- await Assert.ThrowsAsync(async () => await basketService.TransferBasketAsync(null, "steve"));
- }
-
- [Fact]
- public async Task ThrowsGivenNullUserId()
- {
- var basketService = new BasketService(null, null);
-
- await Assert.ThrowsAsync(async () => await basketService.TransferBasketAsync("abcdefg", null));
- }
+ private readonly Mock> _mockLogger = new();
[Fact]
public async Task InvokesBasketRepositoryFirstOrDefaultAsyncOnceIfAnonymousBasketNotExists()
{
var anonymousBasket = null as Basket;
var userBasket = new Basket(_existentUserBasketBuyerId);
- _mockBasketRepo.SetupSequence(x => x.GetBySpecAsync(It.IsAny(), default))
+ _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny(), default))
.ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket);
- var basketService = new BasketService(_mockBasketRepo.Object, null);
+ var basketService = new BasketService(_mockBasketRepo.Object, _mockLogger.Object);
await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId);
- _mockBasketRepo.Verify(x => x.GetBySpecAsync(It.IsAny(), default), Times.Once);
+ _mockBasketRepo.Verify(x => x.FirstOrDefaultAsync(It.IsAny(), default), Times.Once);
}
[Fact]
@@ -55,10 +40,10 @@ public class TransferBasket
var userBasket = new Basket(_existentUserBasketBuyerId);
userBasket.AddItem(1, 10, 4);
userBasket.AddItem(2, 99, 3);
- _mockBasketRepo.SetupSequence(x => x.GetBySpecAsync(It.IsAny(), default))
+ _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny(), default))
.ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket);
- var basketService = new BasketService(_mockBasketRepo.Object, null);
+ var basketService = new BasketService(_mockBasketRepo.Object, _mockLogger.Object);
await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId);
_mockBasketRepo.Verify(x => x.UpdateAsync(userBasket, default), Times.Once);
Assert.Equal(3, userBasket.Items.Count);
@@ -72,10 +57,10 @@ public class TransferBasket
{
var anonymousBasket = new Basket(_existentAnonymousBasketBuyerId);
var userBasket = new Basket(_existentUserBasketBuyerId);
- _mockBasketRepo.SetupSequence(x => x.GetBySpecAsync(It.IsAny(), default))
+ _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny(), default))
.ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket);
- var basketService = new BasketService(_mockBasketRepo.Object, null);
+ var basketService = new BasketService(_mockBasketRepo.Object, _mockLogger.Object);
await basketService.TransferBasketAsync(_nonexistentAnonymousBasketBuyerId, _existentUserBasketBuyerId);
_mockBasketRepo.Verify(x => x.UpdateAsync(userBasket, default), Times.Once);
_mockBasketRepo.Verify(x => x.DeleteAsync(anonymousBasket, default), Times.Once);
@@ -86,10 +71,10 @@ public class TransferBasket
{
var anonymousBasket = new Basket(_existentAnonymousBasketBuyerId);
var userBasket = null as Basket;
- _mockBasketRepo.SetupSequence(x => x.GetBySpecAsync(It.IsAny(), default))
+ _mockBasketRepo.SetupSequence(x => x.FirstOrDefaultAsync(It.IsAny(), default))
.ReturnsAsync(anonymousBasket)
.ReturnsAsync(userBasket);
- var basketService = new BasketService(_mockBasketRepo.Object, null);
+ var basketService = new BasketService(_mockBasketRepo.Object, _mockLogger.Object);
await basketService.TransferBasketAsync(_existentAnonymousBasketBuyerId, _nonexistentUserBasketBuyerId);
_mockBasketRepo.Verify(x => x.AddAsync(It.Is(x => x.BuyerId == _nonexistentUserBasketBuyerId), default), Times.Once);
}
diff --git a/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterPaginatedSpecification.cs b/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterPaginatedSpecification.cs
index c3d3828..5ac89a2 100644
--- a/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterPaginatedSpecification.cs
+++ b/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterPaginatedSpecification.cs
@@ -1,6 +1,4 @@
-using System.Collections.Generic;
-using System.Linq;
-using Microsoft.eShopWeb.ApplicationCore.Entities;
+using Microsoft.eShopWeb.ApplicationCore.Entities;
using Xunit;
namespace Microsoft.eShopWeb.UnitTests.ApplicationCore.Specifications;
@@ -12,9 +10,7 @@ public class CatalogFilterPaginatedSpecification
{
var spec = new eShopWeb.ApplicationCore.Specifications.CatalogFilterPaginatedSpecification(0, 10, null, null);
- var result = GetTestCollection()
- .AsQueryable()
- .Where(spec.WhereExpressions.FirstOrDefault().Filter);
+ var result = spec.Evaluate(GetTestCollection());
Assert.NotNull(result);
Assert.Equal(4, result.ToList().Count);
@@ -25,9 +21,7 @@ public class CatalogFilterPaginatedSpecification
{
var spec = new eShopWeb.ApplicationCore.Specifications.CatalogFilterPaginatedSpecification(0, 10, 1, 1);
- var result = GetTestCollection()
- .AsQueryable()
- .Where(spec.WhereExpressions.FirstOrDefault().Filter);
+ var result = spec.Evaluate(GetTestCollection()).ToList();
Assert.NotNull(result);
Assert.Equal(2, result.ToList().Count);
diff --git a/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecification.cs b/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecification.cs
index 56b1e0d..cb065df 100644
--- a/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecification.cs
+++ b/tests/UnitTests/ApplicationCore/Specifications/CatalogFilterSpecification.cs
@@ -19,9 +19,7 @@ public class CatalogFilterSpecification
{
var spec = new eShopWeb.ApplicationCore.Specifications.CatalogFilterSpecification(brandId, typeId);
- var result = GetTestItemCollection()
- .AsQueryable()
- .Where(spec.WhereExpressions.FirstOrDefault().Filter);
+ var result = spec.Evaluate(GetTestItemCollection()).ToList();
Assert.Equal(expectedCount, result.Count());
}
diff --git a/tests/UnitTests/ApplicationCore/Specifications/CatalogItemsSpecification.cs b/tests/UnitTests/ApplicationCore/Specifications/CatalogItemsSpecification.cs
index 0085ca7..3258322 100644
--- a/tests/UnitTests/ApplicationCore/Specifications/CatalogItemsSpecification.cs
+++ b/tests/UnitTests/ApplicationCore/Specifications/CatalogItemsSpecification.cs
@@ -14,9 +14,7 @@ public class CatalogItemsSpecification
var catalogItemIds = new int[] { 1 };
var spec = new eShopWeb.ApplicationCore.Specifications.CatalogItemsSpecification(catalogItemIds);
- var result = GetTestCollection()
- .AsQueryable()
- .Where(spec.WhereExpressions.FirstOrDefault().Filter);
+ var result = spec.Evaluate(GetTestCollection()).ToList();
Assert.NotNull(result);
Assert.Single(result.ToList());
@@ -28,9 +26,7 @@ public class CatalogItemsSpecification
var catalogItemIds = new int[] { 1, 3 };
var spec = new eShopWeb.ApplicationCore.Specifications.CatalogItemsSpecification(catalogItemIds);
- var result = GetTestCollection()
- .AsQueryable()
- .Where(spec.WhereExpressions.FirstOrDefault().Filter);
+ var result = spec.Evaluate(GetTestCollection()).ToList();
Assert.NotNull(result);
Assert.Equal(2, result.ToList().Count);
diff --git a/tests/UnitTests/ApplicationCore/Specifications/CustomerOrdersWithItemsSpecification.cs b/tests/UnitTests/ApplicationCore/Specifications/CustomerOrdersWithItemsSpecification.cs
index fe3281e..0a066d0 100644
--- a/tests/UnitTests/ApplicationCore/Specifications/CustomerOrdersWithItemsSpecification.cs
+++ b/tests/UnitTests/ApplicationCore/Specifications/CustomerOrdersWithItemsSpecification.cs
@@ -15,14 +15,12 @@ public class CustomerOrdersWithItemsSpecification
{
var spec = new eShopWeb.ApplicationCore.Specifications.CustomerOrdersWithItemsSpecification(_buyerId);
- var result = GetTestCollection()
- .AsQueryable()
- .FirstOrDefault(spec.WhereExpressions.FirstOrDefault().Filter);
+ var result = spec.Evaluate(GetTestCollection()).FirstOrDefault();
Assert.NotNull(result);
Assert.NotNull(result.OrderItems);
Assert.Equal(1, result.OrderItems.Count);
- Assert.NotNull(result.OrderItems.FirstOrDefault().ItemOrdered);
+ Assert.NotNull(result.OrderItems.FirstOrDefault()?.ItemOrdered);
}
[Fact]
@@ -30,15 +28,12 @@ public class CustomerOrdersWithItemsSpecification
{
var spec = new eShopWeb.ApplicationCore.Specifications.CustomerOrdersWithItemsSpecification(_buyerId);
- var result = GetTestCollection()
- .AsQueryable()
- .Where(spec.WhereExpressions.FirstOrDefault().Filter)
- .ToList();
+ var result = spec.Evaluate(GetTestCollection()).ToList();
Assert.NotNull(result);
Assert.Equal(2, result.Count);
Assert.Equal(1, result[0].OrderItems.Count);
- Assert.NotNull(result[0].OrderItems.FirstOrDefault().ItemOrdered);
+ Assert.NotNull(result[0].OrderItems.FirstOrDefault()?.ItemOrdered);
Assert.Equal(2, result[1].OrderItems.Count);
Assert.NotNull(result[1].OrderItems.ToList()[0].ItemOrdered);
Assert.NotNull(result[1].OrderItems.ToList()[1].ItemOrdered);
diff --git a/tests/UnitTests/MediatorHandlers/OrdersTests/GetOrderDetails.cs b/tests/UnitTests/MediatorHandlers/OrdersTests/GetOrderDetails.cs
index ec4cadd..aa19b83 100644
--- a/tests/UnitTests/MediatorHandlers/OrdersTests/GetOrderDetails.cs
+++ b/tests/UnitTests/MediatorHandlers/OrdersTests/GetOrderDetails.cs
@@ -22,7 +22,7 @@ public class GetOrderDetails
Order order = new Order("buyerId", address, new List { item });
_mockOrderRepository = new Mock>();
- _mockOrderRepository.Setup(x => x.GetBySpecAsync(It.IsAny(), default))
+ _mockOrderRepository.Setup(x => x.FirstOrDefaultAsync(It.IsAny(), default))
.ReturnsAsync(order);
}