using System.Net; using System.Net.Http; using System.Text; using Waiter.Floor.Bff.Application.Adapters; using Waiter.Floor.Bff.Contracts.Requests; namespace Waiter.Floor.Bff.Application.UnitTests; public sealed class OperationsWaiterServiceClientTests { [Fact] public async Task FetchAssignmentsAsync_MapsAssignmentsAndRecentActivity() { var client = CreateClient(""" { "contextId": "demo-context", "locationId": "restaurant-demo", "summary": "2 tables currently require floor attention.", "assignments": [ { "waiterId": "service-pool", "tableId": "T-12", "status": "Preparing", "activeOrders": 2 } ], "recentActivity": [ "Order ORD-1002 is currently preparing for table T-12." ] } """); var adapter = new OperationsWaiterServiceClient(client); var response = await adapter.FetchAssignmentsAsync(new GetWaiterAssignmentsRequest("demo-context"), CancellationToken.None); Assert.Equal("restaurant-demo", response.LocationId); Assert.Single(response.Assignments); Assert.Single(response.RecentActivity); Assert.Equal("service-pool", response.Assignments.Single().WaiterId); Assert.Equal("Preparing", response.Assignments.Single().Status); } [Fact] public async Task FetchRecentActivityAsync_ProjectsActivityOnlyResponse() { var client = CreateClient(""" { "contextId": "demo-context", "locationId": "restaurant-demo", "summary": "2 tables currently require floor attention.", "assignments": [], "recentActivity": [ "Order ORD-1003 was served at table T-21 and is ready for payment capture." ] } """); var adapter = new OperationsWaiterServiceClient(client); var response = await adapter.FetchRecentActivityAsync(new GetWaiterAssignmentsRequest("demo-context"), CancellationToken.None); Assert.Equal("demo-context", response.ContextId); Assert.Single(response.RecentActivity); Assert.Contains("floor attention", response.Summary); } [Fact] public async Task SubmitOrderAsync_MapsSharedLifecycleAcceptanceResponse() { var client = CreateClient(""" { "contextId": "demo-context", "orderId": "ORD-42", "accepted": true, "summary": "Order ORD-42 was accepted and is ready for kitchen dispatch.", "status": "accepted", "submittedAtUtc": "2026-03-31T10:15:00Z" } """); var adapter = new OperationsWaiterServiceClient(client); var response = await adapter.SubmitOrderAsync(new SubmitFloorOrderRequest("demo-context", "T-12", "ORD-42", 3), CancellationToken.None); Assert.True(response.Accepted); Assert.Equal("accepted", response.Status); Assert.Equal("demo-context", response.ContextId); Assert.Contains("kitchen dispatch", response.Summary); } [Fact] public async Task UpdateOrderAsync_PrefixesSharedLifecycleUpdateSummary() { var client = CreateClient(""" { "contextId": "demo-context", "orderId": "ORD-42", "accepted": true, "summary": "Order ORD-42 was accepted and is ready for kitchen dispatch.", "status": "accepted", "submittedAtUtc": "2026-03-31T10:15:00Z" } """); var adapter = new OperationsWaiterServiceClient(client); var response = await adapter.UpdateOrderAsync(new UpdateFloorOrderRequest("demo-context", "T-12", "ORD-42", 4), CancellationToken.None); Assert.Contains("Updated order ORD-42.", response.Summary); Assert.Contains("kitchen dispatch", response.Summary); Assert.Equal("accepted", response.Status); } private static HttpClient CreateClient(string json) { return new HttpClient(new StubHttpMessageHandler(json)) { BaseAddress = new Uri("http://operations-service:8080/") }; } private sealed class StubHttpMessageHandler(string json) : HttpMessageHandler { protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(json, Encoding.UTF8, "application/json") }); } } }