Consolidated DTOs under `DocumentService.Application.Common.DTOs.Requests` to centralize and align them with the application layer. Introduced `PdfBase64RequestBase` to encapsulate shared properties, reducing redundancy across request DTOs. Updated controllers, clients, and tests to use the new DTO structure. Removed redundant DTOs and cleaned up unused namespaces and comments. Improved documentation and ensured consistent naming conventions across the codebase.
321 lines
11 KiB
C#
321 lines
11 KiB
C#
using DocumentService.Application.Common.DTOs;
|
|
using DocumentService.Application.Common.DTOs.Requests;
|
|
using FluentAssertions;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using Xunit;
|
|
|
|
namespace DocumentService.Tests.Integration.API;
|
|
|
|
public class PdfValidationControllerTests : IClassFixture<WebApplicationFactory<Program>>
|
|
{
|
|
private readonly WebApplicationFactory<Program> _factory;
|
|
private readonly HttpClient _client;
|
|
|
|
public PdfValidationControllerTests(WebApplicationFactory<Program> factory)
|
|
{
|
|
_factory = factory;
|
|
_client = _factory.CreateClient();
|
|
}
|
|
|
|
#region Base64 JSON Tests
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdf_Base64_ValidPdf_Returns200()
|
|
{
|
|
// Arrange
|
|
// Verwende ein echtes Test-PDF (embedded resource aus Unit Tests)
|
|
var assembly = typeof(PdfValidationControllerTests).Assembly;
|
|
var resourceName = "DocumentService.Tests.TestData.Pdfs.valid.pdf";
|
|
|
|
byte[] pdfBytes;
|
|
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
|
{
|
|
if (stream == null)
|
|
{
|
|
throw new InvalidOperationException($"Test resource '{resourceName}' not found");
|
|
}
|
|
|
|
using var ms = new MemoryStream();
|
|
await stream.CopyToAsync(ms);
|
|
pdfBytes = ms.ToArray();
|
|
}
|
|
|
|
var base64Pdf = Convert.ToBase64String(pdfBytes);
|
|
var request = new ValidatePdfBase64Request { Base64Pdf = base64Pdf };
|
|
|
|
// Act
|
|
var response = await _client.PostAsJsonAsync("/api/pdf/validation/validate", request);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<PdfValidationResult>();
|
|
result.Should().NotBeNull();
|
|
result!.PageCount.Should().BeGreaterThan(0);
|
|
result.FileSizeBytes.Should().BeGreaterThan(0);
|
|
result.PdfVersion.Should().NotBeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdf_Base64_InvalidBase64_Returns400()
|
|
{
|
|
// Arrange
|
|
var request = new ValidatePdfBase64Request { Base64Pdf = "invalid-base64!!!" }; // Kein gültiges Base64
|
|
|
|
// Act
|
|
var response = await _client.PostAsJsonAsync("/api/pdf/validation/validate", request);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
|
|
var problemDetails = await response.Content.ReadAsStringAsync();
|
|
// FormatException message contains "Base-64" (with hyphen)
|
|
problemDetails.Should().MatchRegex("(?i)base.?64", "should contain Base64 validation error");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdf_Base64_EmptyPdf_Returns400()
|
|
{
|
|
// Arrange
|
|
var request = new ValidatePdfBase64Request { Base64Pdf = string.Empty }; // Leerer String
|
|
|
|
// Act
|
|
var response = await _client.PostAsJsonAsync("/api/pdf/validation/validate", request);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
|
|
var problemDetails = await response.Content.ReadAsStringAsync();
|
|
// Empty Base64 causes FormatException or empty stream error
|
|
problemDetails.Should().MatchRegex("(Base64|empty|stream)", "should contain validation error message");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Multipart/Form-Data Tests
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdf_Multipart_ValidPdf_Returns200()
|
|
{
|
|
// Arrange
|
|
var assembly = typeof(PdfValidationControllerTests).Assembly;
|
|
var resourceName = "DocumentService.Tests.TestData.Pdfs.valid.pdf";
|
|
|
|
byte[] pdfBytes;
|
|
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
|
{
|
|
if (stream == null)
|
|
{
|
|
throw new InvalidOperationException($"Test resource '{resourceName}' not found");
|
|
}
|
|
|
|
using var ms = new MemoryStream();
|
|
await stream.CopyToAsync(ms);
|
|
pdfBytes = ms.ToArray();
|
|
}
|
|
|
|
// Create multipart/form-data content
|
|
using var content = new MultipartFormDataContent();
|
|
var fileContent = new ByteArrayContent(pdfBytes);
|
|
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
|
|
content.Add(fileContent, "file", "test.pdf");
|
|
|
|
// Act
|
|
var response = await _client.PostAsync("/api/pdf/validation/validate", content);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<PdfValidationResult>();
|
|
result.Should().NotBeNull();
|
|
result!.PageCount.Should().BeGreaterThan(0);
|
|
result.FileSizeBytes.Should().BeGreaterThan(0);
|
|
result.PdfVersion.Should().NotBeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdf_Multipart_EmptyFile_Returns400()
|
|
{
|
|
// Arrange
|
|
using var content = new MultipartFormDataContent();
|
|
var fileContent = new ByteArrayContent(Array.Empty<byte>());
|
|
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
|
|
content.Add(fileContent, "file", "empty.pdf");
|
|
|
|
// Act
|
|
var response = await _client.PostAsync("/api/pdf/validation/validate", content);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
|
|
var problemDetails = await response.Content.ReadAsStringAsync();
|
|
problemDetails.Should().Contain("cannot be empty");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdf_Multipart_NoFile_Returns400()
|
|
{
|
|
// Arrange
|
|
using var content = new MultipartFormDataContent();
|
|
|
|
// Act
|
|
var response = await _client.PostAsync("/api/pdf/validation/validate", content);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region PDF/A Validation Tests (Base64)
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdfA_Base64_ValidPdf_Returns200()
|
|
{
|
|
// Arrange
|
|
var assembly = typeof(PdfValidationControllerTests).Assembly;
|
|
var resourceName = "DocumentService.Tests.TestData.Pdfs.valid.pdf";
|
|
|
|
byte[] pdfBytes;
|
|
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
|
{
|
|
if (stream == null)
|
|
{
|
|
throw new InvalidOperationException($"Test resource '{resourceName}' not found");
|
|
}
|
|
|
|
using var ms = new MemoryStream();
|
|
await stream.CopyToAsync(ms);
|
|
pdfBytes = ms.ToArray();
|
|
}
|
|
|
|
var base64Pdf = Convert.ToBase64String(pdfBytes);
|
|
var request = new ValidatePdfABase64Request { Base64Pdf = base64Pdf };
|
|
|
|
// Act
|
|
var response = await _client.PostAsJsonAsync("/api/pdf/validation/validate-pdfa", request);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<PdfAValidationResult>();
|
|
result.Should().NotBeNull();
|
|
result!.IsValid.Should().BeTrue();
|
|
result.PageCount.Should().BeGreaterThan(0);
|
|
result.PdfVersion.Should().NotBeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdfA_Base64_InvalidBase64_Returns400()
|
|
{
|
|
// Arrange
|
|
var request = new ValidatePdfABase64Request { Base64Pdf = "invalid-base64!!!" };
|
|
|
|
// Act
|
|
var response = await _client.PostAsJsonAsync("/api/pdf/validation/validate-pdfa", request);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
|
|
var problemDetails = await response.Content.ReadAsStringAsync();
|
|
// FormatException message contains "Base-64" (with hyphen)
|
|
problemDetails.Should().MatchRegex("(?i)base.?64", "should contain Base64 validation error");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdfA_Base64_EmptyPdf_Returns400()
|
|
{
|
|
// Arrange
|
|
var request = new ValidatePdfABase64Request { Base64Pdf = string.Empty };
|
|
|
|
// Act
|
|
var response = await _client.PostAsJsonAsync("/api/pdf/validation/validate-pdfa", request);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
|
|
var problemDetails = await response.Content.ReadAsStringAsync();
|
|
// Empty Base64 causes FormatException or empty stream error
|
|
problemDetails.Should().MatchRegex("(Base64|empty|stream)", "should contain validation error message");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region PDF/A Validation Tests (Multipart)
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdfA_Multipart_ValidPdf_Returns200()
|
|
{
|
|
// Arrange
|
|
var assembly = typeof(PdfValidationControllerTests).Assembly;
|
|
var resourceName = "DocumentService.Tests.TestData.Pdfs.valid.pdf";
|
|
|
|
byte[] pdfBytes;
|
|
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
|
{
|
|
if (stream == null)
|
|
{
|
|
throw new InvalidOperationException($"Test resource '{resourceName}' not found");
|
|
}
|
|
|
|
using var ms = new MemoryStream();
|
|
await stream.CopyToAsync(ms);
|
|
pdfBytes = ms.ToArray();
|
|
}
|
|
|
|
// Create multipart/form-data content
|
|
using var content = new MultipartFormDataContent();
|
|
var fileContent = new ByteArrayContent(pdfBytes);
|
|
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
|
|
content.Add(fileContent, "file", "test.pdf");
|
|
|
|
// Act
|
|
var response = await _client.PostAsync("/api/pdf/validation/validate-pdfa", content);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<PdfAValidationResult>();
|
|
result.Should().NotBeNull();
|
|
result!.IsValid.Should().BeTrue();
|
|
result.PageCount.Should().BeGreaterThan(0);
|
|
result.PdfVersion.Should().NotBeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdfA_Multipart_EmptyFile_Returns400()
|
|
{
|
|
// Arrange
|
|
using var content = new MultipartFormDataContent();
|
|
var fileContent = new ByteArrayContent(Array.Empty<byte>());
|
|
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
|
|
content.Add(fileContent, "file", "empty.pdf");
|
|
|
|
// Act
|
|
var response = await _client.PostAsync("/api/pdf/validation/validate-pdfa", content);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
|
|
var problemDetails = await response.Content.ReadAsStringAsync();
|
|
problemDetails.Should().Contain("cannot be empty");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task POST_ValidatePdfA_Multipart_NoFile_Returns400()
|
|
{
|
|
// Arrange
|
|
using var content = new MultipartFormDataContent();
|
|
|
|
// Act
|
|
var response = await _client.PostAsync("/api/pdf/validation/validate-pdfa", content);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
|
|
}
|
|
|
|
#endregion
|
|
}
|