using System.Net; using System.Text; using Pos.Transactions.Bff.Application.Adapters; using Pos.Transactions.Bff.Contracts.Requests; namespace Pos.Transactions.Bff.Application.UnitTests; public sealed class OperationsPosTransactionsServiceClientTests { [Fact] public async Task FetchSummaryAsync_MapsBalanceCurrencyAndPayments() { var adapter = new OperationsPosTransactionsServiceClient(CreateClient(SummaryPayload)); var response = await adapter.FetchSummaryAsync(new GetPosTransactionSummaryRequest("demo-context"), CancellationToken.None); Assert.Equal(37.50m, response.OpenBalance); Assert.Equal("USD", response.Currency); Assert.Equal(2, response.RecentPayments.Count); } [Fact] public async Task FetchDetailAsync_ReturnsMatchingTransactionWhenPresent() { var adapter = new OperationsPosTransactionsServiceClient(CreateClient(SummaryPayload)); var response = await adapter.FetchDetailAsync(new GetPosTransactionDetailRequest("demo-context", "POS-9001"), CancellationToken.None); Assert.NotNull(response.Transaction); Assert.Equal("POS-9001", response.Transaction!.TransactionId); } [Fact] public async Task FetchRecentPaymentsAsync_ReturnsProjectedPaymentHistory() { var adapter = new OperationsPosTransactionsServiceClient(CreateClient(SummaryPayload)); var response = await adapter.FetchRecentPaymentsAsync(new GetPosTransactionSummaryRequest("demo-context"), CancellationToken.None); Assert.Equal(2, response.RecentPayments.Count); } [Fact] public async Task CapturePaymentAsync_MapsCaptureWorkflowPayload() { var adapter = new OperationsPosTransactionsServiceClient(CreateClient(""" { "contextId": "demo-context", "transactionId": "POS-9003", "succeeded": true, "summary": "Captured 19.95 USD using card.", "status": "captured", "capturedAtUtc": "2026-03-31T14:05:00Z" } """)); var response = await adapter.CapturePaymentAsync( new CapturePosPaymentRequest("demo-context", "POS-9003", 19.95m, "USD", "card"), CancellationToken.None); Assert.True(response.Succeeded); Assert.Equal("captured", 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") }); } } private const string SummaryPayload = """ { "contextId": "demo-context", "summary": "Open POS balance reflects one captured payment and one pending settlement.", "openBalance": 37.50, "currency": "USD", "recentPayments": [ { "transactionId": "POS-9001", "paymentMethod": "card", "amount": 25.50, "currency": "USD", "status": "captured", "capturedAtUtc": "2026-03-31T13:30:00Z" }, { "transactionId": "POS-9002", "paymentMethod": "wallet", "amount": 12.00, "currency": "USD", "status": "pending", "capturedAtUtc": "2026-03-31T13:42:00Z" } ] } """; }