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,236 @@
using DocumentService.Client.Clients;
using DocumentService.Client.Interfaces;
using DocumentService.Client.Models.Requests;
using DocumentService.Client.Models.ValueObjects;
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="PdfOperationsClient"/>.
/// All tests use a fake <see cref="MockHttpMessageHandler"/> — no real HTTP calls are made.
/// </summary>
public class PdfOperationsClientTests
{
// ?? helpers ?????????????????????????????????????????????????????????????
private static (PdfOperationsClient client, MockHttpMessageHandler handler) BuildBytes(byte[] bytes = null!)
{
var handler = MockHttpMessageHandler.ReturningBytes(bytes ?? "merged-pdf"u8.ToArray(), "application/pdf");
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new PdfOperationsClient(httpClient, NullLogger<PdfOperationsClient>.Instance);
return (client, handler);
}
private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
private static AddAnnotationBase64Request FakeAnnotationRequest() => new()
{
Base64Pdf = string.Empty,
AnnotationType = AnnotationType.TextMarkup,
PageNumber = 1,
X1 = 10, Y1 = 20, Width = 100, Height = 30,
Color = "FFFF00",
TextMarkupStyle = TextMarkupStyle.Highlight,
Origin = AnnotationOrigin.TopLeft
};
private static AddStampBase64Request FakeStampRequest() => new()
{
Base64Pdf = string.Empty,
StampType = StampType.Text,
X = 100, Y = 50,
Text = "CONFIDENTIAL",
FontSize = 24,
Color = "FF0000",
Opacity = 0.5,
Placement = StampPlacement.Foreground,
Origin = AnnotationOrigin.BottomLeft
};
// ?? MergeAsync (Streams) ?????????????????????????????????????????????????
[Fact]
public async Task MergeAsync_Streams_SendsMultipartWithAllFiles()
{
// Arrange
var (client, handler) = BuildBytes();
var streams = new List<Stream>
{
new MemoryStream(FakePdfBytes()),
new MemoryStream(FakePdfBytes())
};
// Act
using var result = await client.MergeAsync(streams);
// Assert
result.Should().NotBeNull();
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/operations/merge");
handler.LastRequest.Content.Should().BeOfType<MultipartFormDataContent>();
foreach (var s in streams) s.Dispose();
}
[Fact]
public async Task MergeAsync_Streams_ReturnsMergedPdfStream()
{
// Arrange
var expectedBytes = "merged-content"u8.ToArray();
var (client, _) = BuildBytes(expectedBytes);
// Act
using var result = await client.MergeAsync(new[] { new MemoryStream(FakePdfBytes()), new MemoryStream(FakePdfBytes()) });
var actualBytes = await result.ReadAllBytesAsync();
// Assert
actualBytes.Should().BeEquivalentTo(expectedBytes);
}
// ?? MergeAsync (byte[][]) ????????????????????????????????????????????????
[Fact]
public async Task MergeAsync_ByteArrays_SendsJsonWithBase64List()
{
// Arrange
var (client, handler) = BuildBytes();
// Act
using var result = await client.MergeAsync(new[] { FakePdfBytes(), 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("base64Pdfs").GetArrayLength().Should().Be(2);
}
[Fact]
public async Task MergeAsync_ByteArrays_WithPageRanges_IncludesPageRangesInJson()
{
// Arrange
var (client, handler) = BuildBytes();
var pageRanges = new List<string?> { "1-2", null };
// Act
await client.MergeAsync(new[] { FakePdfBytes(), FakePdfBytes() }, pageRanges);
// Assert
handler.LastRequest!.Content.Should().NotBeNull();
var body = await handler.LastRequest!.Content!.ReadAsStringAsync();
var doc = JsonDocument.Parse(body);
doc.RootElement.GetProperty("pageRanges").GetArrayLength().Should().Be(2);
}
// ?? AnnotateAsync (Stream) ????????????????????????????????????????????????
[Fact]
public async Task AnnotateAsync_Stream_SendsMultipartWithAnnotationFields()
{
// Arrange
var (client, handler) = BuildBytes();
var request = FakeAnnotationRequest();
// Act
using var result = await client.AnnotateAsync(new MemoryStream(FakePdfBytes()), request);
// Assert
result.Should().NotBeNull();
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/operations/annotate");
handler.LastRequest.Content.Should().BeOfType<MultipartFormDataContent>();
}
// ?? AnnotateAsync (byte[]) ????????????????????????????????????????????????
[Fact]
public async Task AnnotateAsync_Bytes_SendsJsonWithBase64Pdf()
{
// Arrange
var (client, handler) = BuildBytes();
var request = FakeAnnotationRequest();
// Act
await client.AnnotateAsync(FakePdfBytes(), request);
// 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();
// annotationType serializes as integer by default (TextMarkup = 0)
doc.RootElement.GetProperty("annotationType").GetInt32().Should().Be((int)AnnotationType.TextMarkup);
}
// ?? StampAsync (Stream) ???????????????????????????????????????????????????
[Fact]
public async Task StampAsync_Stream_SendsMultipartWithStampFields()
{
// Arrange
var (client, handler) = BuildBytes();
var request = FakeStampRequest();
// Act
using var result = await client.StampAsync(new MemoryStream(FakePdfBytes()), request);
// Assert
result.Should().NotBeNull();
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/operations/stamp");
handler.LastRequest.Content.Should().BeOfType<MultipartFormDataContent>();
}
// ?? StampAsync (byte[]) ???????????????????????????????????????????????????
[Fact]
public async Task StampAsync_Bytes_SendsJsonWithBase64Pdf()
{
// Arrange
var (client, handler) = BuildBytes();
var request = FakeStampRequest();
// Act
await client.StampAsync(FakePdfBytes(), request);
// 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();
// stampType serializes as integer by default (Text = 0)
doc.RootElement.GetProperty("stampType").GetInt32().Should().Be((int)StampType.Text);
}
// ?? HTTP error propagation ???????????????????????????????????????????????
[Fact]
public async Task MergeAsync_WhenApiReturns400_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.BadRequest);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new PdfOperationsClient(httpClient, NullLogger<PdfOperationsClient>.Instance);
// Act & Assert
await client.Invoking(c => c.MergeAsync(new[] { new MemoryStream(FakePdfBytes()), new MemoryStream(FakePdfBytes()) }))
.Should().ThrowAsync<HttpRequestException>();
}
}
// ?? local helper extension ???????????????????????????????????????????????????
file static class StreamHelper
{
public static async Task<byte[]> ReadAllBytesAsync(this Stream stream)
{
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
return ms.ToArray();
}
}