const { expect } = require('chai') const sinon = require('sinon') const Path = require('path') const os = require('os') const fs = require('fs') const { execSync } = require('child_process') const textExtractor = require('../../../server/utils/textExtractor') describe('TextExtractor', () => { describe('stripHtml', () => { it('should strip HTML tags', () => { const result = textExtractor.stripHtml('
Hello world
') expect(result).to.equal('Hello world') }) it('should remove script tags with content', () => { const result = textExtractor.stripHtml('Hello
World
') expect(result).to.equal('Hello World') }) it('should remove style tags with content', () => { const result = textExtractor.stripHtml('Text
') expect(result).to.equal('Text') }) it('should decode HTML entities', () => { const result = textExtractor.stripHtml('& < > " ' ') expect(result).to.equal("& < > \" '") }) it('should collapse whitespace', () => { const result = textExtractor.stripHtml('Hello
World
\n\t!
') expect(result).to.equal('Hello World !') }) it('should return empty string for empty input', () => { const result = textExtractor.stripHtml('') expect(result).to.equal('') }) }) describe('extractFromEpub', () => { let epubPath let tmpDir /** * Creates a minimal valid EPUB file using the system zip command */ function createTestEpub(destPath) { tmpDir = fs.mkdtempSync(Path.join(os.tmpdir(), 'epub-test-')) // Create directory structure fs.mkdirSync(Path.join(tmpDir, 'META-INF'), { recursive: true }) fs.mkdirSync(Path.join(tmpDir, 'OEBPS'), { recursive: true }) // mimetype fs.writeFileSync(Path.join(tmpDir, 'mimetype'), 'application/epub+zip') // container.xml fs.writeFileSync( Path.join(tmpDir, 'META-INF', 'container.xml'), `This is the first chapter content.
` ) // chapter2.xhtml fs.writeFileSync( Path.join(tmpDir, 'OEBPS', 'chapter2.xhtml'), `This is the second chapter.
` ) // Create ZIP (EPUB is a ZIP file) // First add mimetype uncompressed, then the rest execSync(`cd "${tmpDir}" && zip -0 -X "${destPath}" mimetype && zip -r -X "${destPath}" META-INF OEBPS`) } before(() => { epubPath = Path.join(os.tmpdir(), `test-epub-${Date.now()}.epub`) createTestEpub(epubPath) }) after(() => { try { fs.unlinkSync(epubPath) } catch (_) {} try { fs.rmSync(tmpDir, { recursive: true }) } catch (_) {} }) it('should extract chapters from a valid EPUB', async () => { const chapters = await textExtractor.extractFromEpub(epubPath) expect(chapters).to.be.an('array') expect(chapters.length).to.equal(2) expect(chapters[0].title).to.equal('Chapter 1') expect(chapters[0].text).to.include('first chapter content') expect(chapters[1].title).to.equal('Chapter 2') expect(chapters[1].text).to.include('second chapter') }) it('should throw for non-existent file', async () => { try { await textExtractor.extractFromEpub('/nonexistent/path/book.epub') expect.fail('Should have thrown') } catch (err) { expect(err).to.be.an('error') } }) }) })