kitchen-service/tests/Kitchen.Service.Application.UnitTests/KitchenWorkflowUseCasesTests.cs
2026-03-31 19:55:18 -06:00

131 lines
5.1 KiB
C#

using Kitchen.Service.Application.Ports;
using Kitchen.Service.Application.UseCases;
using Kitchen.Service.Contracts.Requests;
namespace Kitchen.Service.Application.UnitTests;
public class KitchenWorkflowUseCasesTests
{
private readonly InMemoryKitchenWorkItemStorePort workItemStore = new();
private readonly InMemoryRestaurantLifecycleSyncPort restaurantLifecycle = new();
private readonly DefaultKitchenWorkflowPort workflowPort;
public KitchenWorkflowUseCasesTests()
{
workflowPort = new DefaultKitchenWorkflowPort(workItemStore, restaurantLifecycle);
}
[Fact]
public async Task GetKitchenBoardUseCase_ReturnsLanesAndStations()
{
var useCase = new GetKitchenBoardUseCase(workflowPort);
var response = await useCase.HandleAsync(new GetKitchenBoardRequest("demo-context"), CancellationToken.None);
Assert.Equal("demo-context", response.ContextId);
Assert.NotEmpty(response.Lanes);
Assert.NotEmpty(response.AvailableStations);
Assert.Contains(response.Lanes, lane => lane.Lane == "queued");
}
[Fact]
public async Task GetKitchenBoardUseCase_DerivesTicketForAcceptedRestaurantOrder()
{
await restaurantLifecycle.UpsertOrderAsync(
new Kitchen.Service.Application.State.PersistedRestaurantLifecycleRecord(
"demo-context",
"ORD-1099",
"CHK-1099",
"T-31",
"Accepted",
"Open",
3,
false,
42.00m,
"USD",
"customer-orders",
new[] { "ITEM-701", "ITEM-702" },
DateTime.UtcNow),
CancellationToken.None);
var useCase = new GetKitchenBoardUseCase(workflowPort);
var response = await useCase.HandleAsync(new GetKitchenBoardRequest("demo-context"), CancellationToken.None);
var queuedLane = Assert.Single(response.Lanes, lane => lane.Lane == "queued");
var derivedItem = Assert.Single(queuedLane.Items, item => item.OrderId == "ORD-1099");
Assert.Equal("hot-line", derivedItem.Station);
Assert.Equal("Queued", derivedItem.State);
}
[Fact]
public async Task ClaimKitchenWorkItemUseCase_ReturnsClaimedResponse()
{
var useCase = new ClaimKitchenWorkItemUseCase(workflowPort);
var response = await useCase.HandleAsync(
new ClaimKitchenWorkItemRequest("demo-context", "WK-1001", "chef-maya"),
CancellationToken.None);
var updated = await workItemStore.GetAsync("demo-context", "WK-1001", CancellationToken.None);
Assert.True(response.Claimed);
Assert.Equal("chef-maya", response.ClaimedBy);
Assert.Equal("chef-maya", updated!.ClaimedBy);
}
[Fact]
public async Task UpdateKitchenPriorityUseCase_NormalizesPriority()
{
var useCase = new UpdateKitchenPriorityUseCase(workflowPort);
var response = await useCase.HandleAsync(
new UpdateKitchenPriorityRequest("demo-context", "WK-1001", 0, "expo-noah"),
CancellationToken.None);
var updated = await workItemStore.GetAsync("demo-context", "WK-1001", CancellationToken.None);
Assert.Equal(1, response.Priority);
Assert.Equal(1, updated!.Priority);
}
[Fact]
public async Task TransitionKitchenOrderStateUseCase_UpdatesKitchenAndRestaurantFlow()
{
var useCase = new TransitionKitchenOrderStateUseCase(workflowPort);
var response = await useCase.HandleAsync(
new TransitionKitchenOrderStateRequest("ORD-1001", "KT-1001", "Preparing", "chef-maya"),
CancellationToken.None);
var updatedWorkItem = await workItemStore.GetAsync("demo-context", "WK-1001", CancellationToken.None);
var updatedOrder = await restaurantLifecycle.GetOrderAsync("demo-context", "ORD-1001", CancellationToken.None);
Assert.True(response.Applied);
Assert.Equal("Queued", response.PreviousState);
Assert.Equal("Preparing", response.CurrentState);
Assert.Equal("Preparing", updatedWorkItem!.State);
Assert.Equal("Preparing", updatedOrder!.OrderState);
Assert.True(updatedOrder.HasKitchenTicket);
}
[Fact]
public async Task TransitionKitchenOrderStateUseCase_MarksOrderServedWhenKitchenDelivers()
{
var useCase = new TransitionKitchenOrderStateUseCase(workflowPort);
var response = await useCase.HandleAsync(
new TransitionKitchenOrderStateRequest("ORD-1003", "KT-1003", "Delivered", "expo-noah"),
CancellationToken.None);
var updatedWorkItem = await workItemStore.GetAsync("demo-context", "WK-1003", CancellationToken.None);
var updatedOrder = await restaurantLifecycle.GetOrderAsync("demo-context", "ORD-1003", CancellationToken.None);
Assert.True(response.Applied);
Assert.Equal("ReadyForPickup", response.PreviousState);
Assert.Equal("Delivered", response.CurrentState);
Assert.Equal("Delivered", updatedWorkItem!.State);
Assert.Equal("Served", updatedOrder!.OrderState);
}
}