using System.Net.Http; using Yavsc.Api.Client; namespace PostIt.Tests; /// /// Verifies issues the right /// api/v1/front/query/accept / .../reject requests with /// the PostIt signature payload, using a recording fake /// (no network). /// public class FrontOfficeApiClientTests { private static QueryAcceptanceRequestDto SampleBody() => new() { Strokes = new[] { 2, 100, 200, 300, 400 }, CoordinateMax = 10_000, CapturedAtUtc = new DateTime(2026, 9, 21, 12, 0, 0, DateTimeKind.Utc), }; [Fact] public async Task Accept_posts_to_accept_endpoint_with_signature_body() { var api = new RecordingApi(); var client = new FrontOfficeApiClient(api, "https://business.example/api/v1/"); var body = SampleBody(); await client.AcceptQueryAsync("Rdv", 42, body); Assert.Equal(HttpMethod.Post, api.LastMethod); Assert.Equal( "https://business.example/api/v1/front/query/accept?billingCode=Rdv&queryId=42", api.LastPath); Assert.Same(body, api.LastBody); } [Fact] public async Task Reject_posts_to_reject_endpoint_with_no_body() { var api = new RecordingApi(); var client = new FrontOfficeApiClient(api, "https://business.example/api/v1/"); await client.RejectQueryAsync("Rdv", 42); Assert.Equal(HttpMethod.Post, api.LastMethod); Assert.Equal( "https://business.example/api/v1/front/query/reject?billingCode=Rdv&queryId=42", api.LastPath); Assert.Null(api.LastBody); } [Fact] public async Task Accept_returns_deserialized_response() { var api = new RecordingApi { Response = new QueryAcceptanceResponseDto { QueryId = 42, Status = "Accepted", Signature = new QuerySignatureRefDto { Id = 9, EstimateId = 5, Type = "Pro" }, }, }; var client = new FrontOfficeApiClient(api, "https://business.example/api/v1/"); var response = await client.AcceptQueryAsync("Rdv", 42, SampleBody()); Assert.Equal(42, response.QueryId); Assert.Equal("Accepted", response.Status); Assert.NotNull(response.Signature); Assert.Equal("Pro", response.Signature!.Type); } [Fact] public async Task Accept_rejects_invalid_arguments() { var api = new RecordingApi(); var client = new FrontOfficeApiClient(api, "https://business.example/api/v1/"); await Assert.ThrowsAsync(() => client.AcceptQueryAsync("", 42, SampleBody())); await Assert.ThrowsAsync(() => client.AcceptQueryAsync("Rdv", 0, SampleBody())); await Assert.ThrowsAsync(() => client.AcceptQueryAsync("Rdv", 42, null!)); await Assert.ThrowsAsync(() => client.RejectQueryAsync("", 42)); await Assert.ThrowsAsync(() => client.RejectQueryAsync("Rdv", 0)); } private sealed class RecordingApi : IYavscApiClient { public HttpClient Http { get; } = new(); public HttpMethod? LastMethod { get; private set; } public string? LastPath { get; private set; } public object? LastBody { get; private set; } public QueryAcceptanceResponseDto? Response { get; set; } public Task CallAsync(HttpMethod method, string path, object? body = null, CancellationToken ct = default) { LastMethod = method; LastPath = path; LastBody = body; var response = Response ?? new QueryAcceptanceResponseDto(); return Task.FromResult((T)(object)response); } public Task CallAsync(HttpMethod method, string path, object? body = null, CancellationToken ct = default) { LastMethod = method; LastPath = path; LastBody = body; return Task.CompletedTask; } public Task CallAsync(HttpMethod method, string path, Func contentFactory, CancellationToken ct = default) => CallAsync(method, path, (object?)null, ct); public Task CallAsync(HttpMethod method, string path, Func contentFactory, CancellationToken ct = default) => CallAsync(method, path, (object?)null, ct); public ValueTask DisposeAsync() => ValueTask.CompletedTask; } }