using DocumentService.Application.Common.DTOs; using DocumentService.Client.Clients; using DocumentService.Client.Interfaces; using FluentAssertions; using Microsoft.Extensions.Logging.Abstractions; using System.Net; using System.Net.Http; using System.Text.Json; namespace DocumentService.Tests.Unit.Client; /// /// Unit tests for . /// All tests use a fake — no real HTTP calls are made. /// public class SwissQrCodeClientTests { // ?? helpers ???????????????????????????????????????????????????????????? private static (SwissQrCodeClient client, MockHttpMessageHandler handler) Build(T body) { var handler = MockHttpMessageHandler.ReturningJson(body); var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") }; var client = new SwissQrCodeClient(httpClient, NullLogger.Instance); return (client, handler); } private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray(); // ?? ExtractSwissQrCodeAsync (Stream) — parsed Bill ?????????????????????? [Fact] public async Task ExtractSwissQrCodeAsync_Stream_ParsedMode_SendsMultipartToCorrectEndpoint() { // Arrange var expected = new SwissQrCodeExtractionResult( Bill: new SwissQrBillDto { Version = "V2_0", Currency = "CHF", Account = "CH9300762011623852957", Creditor = new AddressDto { Name = "Test AG", Town = "Bern", CountryCode = "CH", Type = "S", PostalCode = "3000" }, ReferenceType = "NON" }, RawLines: [] ); var (client, handler) = Build(expected); // Act var result = await client.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()), raw: false); // Assert result.Should().NotBeNull(); handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=False"); handler.LastRequest.Content.Should().BeOfType(); } [Fact] public async Task ExtractSwissQrCodeAsync_Stream_RawMode_SendsRawFlagInUrl() { // Arrange var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: ["SPC", "0200", "1"]); var (client, handler) = Build(expected); // Act var result = await client.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()), raw: true); // Assert result.RawLines.Should().HaveCount(3).And.StartWith("SPC"); handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=True"); } // ?? ExtractSwissQrCodeAsync (byte[]) ???????????????????????????????????? [Fact] public async Task ExtractSwissQrCodeAsync_Bytes_SendsJsonWithBase64() { // Arrange var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: []); var (client, handler) = Build(expected); // Act await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: false); // Assert handler.LastRequest!.Content.Should().NotBeNull(); handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json"); var body = await handler.LastRequest.Content!.ReadAsStringAsync(); var doc = JsonDocument.Parse(body); doc.RootElement.GetProperty("base64Pdf").GetString().Should().NotBeNullOrEmpty(); } [Fact] public async Task ExtractSwissQrCodeAsync_Bytes_RawMode_IncludesRawFlagInUrl() { // Arrange var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: ["SPC"]); var (client, handler) = Build(expected); // Act await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: true); // Assert handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=True"); } // ?? HTTP error propagation ?????????????????????????????????????????????? [Fact] public async Task ExtractSwissQrCodeAsync_WhenApiReturns404_ThrowsHttpRequestException() { // Arrange var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.NotFound); var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") }; var client = new SwissQrCodeClient(httpClient, NullLogger.Instance); // Act & Assert await client.Invoking(c => c.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()))) .Should().ThrowAsync(); } [Fact] public async Task ExtractSwissQrCodeAsync_WhenApiReturns500_ThrowsHttpRequestException() { // Arrange var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.InternalServerError); var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") }; var client = new SwissQrCodeClient(httpClient, NullLogger.Instance); // Act & Assert await client.Invoking(c => c.ExtractSwissQrCodeAsync(FakePdfBytes())) .Should().ThrowAsync(); } }