Updated project and solution files to rename and restructure `DocumentOperator` to `DocumentService`. Modified project references in `DocumentService.API.csproj`, `DocumentService.Application.csproj`, and `DocumentService.Infrastructure.csproj` to reflect the new naming convention. Updated `DocumentService.sln` to remove old project references, add new ones, and adjust configuration and nested project mappings accordingly. This change aligns the project structure with the new naming convention.
130 lines
5.0 KiB
C#
130 lines
5.0 KiB
C#
using DocumentService.Application.Common.DTOs;
|
|
using DocumentService.Application.Common.Interfaces;
|
|
using DocumentService.Application.ValidatePdfA.Queries;
|
|
using DocumentService.Domain.Common.Exceptions;
|
|
using FluentAssertions;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace DocumentService.Tests.Unit.Application.Features.ValidatePdfA;
|
|
|
|
public class ValidatePdfAQueryHandlerTests
|
|
{
|
|
private readonly Mock<IPdfProcessor> _mockPdfProcessor;
|
|
private readonly ValidatePdfAQueryHandler _handler;
|
|
|
|
public ValidatePdfAQueryHandlerTests()
|
|
{
|
|
_mockPdfProcessor = new Mock<IPdfProcessor>();
|
|
_handler = new ValidatePdfAQueryHandler(_mockPdfProcessor.Object);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Handle_ValidCompliantPdfA_ReturnsCompliantResult()
|
|
{
|
|
// Arrange
|
|
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
|
|
var expected = new PdfAValidationResult
|
|
{
|
|
IsValid = true, PdfVersion = "1.7", PageCount = 3, FileSize = 2048,
|
|
Encrypted = false, PdfAVersion = "PDF/A-3b", PdfACompliant = true,
|
|
Errors = [], Warnings = []
|
|
};
|
|
|
|
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>())).ReturnsAsync(expected);
|
|
|
|
// Act
|
|
var result = await _handler.Handle(query, CancellationToken.None);
|
|
|
|
// Assert
|
|
result.IsValid.Should().BeTrue();
|
|
result.PageCount.Should().Be(3);
|
|
result.PdfVersion.Should().Be("1.7");
|
|
result.PdfAVersion.Should().Be("PDF/A-3b");
|
|
result.PdfACompliant.Should().BeTrue();
|
|
result.Encrypted.Should().BeFalse();
|
|
result.Errors.Should().BeEmpty();
|
|
result.Warnings.Should().BeEmpty();
|
|
_mockPdfProcessor.Verify(x => x.ValidatePdfAAsync(It.IsAny<Stream>()), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Handle_NonCompliantPdfA_ReturnsErrorsAndWarnings()
|
|
{
|
|
// Arrange
|
|
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
|
|
var expected = new PdfAValidationResult
|
|
{
|
|
IsValid = false, PdfVersion = "1.4", PageCount = 2, FileSize = 1024,
|
|
Encrypted = false, PdfAVersion = null, PdfACompliant = false,
|
|
Errors = ["Missing XMP metadata", "Invalid color space"],
|
|
Warnings = ["Embedded font not subset"]
|
|
};
|
|
|
|
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>())).ReturnsAsync(expected);
|
|
|
|
// Act
|
|
var result = await _handler.Handle(query, CancellationToken.None);
|
|
|
|
// Assert
|
|
result.IsValid.Should().BeFalse();
|
|
result.PdfACompliant.Should().BeFalse();
|
|
result.PdfAVersion.Should().BeNull();
|
|
result.Errors.Should().HaveCount(2).And.Contain("Missing XMP metadata").And.Contain("Invalid color space");
|
|
result.Warnings.Should().HaveCount(1).And.Contain("Embedded font not subset");
|
|
_mockPdfProcessor.Verify(x => x.ValidatePdfAAsync(It.IsAny<Stream>()), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Handle_EncryptedPdf_ReturnsEncryptedFlagAndErrors()
|
|
{
|
|
// Arrange
|
|
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
|
|
var expected = new PdfAValidationResult
|
|
{
|
|
IsValid = false, PdfVersion = "1.7", PageCount = 1, FileSize = 512,
|
|
Encrypted = true, PdfAVersion = null, PdfACompliant = false,
|
|
Errors = ["PDF/A documents cannot be encrypted"],
|
|
Warnings = []
|
|
};
|
|
|
|
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>())).ReturnsAsync(expected);
|
|
|
|
// Act
|
|
var result = await _handler.Handle(query, CancellationToken.None);
|
|
|
|
// Assert
|
|
result.Encrypted.Should().BeTrue();
|
|
result.IsValid.Should().BeFalse();
|
|
result.PdfACompliant.Should().BeFalse();
|
|
result.Errors.Should().Contain("PDF/A documents cannot be encrypted");
|
|
_mockPdfProcessor.Verify(x => x.ValidatePdfAAsync(It.IsAny<Stream>()), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Handle_ProcessorThrowsBadRequest_PropagatesException()
|
|
{
|
|
// Arrange
|
|
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
|
|
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
|
|
.ThrowsAsync(new BadRequestException("Invalid PDF format"));
|
|
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BadRequestException>(
|
|
() => _handler.Handle(query, CancellationToken.None));
|
|
ex.Message.Should().Be("Invalid PDF format");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Handle_ProcessorThrowsGenericException_PropagatesException()
|
|
{
|
|
// Arrange
|
|
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
|
|
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
|
|
.ThrowsAsync(new Exception("Unexpected processing error"));
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<Exception>(() => _handler.Handle(query, CancellationToken.None));
|
|
}
|
|
}
|