import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import fs from 'node:fs/promises'; import path from 'node:path'; import os from 'node:os'; import { Document, Paragraph, TextRun, Packer } from 'docx'; import { registerDocumentConverters } from '../../src/converters/document.js'; import { resolve } from '../../src/converters/registry.js'; import { detectInputMime } from '../../src/mime.js'; let tmpDir; let docxFixturePath; beforeAll(async () => { registerDocumentConverters(); tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'converter-document-')); const doc = new Document({ sections: [ { children: [new Paragraph({ children: [new TextRun('Hello from the fixture document')] })], }, ], }); const buffer = await Packer.toBuffer(doc); docxFixturePath = path.join(tmpDir, 'fixture.docx'); await fs.writeFile(docxFixturePath, buffer); }); afterAll(async () => { await fs.rm(tmpDir, { recursive: true, force: true }); }); describe('document converters', () => { it('converts DOCX to HTML containing the source text', async () => { const outputPath = path.join(tmpDir, 'output.html'); const entry = resolve('docx', 'html'); await entry.convert(docxFixturePath, outputPath); const html = await fs.readFile(outputPath, 'utf8'); expect(html).toContain('Hello from the fixture document'); }, 20000); it('converts TXT to a valid PDF', async () => { const inputPath = path.join(tmpDir, 'fixture.txt'); await fs.writeFile(inputPath, 'Plain text content for the PDF'); const outputPath = path.join(tmpDir, 'from-txt.pdf'); const entry = resolve('txt', 'pdf'); await entry.convert(inputPath, outputPath); const detected = await detectInputMime(outputPath); expect(detected.mime).toBe('application/pdf'); }, 20000); it('converts HTML to a valid PDF', async () => { const inputPath = path.join(tmpDir, 'fixture.html'); await fs.writeFile(inputPath, '

Hello HTML

'); const outputPath = path.join(tmpDir, 'from-html.pdf'); const entry = resolve('html', 'pdf'); await entry.convert(inputPath, outputPath); const detected = await detectInputMime(outputPath); expect(detected.mime).toBe('application/pdf'); }, 20000); it('converts DOCX to a valid PDF', async () => { const outputPath = path.join(tmpDir, 'from-docx.pdf'); const entry = resolve('docx', 'pdf'); await entry.convert(docxFixturePath, outputPath); const detected = await detectInputMime(outputPath); expect(detected.mime).toBe('application/pdf'); }, 20000); it('converts MD to HTML', async () => { const inputPath = path.join(tmpDir, 'fixture.md'); await fs.writeFile(inputPath, '# Heading\n\nSome **bold** text.'); const outputPath = path.join(tmpDir, 'from-md.html'); const entry = resolve('md', 'html'); await entry.convert(inputPath, outputPath); const html = await fs.readFile(outputPath, 'utf8'); expect(html).toContain('

Heading

'); expect(html).toContain('bold'); }); it('converts HTML to MD', async () => { const inputPath = path.join(tmpDir, 'fixture-for-md.html'); await fs.writeFile(inputPath, '

Heading

Some bold text.

'); const outputPath = path.join(tmpDir, 'from-html.md'); const entry = resolve('html', 'md'); await entry.convert(inputPath, outputPath); const markdown = await fs.readFile(outputPath, 'utf8'); expect(markdown).toContain('# Heading'); expect(markdown).toContain('**bold**'); }); it('converts MD to a valid PDF', async () => { const inputPath = path.join(tmpDir, 'fixture-for-pdf.md'); await fs.writeFile(inputPath, '# Heading\n\nSome text.'); const outputPath = path.join(tmpDir, 'from-md.pdf'); const entry = resolve('md', 'pdf'); await entry.convert(inputPath, outputPath); const detected = await detectInputMime(outputPath); expect(detected.mime).toBe('application/pdf'); }, 20000); it('converts DOCX to MD containing the source text', async () => { const outputPath = path.join(tmpDir, 'from-docx.md'); const entry = resolve('docx', 'md'); await entry.convert(docxFixturePath, outputPath); const markdown = await fs.readFile(outputPath, 'utf8'); expect(markdown).toContain('Hello from the fixture document'); }, 20000); it('converts MD to DOCX preserving headings, bold text, and bullet lists', async () => { const inputPath = path.join(tmpDir, 'fixture-for-docx.md'); await fs.writeFile( inputPath, '# Report Title\n\nSome **bold** finding.\n\n- first point\n- second point\n' ); const outputPath = path.join(tmpDir, 'from-md.docx'); const entry = resolve('md', 'docx'); await entry.convert(inputPath, outputPath); const mammoth = await import('mammoth'); const result = await mammoth.default.convertToHtml({ path: outputPath }); expect(result.value).toContain('Report Title'); expect(result.value).toContain('bold'); expect(result.value).toContain('first point'); expect(result.value).toContain('
  • '); }, 20000); it('copies MD content unchanged to TXT', async () => { const inputPath = path.join(tmpDir, 'fixture-for-txt.md'); const content = '# Heading\n\nSome **bold** text.\n'; await fs.writeFile(inputPath, content); const outputPath = path.join(tmpDir, 'from-md.txt'); const entry = resolve('md', 'txt'); await entry.convert(inputPath, outputPath); const output = await fs.readFile(outputPath, 'utf8'); expect(output).toBe(content); }); it('copies TXT content unchanged to MD', async () => { const inputPath = path.join(tmpDir, 'fixture-for-md-from-txt.txt'); const content = 'Plain text content.\n'; await fs.writeFile(inputPath, content); const outputPath = path.join(tmpDir, 'from-txt.md'); const entry = resolve('txt', 'md'); await entry.convert(inputPath, outputPath); const output = await fs.readFile(outputPath, 'utf8'); expect(output).toBe(content); }); });