using FluentAssertions; using FnbEngine.API.Application.Commands; using FnbEngine.Domain.AggregatesModel.KitchenAggregate; using FnbEngine.Domain.SeedWork; using Moq; using Xunit; namespace FnbEngine.UnitTests.Application.Commands; /// /// EN: Unit tests for UpdateTicketStatusCommandHandler. /// VI: Unit tests cho UpdateTicketStatusCommandHandler. /// public class UpdateTicketStatusCommandHandlerTests { private readonly Mock _repoMock; private readonly UpdateTicketStatusCommandHandler _handler; public UpdateTicketStatusCommandHandlerTests() { _repoMock = new Mock(); _repoMock.Setup(r => r.UnitOfWork.SaveEntitiesAsync(It.IsAny())) .ReturnsAsync(true); _handler = new UpdateTicketStatusCommandHandler(_repoMock.Object); } [Theory] [InlineData("inprogress", "InProgress")] [InlineData("InProgress", "InProgress")] [InlineData("ready", "Ready")] [InlineData("Ready", "Ready")] [InlineData("served", "Served")] [InlineData("Served", "Served")] public async Task Handle_WithValidStatus_ShouldUpdateTicketStatus(string inputStatus, string expectedStatus) { // Arrange var ticketId = Guid.NewGuid(); var ticket = new KitchenTicket(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), "Pho Bo"); _repoMock.Setup(r => r.GetByIdAsync(ticketId, It.IsAny())) .ReturnsAsync(ticket); var command = new UpdateTicketStatusCommand(ticketId, inputStatus); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.Should().BeTrue(); ticket.Status.Should().Be(expectedStatus); _repoMock.Verify(r => r.Update(ticket), Times.Once); _repoMock.Verify(r => r.UnitOfWork.SaveEntitiesAsync(It.IsAny()), Times.Once); } [Fact] public async Task Handle_WithNonExistentTicket_ShouldThrowInvalidOperationException() { // Arrange var ticketId = Guid.NewGuid(); _repoMock.Setup(r => r.GetByIdAsync(ticketId, It.IsAny())) .ReturnsAsync((KitchenTicket?)null); var command = new UpdateTicketStatusCommand(ticketId, "Ready"); // Act var action = () => _handler.Handle(command, CancellationToken.None); // Assert await action.Should().ThrowAsync() .WithMessage($"*{ticketId}*not found*"); } [Fact] public async Task Handle_WithInvalidStatus_ShouldThrowArgumentException() { // Arrange var ticketId = Guid.NewGuid(); var ticket = new KitchenTicket(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), "Pho Bo"); _repoMock.Setup(r => r.GetByIdAsync(ticketId, It.IsAny())) .ReturnsAsync(ticket); var command = new UpdateTicketStatusCommand(ticketId, "InvalidStatus"); // Act var action = () => _handler.Handle(command, CancellationToken.None); // Assert await action.Should().ThrowAsync() .WithMessage("*Invalid status*"); } [Fact] public async Task Handle_WithServedStatus_ShouldRaiseDomainEvent() { // Arrange var ticketId = Guid.NewGuid(); var ticket = new KitchenTicket(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), "Pho Bo"); _repoMock.Setup(r => r.GetByIdAsync(ticketId, It.IsAny())) .ReturnsAsync(ticket); var command = new UpdateTicketStatusCommand(ticketId, "Served"); // Act await _handler.Handle(command, CancellationToken.None); // Assert ticket.DomainEvents.Should().ContainSingle(); } }