using DocumentOperator.Application.Common.DTOs; using DocumentOperator.Application.SwissQrCode.Queries; using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; using System.Net; using System.Net.Http.Json; using System.Text.Json; using Xunit; namespace DocumentOperator.Tests.Integration.API; public sealed class ExtractSwissQrCodeEndpointTests : IClassFixture> { private readonly HttpClient _client; private readonly JsonSerializerOptions _jsonOptions; public ExtractSwissQrCodeEndpointTests(WebApplicationFactory factory) { _client = factory.CreateClient(); _jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; } [Fact] public async Task POST_ExtractSwissQrCode_ValidRequest_Returns200() { // Arrange var validPdfBase64 = GetEmbeddedResourceAsBase64("DocumentOperator.Tests.TestData.Pdfs.valid.pdf"); var request = new ExtractSwissQrCodeQuery { Base64Pdf = validPdfBase64 }; // Act var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request); // Assert // Note: The test PDF (valid.pdf) may not actually contain a Swiss QR Code // so this test might return 404. We're testing the endpoint wiring here. // A real test would need a PDF with a Swiss QR Code on the last page. response.StatusCode.Should().BeOneOf(HttpStatusCode.OK, HttpStatusCode.NotFound); if (response.StatusCode == HttpStatusCode.OK) { var result = await response.Content.ReadFromJsonAsync(_jsonOptions); result.Should().NotBeNull(); result.Bill.Should().NotBeNull(); result.RawLines.Should().NotBeEmpty(); } } [Fact] public async Task POST_ExtractSwissQrCode_InvalidBase64_Returns400() { // Arrange var request = new ExtractSwissQrCodeQuery { Base64Pdf = "INVALID_BASE64!!!" }; // Act var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request); // Assert response.StatusCode.Should().Be(HttpStatusCode.BadRequest); } [Fact] public async Task POST_ExtractSwissQrCode_NullReferences_AcceptedByValidation() { // Arrange: References are OPTIONAL - null should not cause validation error (400) // Using pdfWithSwissQRCode.pdf which actually has a QR code, so we get 200 var validPdfBase64 = GetEmbeddedResourceAsBase64("DocumentOperator.Tests.TestData.Pdfs.pdfWithSwissQRCode.pdf"); var request = new { References = (List?)null, // Optional field - should not cause 400 Base64Pdf = validPdfBase64 }; // Act var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request); // Assert: Should NOT be 400 (validation error), should be 200 or 404 response.StatusCode.Should().NotBe(HttpStatusCode.BadRequest, "null References should be accepted (optional field)"); // If extraction succeeds, verify empty references array if (response.StatusCode == HttpStatusCode.OK) { var result = await response.Content.ReadFromJsonAsync(); result.Should().NotBeNull(); } } [Fact] public async Task POST_ExtractSwissQrCode_EmptyPdf_Returns400() { // Arrange var request = new { References = new List { "REF-001" }, Base64Pdf = (string?)null }; // Act var response = await _client.PostAsJsonAsync("/api/pdf/qr-code/extract-swiss", request); // Assert response.StatusCode.Should().Be(HttpStatusCode.BadRequest); } /// /// Helper method to load embedded resource as Base64 string /// private static string GetEmbeddedResourceAsBase64(string resourceName) { var assembly = typeof(ExtractSwissQrCodeEndpointTests).Assembly; using var stream = assembly.GetManifestResourceStream(resourceName); if (stream == null) { throw new FileNotFoundException($"Embedded resource not found: {resourceName}"); } using var memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return Convert.ToBase64String(memoryStream.ToArray()); } }