openreader/compute-worker/tests/compute/algorithms/pdf-stitch-cross-page-blocks.test.ts
Richard R a56aaa2be9 Refactor PDF parsing and rendering logic; migrate to compute-worker protocol
- Removed deprecated functions related to document parsing and blob storage in blobstore.ts.
- Introduced new PDF rendering logic in pdf-preview-renderer.ts and pdf-preview-pdfjs-runtime.ts.
- Updated previews-render.ts to utilize the new PDF rendering functions.
- Refactored user-whisper-align-job.ts to use the compute-worker client for alignment requests.
- Enhanced artifact.ts and operation.ts to validate parsed PDF artifacts and resolve current PDF parses.
- Updated snapshot.ts to align with new worker operation types.
- Adjusted runtime-config.ts to check for compute-worker availability.
- Modified types in parsed-pdf.ts and tts.ts to reflect changes in the compute-worker protocol.
- Added unit tests for PDF artifact validation and compute-worker client contract.
- Removed obsolete pdf-op-key.vitest.spec.ts test file.
2026-06-12 13:43:33 -06:00

106 lines
3.3 KiB
TypeScript

import { describe, expect, test } from 'vitest';
import { stitchCrossPageBlocks } from '../../../src/compute';
import type { ParsedPdfBlock, ParsedPdfDocument, ParsedPdfBlockKind } from '../../../src/compute/types';
import { makeParsedPdfDocument, makeParsedPdfPage } from './support/document-fixtures';
function makeBlock(
id: string,
kind: ParsedPdfBlockKind,
text: string,
page: number,
readingOrder: number,
): ParsedPdfBlock {
return {
id,
kind,
text,
fragments: [{
page,
bbox: [0, 0, 100, 10],
text,
readingOrder,
}],
};
}
function makeDoc(page1Blocks: ParsedPdfBlock[], page2Blocks: ParsedPdfBlock[]): ParsedPdfDocument {
return makeParsedPdfDocument([
makeParsedPdfPage(1, page1Blocks),
makeParsedPdfPage(2, page2Blocks),
]);
}
describe('stitchCrossPageBlocks', () => {
test('stitches paragraph continuation across footer/header noise', () => {
const doc = makeDoc(
[
makeBlock('b1', 'text', 'This sentence continues', 1, 0),
makeBlock('b2', 'footer', 'Footer text', 1, 1),
],
[
makeBlock('b3', 'header', 'Header text', 2, 0),
makeBlock('b4', 'text', 'into the next page.', 2, 1),
],
);
const stitched = stitchCrossPageBlocks(doc);
const page1 = stitched.pages[0];
const page2 = stitched.pages[1];
expect(page1?.blocks[0]?.text).toBe('This sentence continues into the next page.');
expect(page1?.blocks[0]?.fragments).toHaveLength(2);
expect(page2?.blocks.map((b) => b.id)).toEqual(['b3']);
});
test('moves only the continuation sentence and keeps remaining text on next page', () => {
const doc = makeDoc(
[
makeBlock('b1', 'text', 'This sentence continues', 1, 0),
],
[
makeBlock('b2', 'text', 'into the next page. This should stay on page two.', 2, 0),
],
);
const stitched = stitchCrossPageBlocks(doc);
const page1 = stitched.pages[0];
const page2 = stitched.pages[1];
expect(page1?.blocks[0]?.text).toBe('This sentence continues into the next page.');
expect(page1?.blocks[0]?.fragments).toHaveLength(2);
expect(page2?.blocks).toHaveLength(1);
expect(page2?.blocks[0]?.id).toBe('b2');
expect(page2?.blocks[0]?.text).toBe('This should stay on page two.');
});
test('does not stitch across paragraph-title boundary', () => {
const doc = makeDoc(
[
makeBlock('b1', 'text', 'This sentence continues', 1, 0),
],
[
makeBlock('b2', 'paragraph_title', '2 New Section', 2, 0),
makeBlock('b3', 'text', 'into the next page.', 2, 1),
],
);
const stitched = stitchCrossPageBlocks(doc);
expect(stitched.pages[0]?.blocks[0]?.fragments).toHaveLength(1);
expect(stitched.pages[1]?.blocks.map((b) => b.id)).toEqual(['b2', 'b3']);
});
test('does not stitch when tail has sentence terminal', () => {
const doc = makeDoc(
[
makeBlock('b1', 'text', 'This sentence is complete.', 1, 0),
],
[
makeBlock('b2', 'text', 'next sentence starts here', 2, 0),
],
);
const stitched = stitchCrossPageBlocks(doc);
expect(stitched.pages[0]?.blocks[0]?.fragments).toHaveLength(1);
expect(stitched.pages[1]?.blocks.map((b) => b.id)).toEqual(['b2']);
});
});