import assert from "node:assert/strict"; import test from "node:test"; import { extractPdfText, hasPdfMagic } from "../src/llm/pdf-text.js"; import { createPdf } from "./pdf-fixture.js"; test("extracts selectable text with page markers and selected-page support", async () => { const bytes = createPdf(["Quarterly revenue was 42.", "Costs were 18."]); const result = await extractPdfText(bytes, [2]); assert.equal(result.status, "ok"); assert.equal(result.pageCount, 2); assert.deepEqual(result.pages, [2]); assert.match(result.text, /--- Page 2 ---/); assert.match(result.text, /Costs were 18\./); assert.doesNotMatch(result.text, /Quarterly revenue/); }); test("reports PDFs with no selectable text clearly", async () => { const result = await extractPdfText(createPdf([""])); assert.equal(result.status, "no_text"); assert.match(result.text, /No extractable text/); }); test("reports encrypted PDFs clearly", async () => { const result = await extractPdfText(createPdf(["Secret"], true)); assert.equal(result.status, "encrypted"); assert.match(result.text, /encrypted and requires a password/); }); test("reports page-free PDFs and rejects invalid requested pages", async () => { const empty = await extractPdfText(createPdf([])); assert.equal(empty.status, "no_pages"); assert.match(empty.text, /no pages/); const outOfRange = await extractPdfText(createPdf(["Only page"]), [2]); assert.equal(outOfRange.status, "error"); assert.match(outOfRange.text, /has 1 pages/); }); test("limits each extraction to 30 pages and preserves the full page count", async () => { const result = await extractPdfText(createPdf(Array.from({ length: 31 }, (_, index) => `Text on page ${index + 1}.`))); assert.equal(result.status, "ok"); assert.equal(result.pageCount, 31); assert.equal(result.pages.length, 30); assert.equal(result.pages.at(-1), 30); }); test("caps accumulated extracted text at the caller limit", async () => { const result = await extractPdfText(createPdf(["Long sentence. ".repeat(200)]), undefined, 50); assert.equal(result.status, "ok"); assert.equal(result.truncated, true); assert.ok(result.text.length <= 50); }); test("terminates an over-time worker and returns an explicit timeout result", async () => { const result = await extractPdfText(createPdf(["Small document"]), undefined, 12_000, 1); assert.equal(result.status, "error"); assert.match(result.text, /time limit/); }); test("recognizes PDF magic in a mislabeled or prefixed response", () => { assert.equal(hasPdfMagic(new TextEncoder().encode("%PDF-1.4")), true); assert.equal(hasPdfMagic(new TextEncoder().encode(`${" ".repeat(500)}%PDF-1.7`)), true); assert.equal(hasPdfMagic(new TextEncoder().encode("not a PDF")), false); });