Skip to content

Instantly share code, notes, and snippets.

@fnmssteam
Created February 19, 2025 01:38
Show Gist options
  • Select an option

  • Save fnmssteam/8ab50f3ecd6809623d12e3f9713288c4 to your computer and use it in GitHub Desktop.

Select an option

Save fnmssteam/8ab50f3ecd6809623d12e3f9713288c4 to your computer and use it in GitHub Desktop.
DeepSeek Online Store Checkout System Challenge
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;
}
}
}
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