Created
February 19, 2025 01:38
-
-
Save fnmssteam/8ab50f3ecd6809623d12e3f9713288c4 to your computer and use it in GitHub Desktop.
DeepSeek Online Store Checkout System Challenge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using DeepSeekTestExercise.Contracts; | |
| using DeepSeekTestExercise.Entities; | |
| using DeepSeekTestExercise.Events; | |
| using DeepSeekTestExercise.Exceptions; | |
| namespace DeepSeekTestExercise.Services; | |
| public class ShoppingCart | |
| { | |
| private readonly IPaymentGateway _paymentGateway; | |
| private readonly IInventoryService _inventoryService; | |
| public event EventHandler<OrderProcessedEventArgs> OrderProcessed; | |
| public ShoppingCart(IPaymentGateway paymentGateway, IInventoryService inventoryService) | |
| { | |
| _paymentGateway = paymentGateway; | |
| _inventoryService = inventoryService; | |
| } | |
| public async Task<bool> CheckoutAsync(Cart cart) | |
| { | |
| if (!_inventoryService.IsStockAvailable(cart.ItemId, cart.Quantity)) | |
| return false; | |
| try | |
| { | |
| await _paymentGateway.ProcessPaymentAsync(cart.TotalAmount); | |
| _inventoryService.UpdateStock(cart.ItemId, -cart.Quantity); | |
| OrderProcessed?.Invoke(this, new OrderProcessedEventArgs(true)); | |
| return true; | |
| } | |
| catch (Exception e) when (e is PaymentFailedException || e is TaskCanceledException) | |
| { | |
| OrderProcessed?.Invoke(this, new OrderProcessedEventArgs(false)); | |
| return false; | |
| } | |
| } | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using DeepSeekTestExercise.Contracts; | |
| using DeepSeekTestExercise.Entities; | |
| using DeepSeekTestExercise.Exceptions; | |
| using DeepSeekTestExercise.Services; | |
| using NSubstitute; | |
| using NSubstitute.ExceptionExtensions; | |
| namespace DeepSeekTestExerciseTests.Services; | |
| public class ShoppingCartTest | |
| { | |
| private readonly string _itemId; | |
| private readonly int _quantity; | |
| private readonly decimal _amount; | |
| public ShoppingCartTest() | |
| { | |
| _itemId = "1D"; | |
| _quantity = 2; | |
| _amount = 10.55m; | |
| } | |
| [Fact] | |
| public async Task CheckoutAsync_StockAvailableAndPaymentSucceeds_ReturnsTrueAndUpdatesStock() | |
| { | |
| // Arrange | |
| var cart = new Cart { ItemId = _itemId, Quantity = _quantity, TotalAmount = _amount }; | |
| var paymentGateway = Substitute.For<IPaymentGateway>(); | |
| var inventoryService = Substitute.For<IInventoryService>(); | |
| inventoryService.IsStockAvailable(_itemId, _quantity).Returns(true); | |
| var shoppingCart = new ShoppingCart(paymentGateway, inventoryService); | |
| bool eventTriggered = false; | |
| int numberOfEvents = 0; | |
| shoppingCart.OrderProcessed += (sender, args) => eventTriggered = true; numberOfEvents++; | |
| // Act | |
| var result = await shoppingCart.CheckoutAsync(cart); | |
| // Assert | |
| Assert.True(result); | |
| await paymentGateway.Received(1).ProcessPaymentAsync(_amount); | |
| inventoryService.Received(1).UpdateStock(_itemId, -_quantity); | |
| Assert.True(eventTriggered); | |
| Assert.Equal(1, numberOfEvents); | |
| } | |
| [Fact] | |
| public async Task CheckoutAsync_NoStock_ReturnsFalse() | |
| { | |
| // Arrange | |
| var cart = new Cart { ItemId = _itemId, Quantity = _quantity, TotalAmount = _amount }; | |
| var paymentGateway = Substitute.For<IPaymentGateway>(); | |
| var inventoryService = Substitute.For<IInventoryService>(); | |
| inventoryService.IsStockAvailable(_itemId, _quantity).Returns(false); | |
| var shoppingCart = new ShoppingCart(paymentGateway, inventoryService); | |
| bool eventTriggered = false; | |
| int numberOfEvents = 0; | |
| shoppingCart.OrderProcessed += (sender, args) => eventTriggered = true; numberOfEvents++; | |
| // Act | |
| var result = await shoppingCart.CheckoutAsync(cart); | |
| // Assert | |
| Assert.False(result); | |
| await paymentGateway.DidNotReceive().ProcessPaymentAsync(_amount); | |
| inventoryService.DidNotReceive().UpdateStock(_itemId, -_quantity); | |
| Assert.False(eventTriggered); | |
| Assert.Equal(1, numberOfEvents); | |
| } | |
| [Fact] | |
| public async Task CheckoutAsync_PaymentFails_ReturnsFalse() | |
| { | |
| // Arrange | |
| var cart = new Cart { ItemId = _itemId, Quantity = _quantity, TotalAmount = _amount }; | |
| var paymentGateway = Substitute.For<IPaymentGateway>(); | |
| paymentGateway.ProcessPaymentAsync(_amount).Throws<PaymentFailedException>(); | |
| var inventoryService = Substitute.For<IInventoryService>(); | |
| inventoryService.IsStockAvailable(_itemId, _quantity).Returns(true); | |
| var shoppingCart = new ShoppingCart(paymentGateway, inventoryService); | |
| bool eventTriggered = false; | |
| int numberOfEvents = 0; | |
| shoppingCart.OrderProcessed += (sender, args) => eventTriggered = true; numberOfEvents++; | |
| // Act | |
| var result = await shoppingCart.CheckoutAsync(cart); | |
| // Assert | |
| Assert.False(result); | |
| await paymentGateway.Received(1).ProcessPaymentAsync(_amount); | |
| inventoryService.DidNotReceive().UpdateStock(_itemId, -_quantity); | |
| Assert.True(eventTriggered); | |
| Assert.Equal(1, numberOfEvents); | |
| } | |
| [Fact] | |
| public async Task CheckoutAsync_PaymentTimesOut_ReturnsFalse() | |
| { | |
| // Arrange | |
| var cart = new Cart { ItemId = _itemId, Quantity = _quantity, TotalAmount = _amount }; | |
| var paymentGateway = Substitute.For<IPaymentGateway>(); | |
| paymentGateway.ProcessPaymentAsync(_amount) | |
| .Returns(async _ => await Task.Delay(5000, new CancellationToken(true))); | |
| var inventoryService = Substitute.For<IInventoryService>(); | |
| inventoryService.IsStockAvailable(_itemId, _quantity).Returns(true); | |
| var shoppingCart = new ShoppingCart(paymentGateway, inventoryService); | |
| bool eventTriggered = false; | |
| int numberOfEvents = 0; | |
| shoppingCart.OrderProcessed += (sender, args) => eventTriggered = true; numberOfEvents++; | |
| // Act | |
| var result = await shoppingCart.CheckoutAsync(cart); | |
| // Assert | |
| Assert.False(result); | |
| await paymentGateway.Received(1).ProcessPaymentAsync(_amount); | |
| inventoryService.DidNotReceive().UpdateStock(_itemId, -_quantity); | |
| Assert.True(eventTriggered); | |
| Assert.Equal(1, numberOfEvents); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment