using DocumentService.Application.Common.Interfaces; using DocumentService.Application.ConvertToPdfA; using DocumentService.Application.ConvertFromPdfA; using DocumentService.Domain.Common.Exceptions; using FluentAssertions; using Moq; using Xunit; namespace DocumentService.Tests.Unit.Application.Features.ConvertPdfA; public class ConvertToPdfAHandlerTests { private readonly Mock _mockProcessor; private readonly ConvertToPdfACommandHandler _handler; private static readonly byte[] FakePdfBytes = "%PDF"u8.ToArray(); public ConvertToPdfAHandlerTests() { _mockProcessor = new Mock(); _handler = new ConvertToPdfACommandHandler(_mockProcessor.Object); } [Fact] public async Task Handle_ValidPdfAndLevel_ReturnsConvertedBytes() { // Arrange var command = new ConvertToPdfACommand { PdfStream = new MemoryStream(FakePdfBytes), PdfALevel = "PDF/A-3b" }; var expected = new byte[] { 0x25, 0x50, 0x44, 0x46, 0x0A }; _mockProcessor.Setup(x => x.ConvertToPdfAAsync(It.IsAny(), "PDF/A-3b")).ReturnsAsync(expected); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.Should().BeEquivalentTo(expected); _mockProcessor.Verify(x => x.ConvertToPdfAAsync(It.IsAny(), "PDF/A-3b"), Times.Once); } [Fact] public async Task Handle_ProcessorThrowsNotImplemented_PropagatesException() { // Arrange var command = new ConvertToPdfACommand { PdfStream = new MemoryStream(FakePdfBytes), PdfALevel = "PDF/A-1b" }; _mockProcessor.Setup(x => x.ConvertToPdfAAsync(It.IsAny(), "PDF/A-1b")) .ThrowsAsync(new NotImplementedException("PDF/A conversion not yet implemented")); // Act & Assert var ex = await Assert.ThrowsAsync( () => _handler.Handle(command, CancellationToken.None)); ex.Message.Should().Contain("not yet implemented"); } [Fact] public async Task Handle_ProcessorThrowsBadRequest_PropagatesException() { // Arrange var command = new ConvertToPdfACommand { PdfStream = new MemoryStream(FakePdfBytes), PdfALevel = "PDF/A-2b" }; _mockProcessor.Setup(x => x.ConvertToPdfAAsync(It.IsAny(), "PDF/A-2b")) .ThrowsAsync(new BadRequestException("PDF stream cannot be empty")); // Act & Assert var ex = await Assert.ThrowsAsync( () => _handler.Handle(command, CancellationToken.None)); ex.Message.Should().Contain("empty"); } } public class ConvertFromPdfAHandlerTests { private readonly Mock _mockProcessor; private readonly ConvertFromPdfACommandHandler _handler; private static readonly byte[] FakePdfBytes = "%PDF"u8.ToArray(); public ConvertFromPdfAHandlerTests() { _mockProcessor = new Mock(); _handler = new ConvertFromPdfACommandHandler(_mockProcessor.Object); } [Fact] public async Task Handle_ValidPdfA_ReturnsStandardPdfBytes() { // Arrange var command = new ConvertFromPdfACommand { PdfStream = new MemoryStream(FakePdfBytes) }; var expected = new byte[] { 0x25, 0x50, 0x44, 0x46, 0x0B }; _mockProcessor.Setup(x => x.ConvertFromPdfAAsync(It.IsAny())).ReturnsAsync(expected); // Act var result = await _handler.Handle(command, CancellationToken.None); // Assert result.Should().BeEquivalentTo(expected); _mockProcessor.Verify(x => x.ConvertFromPdfAAsync(It.IsAny()), Times.Once); } [Fact] public async Task Handle_ProcessorThrowsBadRequest_PropagatesException() { // Arrange var command = new ConvertFromPdfACommand { PdfStream = new MemoryStream(FakePdfBytes) }; _mockProcessor.Setup(x => x.ConvertFromPdfAAsync(It.IsAny())) .ThrowsAsync(new BadRequestException("PDF stream must be at position 0")); // Act & Assert var ex = await Assert.ThrowsAsync( () => _handler.Handle(command, CancellationToken.None)); ex.Message.Should().Contain("position 0"); } [Fact] public async Task Handle_ProcessorThrowsGenericException_PropagatesException() { // Arrange var command = new ConvertFromPdfACommand { PdfStream = new MemoryStream(FakePdfBytes) }; _mockProcessor.Setup(x => x.ConvertFromPdfAAsync(It.IsAny())) .ThrowsAsync(new Exception("Unexpected error")); // Act & Assert await Assert.ThrowsAsync(() => _handler.Handle(command, CancellationToken.None)); } }