diff --git a/DocumentOperator.Tests/Unit/Client/PdfValidationClientTests.cs b/DocumentOperator.Tests/Unit/Client/PdfValidationClientTests.cs
index dedca82..761bfa0 100644
--- a/DocumentOperator.Tests/Unit/Client/PdfValidationClientTests.cs
+++ b/DocumentOperator.Tests/Unit/Client/PdfValidationClientTests.cs
@@ -1,168 +1,183 @@
using DocumentService.Client.Clients;
using DocumentService.Client.Interfaces;
-using DocumentService.Client.Models.Requests;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using System.Net;
using System.Net.Http;
using System.Text.Json;
+using Xunit;
namespace DocumentService.Tests.Unit.Client;
-///
-/// Unit tests for .
-/// All tests use a fake — no real HTTP calls are made.
-///
public class PdfValidationClientTests
{
- // ?? helpers ?????????????????????????????????????????????????????????????
-
private static (PdfValidationClient client, MockHttpMessageHandler handler) Build(T responseBody)
{
var handler = MockHttpMessageHandler.ReturningJson(responseBody);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
- var client = new PdfValidationClient(httpClient, NullLogger.Instance);
- return (client, handler);
+ return (new PdfValidationClient(httpClient, NullLogger.Instance), handler);
}
- private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
+ private static (PdfValidationClient client, MockHttpMessageHandler handler) BuildError(HttpStatusCode code)
+ {
+ var handler = MockHttpMessageHandler.ReturningStatus(code);
+ var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
+ return (new PdfValidationClient(httpClient, NullLogger.Instance), handler);
+ }
- // ?? ValidatePdfAsync (Stream) ????????????????????????????????????????????
+ private static byte[] FakePdfBytes() => "fake-pdf"u8.ToArray();
+
+ // ── ValidatePdfAsync (Stream) ────────────────────────────────────────────
[Fact]
public async Task ValidatePdfAsync_Stream_SendsMultipartPost()
{
- // Arrange
- var expected = new PdfValidationResult { PageCount = 3, PdfVersion = "1.7", FileSizeBytes = 2048 };
+ var expected = new PdfValidationResult { PageCount = 3, PdfVersion = "1.7", FileSizeBytes = 2048, IsEncrypted = false };
var (client, handler) = Build(expected);
- // Act
var result = await client.ValidatePdfAsync(new MemoryStream(FakePdfBytes()));
- // Assert
result.PageCount.Should().Be(3);
result.PdfVersion.Should().Be("1.7");
+ result.FileSizeBytes.Should().Be(2048);
+ result.IsEncrypted.Should().BeFalse();
handler.LastRequest!.Method.Should().Be(HttpMethod.Post);
handler.LastRequest.RequestUri!.PathAndQuery.Should().Be("/api/pdf/validation/validate");
handler.LastRequest.Content.Should().BeOfType();
}
+ [Fact]
+ public async Task ValidatePdfAsync_Stream_EncryptedPdf_DeserializesIsEncryptedTrue()
+ {
+ var expected = new PdfValidationResult { PageCount = 1, IsEncrypted = true, PdfVersion = "1.6" };
+ var (client, _) = Build(expected);
+
+ var result = await client.ValidatePdfAsync(new MemoryStream(FakePdfBytes()));
+
+ result.IsEncrypted.Should().BeTrue("encrypted PDFs should surface IsEncrypted=true");
+ }
+
[Fact]
public async Task ValidatePdfAsync_Stream_ThrowsWhenApiReturnsNull()
{
- // Arrange — API returns JSON null
var handler = MockHttpMessageHandler.ReturningJson(null);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new PdfValidationClient(httpClient, NullLogger.Instance);
- // Act & Assert
await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync();
}
- // ?? ValidatePdfAsync (byte[]) ????????????????????????????????????????????
+ [Fact]
+ public async Task ValidatePdfAsync_Stream_WhenApiReturns400_ThrowsHttpRequestException()
+ {
+ var (client, _) = BuildError(HttpStatusCode.BadRequest);
+ await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
+ .Should().ThrowAsync();
+ }
+
+ [Fact]
+ public async Task ValidatePdfAsync_Stream_WhenApiReturns500_ThrowsHttpRequestException()
+ {
+ var (client, _) = BuildError(HttpStatusCode.InternalServerError);
+ await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
+ .Should().ThrowAsync();
+ }
+
+ // ── ValidatePdfAsync (byte[]) ────────────────────────────────────────────
[Fact]
public async Task ValidatePdfAsync_Bytes_SendsJsonWithBase64()
{
- // Arrange
- var expected = new PdfValidationResult { PageCount = 1, IsEncrypted = false };
+ var expected = new PdfValidationResult { PageCount = 1, IsEncrypted = false, HasAttachments = true, AttachmentCount = 2 };
var (client, handler) = Build(expected);
- // Act
var result = await client.ValidatePdfAsync(FakePdfBytes());
- // Assert
result.PageCount.Should().Be(1);
- handler.LastRequest!.Content.Should().NotBeNull();
- handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json");
-
+ result.HasAttachments.Should().BeTrue();
+ result.AttachmentCount.Should().Be(2);
+ 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();
}
- // ?? ValidatePdfAAsync (Stream) ???????????????????????????????????????????
+ [Fact]
+ public async Task ValidatePdfAsync_Bytes_WhenApiReturns400_ThrowsHttpRequestException()
+ {
+ var (client, _) = BuildError(HttpStatusCode.BadRequest);
+ await client.Invoking(c => c.ValidatePdfAsync(FakePdfBytes()))
+ .Should().ThrowAsync();
+ }
+
+ // ── ValidatePdfAAsync (Stream) ───────────────────────────────────────────
[Fact]
- public async Task ValidatePdfAAsync_Stream_SendsMultipartPost()
+ public async Task ValidatePdfAAsync_Stream_DeserializesAllFields()
{
- // Arrange
- var expected = new PdfAValidationResult { IsValid = true, PdfAVersion = "PDF/A-3b", PageCount = 2 };
+ var expected = new PdfAValidationResult
+ {
+ IsValid = true, PdfAVersion = "PDF/A-3b", PageCount = 2,
+ Errors = [], Warnings = []
+ };
var (client, handler) = Build(expected);
- // Act
var result = await client.ValidatePdfAAsync(new MemoryStream(FakePdfBytes()));
- // Assert
result.IsValid.Should().BeTrue();
result.PdfAVersion.Should().Be("PDF/A-3b");
+ result.PageCount.Should().Be(2);
+ result.Errors.Should().BeEmpty();
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/validation/validate-pdfa");
handler.LastRequest.Content.Should().BeOfType();
}
[Fact]
- public async Task ValidatePdfAAsync_Stream_WithErrors_ReturnsErrors()
+ public async Task ValidatePdfAAsync_Stream_NonCompliant_ReturnsErrors()
{
- // Arrange
var expected = new PdfAValidationResult
{
IsValid = false,
- Errors = new List { "Missing embedded font", "Encryption not allowed" }
+ Errors = ["Missing embedded font", "Encryption not allowed"],
+ Warnings = ["Manual verification recommended"]
};
var (client, _) = Build(expected);
- // Act
var result = await client.ValidatePdfAAsync(new MemoryStream(FakePdfBytes()));
- // Assert
result.IsValid.Should().BeFalse();
result.Errors.Should().HaveCount(2).And.Contain("Missing embedded font");
+ result.Warnings.Should().HaveCount(1);
}
- // ?? ValidatePdfAAsync (byte[]) ???????????????????????????????????????????
+ [Fact]
+ public async Task ValidatePdfAAsync_Stream_WhenApiReturns400_ThrowsHttpRequestException()
+ {
+ var (client, _) = BuildError(HttpStatusCode.BadRequest);
+ await client.Invoking(c => c.ValidatePdfAAsync(new MemoryStream(FakePdfBytes())))
+ .Should().ThrowAsync();
+ }
+
+ // ── ValidatePdfAAsync (byte[]) ───────────────────────────────────────────
[Fact]
- public async Task ValidatePdfAAsync_Bytes_SendsJson()
+ public async Task ValidatePdfAAsync_Bytes_SendsJsonToCorrectEndpoint()
{
- // Arrange
var expected = new PdfAValidationResult { IsValid = true };
var (client, handler) = Build(expected);
- // Act
await client.ValidatePdfAAsync(FakePdfBytes());
- // Assert
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/validation/validate-pdfa");
- handler.LastRequest.Content.Should().NotBeNull();
handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json");
}
- // ?? HTTP error propagation ???????????????????????????????????????????????
-
[Fact]
- public async Task ValidatePdfAsync_WhenApiReturns400_ThrowsHttpRequestException()
+ public async Task ValidatePdfAAsync_Bytes_WhenApiReturns500_ThrowsHttpRequestException()
{
- // Arrange
- var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.BadRequest);
- var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
- var client = new PdfValidationClient(httpClient, NullLogger.Instance);
-
- // Act & Assert
- await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
- .Should().ThrowAsync();
- }
-
- [Fact]
- public async Task ValidatePdfAsync_WhenApiReturns500_ThrowsHttpRequestException()
- {
- // Arrange
- var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.InternalServerError);
- var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
- var client = new PdfValidationClient(httpClient, NullLogger.Instance);
-
- // Act & Assert
- await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
+ var (client, _) = BuildError(HttpStatusCode.InternalServerError);
+ await client.Invoking(c => c.ValidatePdfAAsync(FakePdfBytes()))
.Should().ThrowAsync();
}
}