Refactor: Standardize method names across clients
Renamed methods across multiple client classes for consistency, shortening and aligning naming conventions (e.g., `CheckAttachmentsAsync` → `CheckAsync`, `ValidatePdfAsync` → `ValidateAsync`). Updated corresponding interfaces, unit tests, and documentation to reflect the new method names. Standardized method signatures to support both `Stream` and `byte[]` overloads consistently. Improved error handling in tests and updated examples in the README for batch processing and validation scenarios. Enhanced API endpoint overview for clarity.
This commit is contained in:
@@ -54,10 +54,10 @@ public class PdfAttachmentClientTests
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
// ?? CheckAttachmentsAsync (Stream) ???????????????????????????????????????
|
||||
// ?? CheckAsync (Stream) ???????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task CheckAttachmentsAsync_Stream_SendsMultipartPost()
|
||||
public async Task CheckAsync_Stream_SendsMultipartPost()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new AttachmentCheckResult
|
||||
@@ -72,7 +72,7 @@ public class PdfAttachmentClientTests
|
||||
var (client, handler) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
var result = await client.CheckAttachmentsAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.HasAttachments.Should().BeTrue();
|
||||
@@ -83,14 +83,14 @@ public class PdfAttachmentClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckAttachmentsAsync_Stream_PdfWithNoAttachments_ReturnsFalse()
|
||||
public async Task CheckAsync_Stream_PdfWithNoAttachments_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new AttachmentCheckResult { HasAttachments = false, AttachmentCount = 0, Attachments = [] };
|
||||
var (client, _) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
var result = await client.CheckAttachmentsAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.HasAttachments.Should().BeFalse();
|
||||
@@ -98,17 +98,17 @@ public class PdfAttachmentClientTests
|
||||
result.Attachments.Should().BeEmpty();
|
||||
}
|
||||
|
||||
// ?? CheckAttachmentsAsync (byte[]) ???????????????????????????????????????
|
||||
// ?? CheckAsync (byte[]) ???????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task CheckAttachmentsAsync_Bytes_SendsJsonWithBase64()
|
||||
public async Task CheckAsync_Bytes_SendsJsonWithBase64()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new AttachmentCheckResult { HasAttachments = false };
|
||||
var (client, handler) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
await client.CheckAttachmentsAsync(FakePdfBytes());
|
||||
await client.CheckAsync(FakePdfBytes());
|
||||
|
||||
// Assert
|
||||
handler.LastRequest!.Content.Should().NotBeNull();
|
||||
@@ -118,10 +118,10 @@ public class PdfAttachmentClientTests
|
||||
doc.RootElement.GetProperty("base64Pdf").GetString().Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
// ?? ExtractAttachmentsAsync (Stream) <20> ZIP unzip ?????????????????????????
|
||||
// ?? ExtractAsync (Stream) <20> ZIP unzip ?????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractAttachmentsAsync_Stream_UnzipsAndReturnsDictionary()
|
||||
public async Task ExtractAsync_Stream_UnzipsAndReturnsDictionary()
|
||||
{
|
||||
// Arrange
|
||||
var zipBytes = BuildZip(new Dictionary<string, string>
|
||||
@@ -132,7 +132,7 @@ public class PdfAttachmentClientTests
|
||||
var (client, handler) = BuildBytes(zipBytes);
|
||||
|
||||
// Act
|
||||
var result = await client.ExtractAttachmentsAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.Should().HaveCount(2);
|
||||
@@ -150,7 +150,7 @@ public class PdfAttachmentClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractAttachmentsAsync_Stream_WithSingleEntry_ReturnsOneItem()
|
||||
public async Task ExtractAsync_Stream_WithSingleEntry_ReturnsOneItem()
|
||||
{
|
||||
// Arrange
|
||||
var zipBytes = BuildZip(new Dictionary<string, string>
|
||||
@@ -160,7 +160,7 @@ public class PdfAttachmentClientTests
|
||||
var (client, _) = BuildBytes(zipBytes);
|
||||
|
||||
// Act
|
||||
var result = await client.ExtractAttachmentsAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.Should().HaveCount(1);
|
||||
@@ -169,10 +169,10 @@ public class PdfAttachmentClientTests
|
||||
foreach (var s in result.Values) s.Dispose();
|
||||
}
|
||||
|
||||
// ?? ExtractAttachmentsAsync (byte[]) <20> ZIP unzip ?????????????????????????
|
||||
// ?? ExtractAsync (byte[]) <20> ZIP unzip ?????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractAttachmentsAsync_Bytes_SendsJsonAndUnzips()
|
||||
public async Task ExtractAsync_Bytes_SendsJsonAndUnzips()
|
||||
{
|
||||
// Arrange
|
||||
var zipBytes = BuildZip(new Dictionary<string, string>
|
||||
@@ -182,7 +182,7 @@ public class PdfAttachmentClientTests
|
||||
var (client, handler) = BuildBytes(zipBytes);
|
||||
|
||||
// Act
|
||||
var result = await client.ExtractAttachmentsAsync(FakePdfBytes());
|
||||
var result = await client.ExtractAsync(FakePdfBytes());
|
||||
|
||||
// Assert
|
||||
result.Should().ContainKey("invoice.xml");
|
||||
@@ -195,7 +195,7 @@ public class PdfAttachmentClientTests
|
||||
// ?? HTTP error propagation ???????????????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task CheckAttachmentsAsync_WhenApiReturns404_ThrowsHttpRequestException()
|
||||
public async Task CheckAsync_WhenApiReturns404_ThrowsHttpRequestException()
|
||||
{
|
||||
// Arrange
|
||||
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.NotFound);
|
||||
@@ -203,12 +203,12 @@ public class PdfAttachmentClientTests
|
||||
var client = new PdfAttachmentClient(httpClient, NullLogger<PdfAttachmentClient>.Instance);
|
||||
|
||||
// Act & Assert
|
||||
await client.Invoking(c => c.CheckAttachmentsAsync(new MemoryStream(FakePdfBytes())))
|
||||
await client.Invoking(c => c.CheckAsync(new MemoryStream(FakePdfBytes())))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractAttachmentsAsync_WhenApiReturns500_ThrowsHttpRequestException()
|
||||
public async Task ExtractAsync_WhenApiReturns500_ThrowsHttpRequestException()
|
||||
{
|
||||
// Arrange
|
||||
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.InternalServerError);
|
||||
@@ -216,7 +216,7 @@ public class PdfAttachmentClientTests
|
||||
var client = new PdfAttachmentClient(httpClient, NullLogger<PdfAttachmentClient>.Instance);
|
||||
|
||||
// Act & Assert
|
||||
await client.Invoking(c => c.ExtractAttachmentsAsync(new MemoryStream(FakePdfBytes())))
|
||||
await client.Invoking(c => c.ExtractAsync(new MemoryStream(FakePdfBytes())))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,15 +28,15 @@ public class PdfValidationClientTests
|
||||
|
||||
private static byte[] FakePdfBytes() => "fake-pdf"u8.ToArray();
|
||||
|
||||
// ── ValidatePdfAsync (Stream) ────────────────────────────────────────────
|
||||
// ── ValidateAsync (Stream) ────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task ValidatePdfAsync_Stream_SendsMultipartPost()
|
||||
public async Task ValidateAsync_Stream_SendsMultipartPost()
|
||||
{
|
||||
var expected = new PdfValidationResult(PageCount: 3, FileSizeBytes: 2048, FileSizeMB: 0, PdfVersion: "1.7", HasAttachments: false, AttachmentCount: 0, IsEncrypted: false);
|
||||
var (client, handler) = Build(expected);
|
||||
|
||||
var result = await client.ValidatePdfAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.ValidateAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
result.PageCount.Should().Be(3);
|
||||
result.PdfVersion.Should().Be("1.7");
|
||||
@@ -48,52 +48,52 @@ public class PdfValidationClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidatePdfAsync_Stream_EncryptedPdf_DeserializesIsEncryptedTrue()
|
||||
public async Task ValidateAsync_Stream_EncryptedPdf_DeserializesIsEncryptedTrue()
|
||||
{
|
||||
var expected = new PdfValidationResult(PageCount: 1, FileSizeBytes: 0, FileSizeMB: 0, PdfVersion: "1.6", HasAttachments: false, AttachmentCount: 0, IsEncrypted: true);
|
||||
var (client, _) = Build(expected);
|
||||
|
||||
var result = await client.ValidatePdfAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.ValidateAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
result.IsEncrypted.Should().BeTrue("encrypted PDFs should surface IsEncrypted=true");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidatePdfAsync_Stream_ThrowsWhenApiReturnsNull()
|
||||
public async Task ValidateAsync_Stream_ThrowsWhenApiReturnsNull()
|
||||
{
|
||||
var handler = MockHttpMessageHandler.ReturningJson<PdfValidationResult?>(null);
|
||||
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
|
||||
var client = new PdfValidationClient(httpClient, NullLogger<PdfValidationClient>.Instance);
|
||||
|
||||
await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
|
||||
await client.Invoking(c => c.ValidateAsync(new MemoryStream(FakePdfBytes())))
|
||||
.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidatePdfAsync_Stream_WhenApiReturns400_ThrowsHttpRequestException()
|
||||
public async Task ValidateAsync_Stream_WhenApiReturns400_ThrowsHttpRequestException()
|
||||
{
|
||||
var (client, _) = BuildError(HttpStatusCode.BadRequest);
|
||||
await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
|
||||
await client.Invoking(c => c.ValidateAsync(new MemoryStream(FakePdfBytes())))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidatePdfAsync_Stream_WhenApiReturns500_ThrowsHttpRequestException()
|
||||
public async Task ValidateAsync_Stream_WhenApiReturns500_ThrowsHttpRequestException()
|
||||
{
|
||||
var (client, _) = BuildError(HttpStatusCode.InternalServerError);
|
||||
await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
|
||||
await client.Invoking(c => c.ValidateAsync(new MemoryStream(FakePdfBytes())))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
|
||||
// ── ValidatePdfAsync (byte[]) ────────────────────────────────────────────
|
||||
// ── ValidateAsync (byte[]) ────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task ValidatePdfAsync_Bytes_SendsJsonWithBase64()
|
||||
public async Task ValidateAsync_Bytes_SendsJsonWithBase64()
|
||||
{
|
||||
var expected = new PdfValidationResult(PageCount: 1, FileSizeBytes: 0, FileSizeMB: 0, PdfVersion: "", HasAttachments: true, AttachmentCount: 2, IsEncrypted: false);
|
||||
var (client, handler) = Build(expected);
|
||||
|
||||
var result = await client.ValidatePdfAsync(FakePdfBytes());
|
||||
var result = await client.ValidateAsync(FakePdfBytes());
|
||||
|
||||
result.PageCount.Should().Be(1);
|
||||
result.HasAttachments.Should().BeTrue();
|
||||
@@ -105,10 +105,10 @@ public class PdfValidationClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ValidatePdfAsync_Bytes_WhenApiReturns400_ThrowsHttpRequestException()
|
||||
public async Task ValidateAsync_Bytes_WhenApiReturns400_ThrowsHttpRequestException()
|
||||
{
|
||||
var (client, _) = BuildError(HttpStatusCode.BadRequest);
|
||||
await client.Invoking(c => c.ValidatePdfAsync(FakePdfBytes()))
|
||||
await client.Invoking(c => c.ValidateAsync(FakePdfBytes()))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace DocumentService.Tests.Unit.Client;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for <see cref="SwissQrCodeClient"/>.
|
||||
/// All tests use a fake <see cref="MockHttpMessageHandler"/> — no real HTTP calls are made.
|
||||
/// All tests use a fake <see cref="MockHttpMessageHandler"/> <EFBFBD> no real HTTP calls are made.
|
||||
/// </summary>
|
||||
public class SwissQrCodeClientTests
|
||||
{
|
||||
@@ -27,10 +27,10 @@ public class SwissQrCodeClientTests
|
||||
|
||||
private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
|
||||
|
||||
// ?? ExtractSwissQrCodeAsync (Stream) — parsed Bill ??????????????????????
|
||||
// ?? ExtractAsync (Stream) <EFBFBD> parsed Bill ??????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_Stream_ParsedMode_SendsMultipartToCorrectEndpoint()
|
||||
public async Task ExtractAsync_Stream_ParsedMode_SendsMultipartToCorrectEndpoint()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new SwissQrCodeExtractionResult(
|
||||
@@ -47,7 +47,7 @@ public class SwissQrCodeClientTests
|
||||
var (client, handler) = Build(expected);
|
||||
|
||||
// Act
|
||||
var result = await client.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()), raw: false);
|
||||
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()), raw: false);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
@@ -56,31 +56,31 @@ public class SwissQrCodeClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_Stream_RawMode_SendsRawFlagInUrl()
|
||||
public async Task ExtractAsync_Stream_RawMode_SendsRawFlagInUrl()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: ["SPC", "0200", "1"]);
|
||||
var (client, handler) = Build(expected);
|
||||
|
||||
// Act
|
||||
var result = await client.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()), raw: true);
|
||||
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()), raw: true);
|
||||
|
||||
// Assert
|
||||
result.RawLines.Should().HaveCount(3).And.StartWith("SPC");
|
||||
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=True");
|
||||
}
|
||||
|
||||
// ?? ExtractSwissQrCodeAsync (byte[]) ????????????????????????????????????
|
||||
// ?? ExtractAsync (byte[]) ????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_Bytes_SendsJsonWithBase64()
|
||||
public async Task ExtractAsync_Bytes_SendsJsonWithBase64()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: []);
|
||||
var (client, handler) = Build(expected);
|
||||
|
||||
// Act
|
||||
await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: false);
|
||||
await client.ExtractAsync(FakePdfBytes(), raw: false);
|
||||
|
||||
// Assert
|
||||
handler.LastRequest!.Content.Should().NotBeNull();
|
||||
@@ -91,14 +91,14 @@ public class SwissQrCodeClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_Bytes_RawMode_IncludesRawFlagInUrl()
|
||||
public async Task ExtractAsync_Bytes_RawMode_IncludesRawFlagInUrl()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: ["SPC"]);
|
||||
var (client, handler) = Build(expected);
|
||||
|
||||
// Act
|
||||
await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: true);
|
||||
await client.ExtractAsync(FakePdfBytes(), raw: true);
|
||||
|
||||
// Assert
|
||||
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=True");
|
||||
@@ -107,7 +107,7 @@ public class SwissQrCodeClientTests
|
||||
// ?? HTTP error propagation ??????????????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_WhenApiReturns404_ThrowsHttpRequestException()
|
||||
public async Task ExtractAsync_WhenApiReturns404_ThrowsHttpRequestException()
|
||||
{
|
||||
// Arrange
|
||||
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.NotFound);
|
||||
@@ -115,12 +115,12 @@ public class SwissQrCodeClientTests
|
||||
var client = new SwissQrCodeClient(httpClient, NullLogger<SwissQrCodeClient>.Instance);
|
||||
|
||||
// Act & Assert
|
||||
await client.Invoking(c => c.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes())))
|
||||
await client.Invoking(c => c.ExtractAsync(new MemoryStream(FakePdfBytes())))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_WhenApiReturns500_ThrowsHttpRequestException()
|
||||
public async Task ExtractAsync_WhenApiReturns500_ThrowsHttpRequestException()
|
||||
{
|
||||
// Arrange
|
||||
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.InternalServerError);
|
||||
@@ -128,7 +128,7 @@ public class SwissQrCodeClientTests
|
||||
var client = new SwissQrCodeClient(httpClient, NullLogger<SwissQrCodeClient>.Instance);
|
||||
|
||||
// Act & Assert
|
||||
await client.Invoking(c => c.ExtractSwissQrCodeAsync(FakePdfBytes()))
|
||||
await client.Invoking(c => c.ExtractAsync(FakePdfBytes()))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,20 +84,20 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange
|
||||
var pdfBytes = ValidPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(QrResult());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
result!.Bill.Should().NotBeNull();
|
||||
result.Bill!.Currency.Should().Be("CHF");
|
||||
_validation.Verify(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_validation.Verify(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(pdfBytes, false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -105,18 +105,18 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange
|
||||
var pdfBytes = QrPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, true, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, true, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(RawQrResult());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, raw: true);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(pdfBytes, raw: true);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
result!.RawLines.Should().Contain("SPC");
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(pdfBytes, true, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(pdfBytes, true, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -124,16 +124,16 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange
|
||||
var pdfBytes = EncryptedPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
// Act
|
||||
var act = async () => await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: true);
|
||||
var act = async () => await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: true);
|
||||
|
||||
// Assert
|
||||
await act.Should().ThrowAsync<InvalidOperationException>()
|
||||
.WithMessage("*PDF validation failed*");
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -141,15 +141,15 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange
|
||||
var pdfBytes = EncryptedPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: false);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: false);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -157,11 +157,11 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange – PageCount=0 and FileSize=0 → IsValid=false
|
||||
var pdfBytes = new byte[] { 0x00 };
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_EmptyFile());
|
||||
|
||||
// Act & Assert
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: true))
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: true))
|
||||
.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
|
||||
@@ -170,11 +170,11 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange – ensure the message includes diagnostic fields
|
||||
var pdfBytes = ValidPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
// Act
|
||||
var act = async () => await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: true);
|
||||
var act = async () => await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: true);
|
||||
|
||||
// Assert
|
||||
var ex = await act.Should().ThrowAsync<InvalidOperationException>();
|
||||
@@ -186,14 +186,14 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange – simulate network/API failure during validation
|
||||
var pdfBytes = ValidPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ThrowsAsync(new HttpRequestException("API unreachable"));
|
||||
|
||||
// Act & Assert
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfBytes))
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfBytes))
|
||||
.Should().ThrowAsync<HttpRequestException>()
|
||||
.WithMessage("*API unreachable*");
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -201,13 +201,13 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange – validation succeeds but extraction fails
|
||||
var pdfBytes = QrPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
|
||||
.ThrowsAsync(new HttpRequestException("Extraction failed"));
|
||||
|
||||
// Act & Assert
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfBytes))
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfBytes))
|
||||
.Should().ThrowAsync<HttpRequestException>()
|
||||
.WithMessage("*Extraction failed*");
|
||||
}
|
||||
@@ -219,15 +219,15 @@ public class WorkflowsClientTests
|
||||
var pdfBytes = ValidPdfBytes();
|
||||
var cts = new CancellationTokenSource();
|
||||
var token = cts.Token;
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, token)).ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, token)).ReturnsAsync(QrResult());
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, token)).ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, false, token)).ReturnsAsync(QrResult());
|
||||
|
||||
// Act
|
||||
await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, cancellationToken: token);
|
||||
await Sut.ExtractSwissQrCodeAsync(pdfBytes, cancellationToken: token);
|
||||
|
||||
// Assert
|
||||
_validation.Verify(v => v.ValidatePdfAsync(pdfBytes, token), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, token), Times.Once);
|
||||
_validation.Verify(v => v.ValidateAsync(pdfBytes, token), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(pdfBytes, false, token), Times.Once);
|
||||
}
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════════
|
||||
@@ -238,20 +238,20 @@ public class WorkflowsClientTests
|
||||
public async Task Stream_ValidPdf_CallsValidationWithStreamThenExtractionWithStream_ReturnsResult()
|
||||
{
|
||||
// Arrange – validation client receives a Stream, extraction client receives the same stream reset to 0
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(QrResult());
|
||||
|
||||
using var pdfStream = new MemoryStream(ValidPdfBytes());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
_validation.Verify(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_validation.Verify(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -259,16 +259,16 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange – we verify the stream position is 0 when extraction is called
|
||||
Stream? streamAtExtraction = null;
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
|
||||
.Callback<Stream, bool, CancellationToken>((s, _, _) => streamAtExtraction = s)
|
||||
.ReturnsAsync(QrResult());
|
||||
|
||||
using var pdfStream = new MemoryStream(ValidPdfBytes());
|
||||
|
||||
// Act
|
||||
await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream);
|
||||
await Sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
streamAtExtraction.Should().NotBeNull();
|
||||
@@ -279,52 +279,52 @@ public class WorkflowsClientTests
|
||||
public async Task Stream_InvalidPdf_ThrowIfInvalidTrue_ThrowsWithoutCallingExtraction()
|
||||
{
|
||||
// Arrange
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
using var pdfStream = new MemoryStream(EncryptedPdfBytes());
|
||||
|
||||
// Act & Assert
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfStream, throwIfInvalid: true))
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfStream, throwIfInvalid: true))
|
||||
.Should().ThrowAsync<InvalidOperationException>()
|
||||
.WithMessage("*PDF validation failed*");
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Stream_InvalidPdf_ThrowIfInvalidFalse_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
using var pdfStream = new MemoryStream(EncryptedPdfBytes());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream, throwIfInvalid: false);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(pdfStream, throwIfInvalid: false);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Stream_ValidPdf_RawMode_PassesRawFlagToExtraction()
|
||||
{
|
||||
// Arrange
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(RawQrResult());
|
||||
|
||||
using var pdfStream = new MemoryStream(QrPdfBytes());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream, raw: true);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(pdfStream, raw: true);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════════
|
||||
@@ -340,18 +340,18 @@ public class WorkflowsClientTests
|
||||
{
|
||||
await File.WriteAllBytesAsync(tempPath, ValidPdfBytes());
|
||||
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(QrResult());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(tempPath);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(tempPath);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
_validation.Verify(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_validation.Verify(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -368,13 +368,13 @@ public class WorkflowsClientTests
|
||||
{
|
||||
await File.WriteAllBytesAsync(tempPath, EncryptedPdfBytes());
|
||||
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
// Act & Assert
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(tempPath, throwIfInvalid: true))
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(tempPath, throwIfInvalid: true))
|
||||
.Should().ThrowAsync<InvalidOperationException>();
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -391,11 +391,11 @@ public class WorkflowsClientTests
|
||||
{
|
||||
await File.WriteAllBytesAsync(tempPath, EncryptedPdfBytes());
|
||||
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(tempPath, throwIfInvalid: false);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(tempPath, throwIfInvalid: false);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
@@ -413,10 +413,10 @@ public class WorkflowsClientTests
|
||||
var nonExistent = Path.Combine(Path.GetTempPath(), "does_not_exist_12345.pdf");
|
||||
|
||||
// Act & Assert
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(nonExistent))
|
||||
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(nonExistent))
|
||||
.Should().ThrowAsync<FileNotFoundException>();
|
||||
_validation.Verify(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_validation.Verify(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -428,17 +428,17 @@ public class WorkflowsClientTests
|
||||
{
|
||||
await File.WriteAllBytesAsync(tempPath, QrPdfBytes());
|
||||
|
||||
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(ValidResult());
|
||||
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()))
|
||||
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(RawQrResult());
|
||||
|
||||
// Act
|
||||
var result = await Sut.ExtractSwissQrCodeValidatedAsync(tempPath, raw: true);
|
||||
var result = await Sut.ExtractSwissQrCodeAsync(tempPath, raw: true);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -457,16 +457,16 @@ public class WorkflowsClientTests
|
||||
{
|
||||
// Arrange
|
||||
var pdfBytes = EncryptedPdfBytes();
|
||||
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(InvalidResult_Encrypted());
|
||||
|
||||
// Act
|
||||
try { await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: throwIfInvalid); }
|
||||
try { await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: throwIfInvalid); }
|
||||
catch (InvalidOperationException) { /* expected when throwIfInvalid=true */ }
|
||||
|
||||
// Assert — extraction must never be called in either branch
|
||||
_swissQrCode.Verify(
|
||||
q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Never,
|
||||
"extraction must not be attempted on an invalid document");
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ 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.
|
||||
/// All tests use a fake <see cref="MockHttpMessageHandler"/> <EFBFBD> no real HTTP calls are made.
|
||||
/// </summary>
|
||||
public class ZugferdClientTests
|
||||
{
|
||||
@@ -37,17 +37,17 @@ public class ZugferdClientTests
|
||||
private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
|
||||
private static byte[] FakeXmlBytes() => "<invoice>test</invoice>"u8.ToArray();
|
||||
|
||||
// ?? HasZugferdAsync (Stream) ?????????????????????????????????????????????
|
||||
// ?? CheckAsync (Stream) ?????????????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task HasZugferdAsync_Stream_WhenZugferdPresent_ReturnsTrue()
|
||||
public async Task CheckAsync_Stream_WhenZugferdPresent_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ZugferdCheckResult { HasZugferd = true, ZugferdFileName = "factur-x.xml" };
|
||||
var (client, handler) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
var result = await client.HasZugferdAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.HasZugferd.Should().BeTrue();
|
||||
@@ -56,31 +56,31 @@ public class ZugferdClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HasZugferdAsync_Stream_WhenNoZugferd_ReturnsFalse()
|
||||
public async Task CheckAsync_Stream_WhenNoZugferd_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ZugferdCheckResult { HasZugferd = false };
|
||||
var (client, _) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
var result = await client.HasZugferdAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.HasZugferd.Should().BeFalse();
|
||||
result.ZugferdFileName.Should().BeNull();
|
||||
}
|
||||
|
||||
// ?? HasZugferdAsync (byte[]) ?????????????????????????????????????????????
|
||||
// ?? CheckAsync (byte[]) ?????????????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task HasZugferdAsync_Bytes_SendsJsonWithBase64()
|
||||
public async Task CheckAsync_Bytes_SendsJsonWithBase64()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ZugferdCheckResult { HasZugferd = true };
|
||||
var (client, handler) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
await client.HasZugferdAsync(FakePdfBytes());
|
||||
await client.CheckAsync(FakePdfBytes());
|
||||
|
||||
// Assert
|
||||
handler.LastRequest!.Content.Should().NotBeNull();
|
||||
@@ -90,16 +90,16 @@ public class ZugferdClientTests
|
||||
doc.RootElement.GetProperty("base64Pdf").GetString().Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
// ?? ExtractZugferdAsync (Stream) — raw XML stream ?????????????????????????
|
||||
// ?? ExtractAsync (Stream) <EFBFBD> raw XML stream ?????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractZugferdAsync_Stream_SendsMultipartWithAsFileTrue()
|
||||
public async Task ExtractAsync_Stream_SendsMultipartWithAsFileTrue()
|
||||
{
|
||||
// Arrange
|
||||
var (client, handler) = BuildBytes(FakeXmlBytes());
|
||||
|
||||
// Act
|
||||
using var result = await client.ExtractZugferdAsync(new MemoryStream(FakePdfBytes()));
|
||||
using var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
@@ -108,30 +108,30 @@ public class ZugferdClientTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractZugferdAsync_Stream_ReturnsXmlContent()
|
||||
public async Task ExtractAsync_Stream_ReturnsXmlContent()
|
||||
{
|
||||
// Arrange
|
||||
var xmlBytes = "<root><invoice/></root>"u8.ToArray();
|
||||
var (client, _) = BuildBytes(xmlBytes);
|
||||
|
||||
// Act
|
||||
using var result = await client.ExtractZugferdAsync(new MemoryStream(FakePdfBytes()));
|
||||
using var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
|
||||
var content = await new StreamReader(result).ReadToEndAsync();
|
||||
|
||||
// Assert
|
||||
content.Should().Be("<root><invoice/></root>");
|
||||
}
|
||||
|
||||
// ?? ExtractZugferdAsync (byte[]) ?????????????????????????????????????????
|
||||
// ?? ExtractAsync (byte[]) ?????????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractZugferdAsync_Bytes_SendsJsonWithFormatFile()
|
||||
public async Task ExtractAsync_Bytes_SendsJsonWithFormatFile()
|
||||
{
|
||||
// Arrange
|
||||
var (client, handler) = BuildBytes(FakeXmlBytes());
|
||||
|
||||
// Act
|
||||
using var result = await client.ExtractZugferdAsync(FakePdfBytes());
|
||||
using var result = await client.ExtractAsync(FakePdfBytes());
|
||||
|
||||
// Assert
|
||||
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?format=file");
|
||||
@@ -139,10 +139,10 @@ public class ZugferdClientTests
|
||||
handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json");
|
||||
}
|
||||
|
||||
// ?? ExtractZugferdAsResultAsync (Stream) ?????????????????????????????????
|
||||
// ?? ExtractAsResultAsync (Stream) ?????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractZugferdAsResultAsync_Stream_ReturnsStructuredResult()
|
||||
public async Task ExtractAsResultAsync_Stream_ReturnsStructuredResult()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ZugferdExtractionResult
|
||||
@@ -153,7 +153,7 @@ public class ZugferdClientTests
|
||||
var (client, handler) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
var result = await client.ExtractZugferdAsResultAsync(new MemoryStream(FakePdfBytes()));
|
||||
var result = await client.ExtractAsResultAsync(new MemoryStream(FakePdfBytes()));
|
||||
|
||||
// Assert
|
||||
result.FileName.Should().Be("factur-x.xml");
|
||||
@@ -161,17 +161,17 @@ public class ZugferdClientTests
|
||||
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?asFile=false");
|
||||
}
|
||||
|
||||
// ?? ExtractZugferdAsResultAsync (byte[]) ?????????????????????????????????
|
||||
// ?? ExtractAsResultAsync (byte[]) ?????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractZugferdAsResultAsync_Bytes_SendsJsonWithFormatJson()
|
||||
public async Task ExtractAsResultAsync_Bytes_SendsJsonWithFormatJson()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ZugferdExtractionResult { FileName = "zugferd.xml", XmlContent = "<x/>" };
|
||||
var (client, handler) = BuildJson(expected);
|
||||
|
||||
// Act
|
||||
await client.ExtractZugferdAsResultAsync(FakePdfBytes());
|
||||
await client.ExtractAsResultAsync(FakePdfBytes());
|
||||
|
||||
// Assert
|
||||
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?format=json");
|
||||
@@ -182,7 +182,7 @@ public class ZugferdClientTests
|
||||
// ?? HTTP error propagation ???????????????????????????????????????????????
|
||||
|
||||
[Fact]
|
||||
public async Task HasZugferdAsync_WhenApiReturns400_ThrowsHttpRequestException()
|
||||
public async Task CheckAsync_WhenApiReturns400_ThrowsHttpRequestException()
|
||||
{
|
||||
// Arrange
|
||||
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.BadRequest);
|
||||
@@ -190,7 +190,7 @@ public class ZugferdClientTests
|
||||
var client = new ZugferdClient(httpClient, NullLogger<ZugferdClient>.Instance);
|
||||
|
||||
// Act & Assert
|
||||
await client.Invoking(c => c.HasZugferdAsync(new MemoryStream(FakePdfBytes())))
|
||||
await client.Invoking(c => c.CheckAsync(new MemoryStream(FakePdfBytes())))
|
||||
.Should().ThrowAsync<HttpRequestException>();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user