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:
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user