Refactor: Rename DocumentOperator to DocumentService

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.
This commit is contained in:
2026-08-30 21:33:25 +02:00
parent 050cb55bf9
commit 207c778f3a
108 changed files with 37 additions and 37 deletions

View File

@@ -0,0 +1,199 @@
using DocumentService.Client.Clients;
using DocumentService.Client.Interfaces;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using System.Net;
using System.Net.Http;
using System.Text.Json;
namespace DocumentService.Tests.Unit.Client;
/// <summary>
/// Unit tests for <see cref="ZugferdClient"/>.
/// All tests use a fake <see cref="MockHttpMessageHandler"/> — no real HTTP calls are made.
/// </summary>
public class ZugferdClientTests
{
// ?? helpers ?????????????????????????????????????????????????????????????
private static (ZugferdClient client, MockHttpMessageHandler handler) BuildJson<T>(T body)
{
var handler = MockHttpMessageHandler.ReturningJson(body);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new ZugferdClient(httpClient, NullLogger<ZugferdClient>.Instance);
return (client, handler);
}
private static (ZugferdClient client, MockHttpMessageHandler handler) BuildBytes(byte[] bytes, string mediaType = "application/xml")
{
var handler = MockHttpMessageHandler.ReturningBytes(bytes, mediaType);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new ZugferdClient(httpClient, NullLogger<ZugferdClient>.Instance);
return (client, handler);
}
private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
private static byte[] FakeXmlBytes() => "<invoice>test</invoice>"u8.ToArray();
// ?? HasZugferdAsync (Stream) ?????????????????????????????????????????????
[Fact]
public async Task HasZugferdAsync_Stream_WhenZugferdPresent_ReturnsTrue()
{
// Arrange
var expected = new ZugferdCheckResult { HasZugferd = true, Version = "2.1", Profile = "EN 16931" };
var (client, handler) = BuildJson(expected);
// Act
var result = await client.HasZugferdAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.HasZugferd.Should().BeTrue();
result.Version.Should().Be("2.1");
result.Profile.Should().Be("EN 16931");
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/has-zugferd");
handler.LastRequest.Content.Should().BeOfType<MultipartFormDataContent>();
}
[Fact]
public async Task HasZugferdAsync_Stream_WhenNoZugferd_ReturnsFalse()
{
// Arrange
var expected = new ZugferdCheckResult { HasZugferd = false };
var (client, _) = BuildJson(expected);
// Act
var result = await client.HasZugferdAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.HasZugferd.Should().BeFalse();
result.Version.Should().BeNull();
}
// ?? HasZugferdAsync (byte[]) ?????????????????????????????????????????????
[Fact]
public async Task HasZugferdAsync_Bytes_SendsJsonWithBase64()
{
// Arrange
var expected = new ZugferdCheckResult { HasZugferd = true };
var (client, handler) = BuildJson(expected);
// Act
await client.HasZugferdAsync(FakePdfBytes());
// Assert
handler.LastRequest!.Content.Should().NotBeNull();
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();
}
// ?? ExtractZugferdAsync (Stream) — raw XML stream ?????????????????????????
[Fact]
public async Task ExtractZugferdAsync_Stream_SendsMultipartWithAsFileTrue()
{
// Arrange
var (client, handler) = BuildBytes(FakeXmlBytes());
// Act
using var result = await client.ExtractZugferdAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.Should().NotBeNull();
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?asFile=true");
handler.LastRequest.Content.Should().BeOfType<MultipartFormDataContent>();
}
[Fact]
public async Task ExtractZugferdAsync_Stream_ReturnsXmlContent()
{
// Arrange
var xmlBytes = "<root><invoice/></root>"u8.ToArray();
var (client, _) = BuildBytes(xmlBytes);
// Act
using var result = await client.ExtractZugferdAsync(new MemoryStream(FakePdfBytes()));
var content = await new StreamReader(result).ReadToEndAsync();
// Assert
content.Should().Be("<root><invoice/></root>");
}
// ?? ExtractZugferdAsync (byte[]) ?????????????????????????????????????????
[Fact]
public async Task ExtractZugferdAsync_Bytes_SendsJsonWithFormatFile()
{
// Arrange
var (client, handler) = BuildBytes(FakeXmlBytes());
// Act
using var result = await client.ExtractZugferdAsync(FakePdfBytes());
// Assert
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?format=file");
handler.LastRequest.Content.Should().NotBeNull();
handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json");
}
// ?? ExtractZugferdAsResultAsync (Stream) ?????????????????????????????????
[Fact]
public async Task ExtractZugferdAsResultAsync_Stream_ReturnsStructuredResult()
{
// Arrange
var expected = new ZugferdExtractionResult
{
FileName = "factur-x.xml",
XmlContent = "<invoice/>",
Version = "2.1",
Profile = "EN 16931"
};
var (client, handler) = BuildJson(expected);
// Act
var result = await client.ExtractZugferdAsResultAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.FileName.Should().Be("factur-x.xml");
result.XmlContent.Should().Be("<invoice/>");
result.Version.Should().Be("2.1");
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?asFile=false");
}
// ?? ExtractZugferdAsResultAsync (byte[]) ?????????????????????????????????
[Fact]
public async Task ExtractZugferdAsResultAsync_Bytes_SendsJsonWithFormatJson()
{
// Arrange
var expected = new ZugferdExtractionResult { FileName = "zugferd.xml", XmlContent = "<x/>" };
var (client, handler) = BuildJson(expected);
// Act
await client.ExtractZugferdAsResultAsync(FakePdfBytes());
// Assert
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?format=json");
handler.LastRequest.Content.Should().NotBeNull();
handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json");
}
// ?? HTTP error propagation ???????????????????????????????????????????????
[Fact]
public async Task HasZugferdAsync_WhenApiReturns400_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.BadRequest);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new ZugferdClient(httpClient, NullLogger<ZugferdClient>.Instance);
// Act & Assert
await client.Invoking(c => c.HasZugferdAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
}