96 lines
3.1 KiB
TypeScript
96 lines
3.1 KiB
TypeScript
import { describe, it, expect, vi } from "vitest";
|
|
import { PDFDocument } from "pdf-lib";
|
|
import { pdfWatermarkPlugin, type PdfWatermarkOptions } from "./index";
|
|
import { runPdfWatermark } from "./run";
|
|
import { MAX_WATERMARK_CHARS } from "./watermark";
|
|
import type { ToolContext } from "../../core/plugins/plugin-types";
|
|
|
|
const mockContext: ToolContext = {
|
|
signal: new AbortController().signal,
|
|
reportProgress: vi.fn(),
|
|
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
};
|
|
|
|
const defaultOptions: PdfWatermarkOptions = {
|
|
text: "CONFIDENTIAL",
|
|
orientation: "diagonal",
|
|
opacity: 30,
|
|
color: "light-grey",
|
|
};
|
|
|
|
async function makePdfFile(): Promise<File> {
|
|
const doc = await PDFDocument.create();
|
|
doc.addPage([595, 842]);
|
|
const bytes = await doc.save();
|
|
return new File([bytes as unknown as BlobPart], "sample.pdf", {
|
|
type: "application/pdf",
|
|
});
|
|
}
|
|
|
|
describe("PDF Watermark Plugin", () => {
|
|
it("should have correct manifest", () => {
|
|
expect(pdfWatermarkPlugin.manifest.id).toBe("pdf-watermark");
|
|
expect(pdfWatermarkPlugin.manifest.category).toBe("pdf");
|
|
expect(pdfWatermarkPlugin.manifest.input.type).toBe("files");
|
|
expect(pdfWatermarkPlugin.manifest.output.type).toBe("files");
|
|
});
|
|
|
|
it("should throw if no file provided", async () => {
|
|
await expect(
|
|
runPdfWatermark({ files: [] }, defaultOptions, mockContext)
|
|
).rejects.toThrow("No PDF file provided.");
|
|
});
|
|
|
|
it("should throw if watermark text is empty", async () => {
|
|
const file = await makePdfFile();
|
|
await expect(
|
|
runPdfWatermark({ files: [file] }, { ...defaultOptions, text: " " }, mockContext)
|
|
).rejects.toThrow("Watermark text is required.");
|
|
});
|
|
|
|
it("should produce a watermarked PDF", async () => {
|
|
const file = await makePdfFile();
|
|
const result = await runPdfWatermark(
|
|
{ files: [file] },
|
|
defaultOptions,
|
|
mockContext
|
|
);
|
|
|
|
expect(result.type).toBe("files");
|
|
if (result.type !== "files") throw new Error("unexpected result");
|
|
expect(result.files).toHaveLength(1);
|
|
expect(result.files[0].name).toBe("sample_watermarked.pdf");
|
|
expect(result.files[0].mimeType).toBe("application/pdf");
|
|
expect(result.files[0].blob.size).toBeGreaterThan(0);
|
|
|
|
// Output should still be a loadable PDF with the same page count.
|
|
const out = await result.files[0].blob.arrayBuffer();
|
|
const reloaded = await PDFDocument.load(new Uint8Array(out));
|
|
expect(reloaded.getPageCount()).toBe(1);
|
|
});
|
|
|
|
it.each(["horizontal", "vertical", "diagonal"] as const)(
|
|
"should handle %s orientation",
|
|
async (orientation) => {
|
|
const file = await makePdfFile();
|
|
const result = await runPdfWatermark(
|
|
{ files: [file] },
|
|
{ ...defaultOptions, orientation },
|
|
mockContext
|
|
);
|
|
expect(result.type).toBe("files");
|
|
}
|
|
);
|
|
|
|
it("should truncate text beyond the max length", async () => {
|
|
const file = await makePdfFile();
|
|
const longText = "A".repeat(MAX_WATERMARK_CHARS + 50);
|
|
const result = await runPdfWatermark(
|
|
{ files: [file] },
|
|
{ ...defaultOptions, text: longText },
|
|
mockContext
|
|
);
|
|
expect(result.type).toBe("files");
|
|
});
|
|
});
|