openreader/tests/unit/pdf-audiobook-adapter.vitest.spec.ts

135 lines
4 KiB
TypeScript

import { describe, expect, test } from 'vitest';
import { createPdfAudiobookSourceAdapter } from '../../src/lib/client/audiobooks/adapters/pdf';
import type { ParsedPdfDocument } from '../../src/types/parsed-pdf';
import type { DocumentSettings } from '../../src/types/document-settings';
describe('pdf audiobook adapter', () => {
test('builds chapters from paragraph titles and filters skipped kinds', async () => {
const parsed: ParsedPdfDocument = {
schemaVersion: 1,
documentId: 'doc-1',
parserVersion: 'test',
parsedAt: 1_700_000_000_000,
pages: [
{
pageNumber: 1,
width: 100,
height: 100,
blocks: [
{
id: 'b1',
kind: 'paragraph_title',
text: 'Intro',
fragments: [{ page: 1, bbox: [0, 80, 100, 90], text: 'Intro', readingOrder: 0 }],
},
{
id: 'b2',
kind: 'text',
text: 'Welcome text.',
fragments: [{ page: 1, bbox: [0, 60, 100, 79], text: 'Welcome text.', readingOrder: 1 }],
},
{
id: 'b3',
kind: 'header',
text: 'Header line',
fragments: [{ page: 1, bbox: [0, 95, 100, 100], text: 'Header line', readingOrder: 2 }],
},
{
id: 'b4',
kind: 'paragraph_title',
text: 'Second',
fragments: [{ page: 1, bbox: [0, 40, 100, 50], text: 'Second', readingOrder: 3 }],
},
{
id: 'b5',
kind: 'text',
text: 'More body.',
fragments: [{ page: 1, bbox: [0, 20, 100, 39], text: 'More body.', readingOrder: 4 }],
},
],
},
],
};
const settings: DocumentSettings = {
schemaVersion: 1,
pdf: {
skipBlockKinds: ['header'],
},
};
const adapter = createPdfAudiobookSourceAdapter({
parsed,
settings,
});
const chapters = await adapter.prepareChapters();
expect(chapters).toHaveLength(2);
expect(chapters[0].title).toBe('Intro');
expect(chapters[0].text).toContain('Welcome text.');
expect(chapters[0].text).not.toContain('Header line');
expect(chapters[1].title).toBe('Second');
expect(chapters[1].text).toContain('More body.');
});
test('keeps a single section chapter when only one heading is present', async () => {
const parsed: ParsedPdfDocument = {
schemaVersion: 1,
documentId: 'doc-2',
parserVersion: 'test',
parsedAt: 1_700_000_000_001,
pages: [
{
pageNumber: 1,
width: 100,
height: 100,
blocks: [
{
id: 'p1-title',
kind: 'doc_title',
text: 'Sample PDF',
fragments: [{ page: 1, bbox: [0, 80, 100, 90], text: 'Sample PDF', readingOrder: 0 }],
},
{
id: 'p1-text',
kind: 'text',
text: 'First page body.',
fragments: [{ page: 1, bbox: [0, 50, 100, 79], text: 'First page body.', readingOrder: 1 }],
},
],
},
{
pageNumber: 2,
width: 100,
height: 100,
blocks: [
{
id: 'p2-text',
kind: 'text',
text: 'Second page body.',
fragments: [{ page: 2, bbox: [0, 50, 100, 79], text: 'Second page body.', readingOrder: 0 }],
},
],
},
],
};
const settings: DocumentSettings = {
schemaVersion: 1,
pdf: {
skipBlockKinds: [],
},
};
const adapter = createPdfAudiobookSourceAdapter({
parsed,
settings,
});
const chapters = await adapter.prepareChapters();
expect(chapters).toHaveLength(1);
expect(chapters[0].title).toBe('Sample PDF');
expect(chapters[0].text).toContain('First page body.');
expect(chapters[0].text).toContain('Second page body.');
});
});