test(infrastructure): Add 12 unit tests for AddAnnotationAsync

- 5 happy path tests (one per annotation type)
- 7 validation error tests (empty stream, invalid position, page number, content, style, color)
- All tests passing (12/12)
- Total unit tests: 37 (25 previous + 12 annotation)
This commit is contained in:
2026-07-21 12:28:17 +02:00
parent 41f97ce533
commit a23c78ec3a

View File

@@ -565,5 +565,252 @@ public class DevExpressPdfProcessorTests
} }
#endregion #endregion
#region AddAnnotationAsync Tests
[Fact]
public async Task AddAnnotationAsync_TextMarkupHighlight_ReturnsAnnotatedPdf()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
var annotationType = Domain.Models.ValueObjects.AnnotationType.TextMarkup;
var rectangle = (X1: 100.0, Y1: 100.0, X2: 200.0, Y2: 120.0);
var textMarkupStyle = Domain.Models.ValueObjects.TextMarkupStyle.Highlight;
// Act
byte[] result = await _sut.AddAnnotationAsync(
pdfStream,
annotationType,
pageNumber: 1,
rectangle,
content: "Important text",
author: "Test Author",
color: "FFFF00", // Yellow
textMarkupStyle);
// Assert
result.Should().NotBeEmpty();
result.Length.Should().BeGreaterThan((int)pdfStream.Length); // Annotation adds bytes
}
[Fact]
public async Task AddAnnotationAsync_FreeText_ReturnsAnnotatedPdf()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
var annotationType = Domain.Models.ValueObjects.AnnotationType.FreeText;
var rectangle = (X1: 50.0, Y1: 50.0, X2: 150.0, Y2: 100.0);
// Act
byte[] result = await _sut.AddAnnotationAsync(
pdfStream,
annotationType,
pageNumber: 1,
rectangle,
content: "Free text annotation",
author: "John Doe",
color: "FF0000"); // Red
// Assert
result.Should().NotBeEmpty();
result.Length.Should().BeGreaterThan((int)pdfStream.Length);
}
[Fact]
public async Task AddAnnotationAsync_StickyNote_ReturnsAnnotatedPdf()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
var annotationType = Domain.Models.ValueObjects.AnnotationType.StickyNote;
var rectangle = (X1: 300.0, Y1: 300.0, X2: 320.0, Y2: 320.0);
// Act
byte[] result = await _sut.AddAnnotationAsync(
pdfStream,
annotationType,
pageNumber: 1,
rectangle,
content: "Please review this section",
author: "Reviewer");
// Assert
result.Should().NotBeEmpty();
}
[Fact]
public async Task AddAnnotationAsync_Circle_ReturnsAnnotatedPdf()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
var annotationType = Domain.Models.ValueObjects.AnnotationType.Circle;
var rectangle = (X1: 100.0, Y1: 200.0, X2: 200.0, Y2: 300.0);
// Act
byte[] result = await _sut.AddAnnotationAsync(
pdfStream,
annotationType,
pageNumber: 1,
rectangle,
content: "Circle annotation",
color: "00FF00"); // Green
// Assert
result.Should().NotBeEmpty();
}
[Fact]
public async Task AddAnnotationAsync_Square_ReturnsAnnotatedPdf()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
var annotationType = Domain.Models.ValueObjects.AnnotationType.Square;
var rectangle = (X1: 250.0, Y1: 250.0, X2: 350.0, Y2: 350.0);
// Act
byte[] result = await _sut.AddAnnotationAsync(
pdfStream,
annotationType,
pageNumber: 1,
rectangle,
color: "0000FF"); // Blue
// Assert
result.Should().NotBeEmpty();
}
[Fact]
public async Task AddAnnotationAsync_EmptyStream_ThrowsBadRequestException()
{
// Arrange
using var emptyStream = new MemoryStream();
// Act
var act = async () => await _sut.AddAnnotationAsync(
emptyStream,
Domain.Models.ValueObjects.AnnotationType.FreeText,
pageNumber: 1,
rectangle: (0, 0, 100, 100),
content: "Test");
// Assert
await act.Should().ThrowAsync<BadRequestException>()
.WithMessage("*cannot be empty*");
}
[Fact]
public async Task AddAnnotationAsync_StreamNotAtPositionZero_ThrowsBadRequestException()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
pdfStream.Position = 10; // Move stream position
// Act
var act = async () => await _sut.AddAnnotationAsync(
pdfStream,
Domain.Models.ValueObjects.AnnotationType.Circle,
pageNumber: 1,
rectangle: (0, 0, 100, 100));
// Assert
await act.Should().ThrowAsync<BadRequestException>()
.WithMessage("*must be at position 0*");
}
[Fact]
public async Task AddAnnotationAsync_InvalidPageNumber_ThrowsBadRequestException()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
// Act
var act = async () => await _sut.AddAnnotationAsync(
pdfStream,
Domain.Models.ValueObjects.AnnotationType.FreeText,
pageNumber: 999, // Exceeds page count
rectangle: (0, 0, 100, 100),
content: "Test");
// Assert
await act.Should().ThrowAsync<BadRequestException>()
.WithMessage("*exceeds document page count*");
}
[Fact]
public async Task AddAnnotationAsync_FreeTextWithoutContent_ThrowsBadRequestException()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
// Act
var act = async () => await _sut.AddAnnotationAsync(
pdfStream,
Domain.Models.ValueObjects.AnnotationType.FreeText,
pageNumber: 1,
rectangle: (0, 0, 100, 100),
content: null); // Missing required content
// Assert
await act.Should().ThrowAsync<BadRequestException>()
.WithMessage("*requires content*");
}
[Fact]
public async Task AddAnnotationAsync_StickyNoteWithoutContent_ThrowsBadRequestException()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
// Act
var act = async () => await _sut.AddAnnotationAsync(
pdfStream,
Domain.Models.ValueObjects.AnnotationType.StickyNote,
pageNumber: 1,
rectangle: (0, 0, 20, 20),
content: ""); // Empty content
// Assert
await act.Should().ThrowAsync<BadRequestException>()
.WithMessage("*requires content*");
}
[Fact]
public async Task AddAnnotationAsync_TextMarkupWithoutStyle_ThrowsBadRequestException()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
// Act
var act = async () => await _sut.AddAnnotationAsync(
pdfStream,
Domain.Models.ValueObjects.AnnotationType.TextMarkup,
pageNumber: 1,
rectangle: (0, 0, 100, 100),
textMarkupStyle: null); // Missing required style
// Assert
await act.Should().ThrowAsync<BadRequestException>()
.WithMessage("*requires textMarkupStyle*");
}
[Fact]
public async Task AddAnnotationAsync_InvalidColorFormat_ThrowsBadRequestException()
{
// Arrange
using var pdfStream = LoadTestPdfAsStream("valid.pdf");
// Act
var act = async () => await _sut.AddAnnotationAsync(
pdfStream,
Domain.Models.ValueObjects.AnnotationType.Circle,
pageNumber: 1,
rectangle: (0, 0, 100, 100),
color: "INVALID"); // Invalid hex format
// Assert
await act.Should().ThrowAsync<BadRequestException>()
.WithMessage("*Invalid color format*");
}
#endregion
} }