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
|
||||
|
||||
#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