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); } }