Files
bentopdf/src/tests/tesseract-runtime.test.ts
T
alam00000 77da6d7a7d feat: integrate Tesseract.js with improved language availability and font handling
- Refactored OCR page recognition to utilize a configured Tesseract worker.
- Added functions to manage font URLs and asset filenames based on language.
- Implemented language availability checks and error handling for unsupported languages.
- Enhanced PDF workflow to display available OCR languages and handle user selections.
- Introduced utility functions for resolving Tesseract asset configurations.
- Added tests for OCR functionality, font loading, and Tesseract runtime behavior.
- Updated global types to include environment variables for Tesseract and font configurations.
2026-03-14 15:50:30 +05:30

129 lines
4.0 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
const { createWorker } = vi.hoisted(() => ({
createWorker: vi.fn(),
}));
vi.mock('tesseract.js', () => ({
default: {
createWorker,
},
}));
import {
buildTesseractWorkerOptions,
createConfiguredTesseractWorker,
getIncompleteTesseractOverrideKeys,
hasCompleteTesseractOverrides,
hasConfiguredTesseractOverrides,
resolveTesseractAssetConfig,
} from '../js/utils/tesseract-runtime';
import {
assertTesseractLanguagesAvailable,
getAvailableTesseractLanguageEntries,
getUnavailableTesseractLanguages,
UnsupportedOcrLanguageError,
} from '../js/utils/tesseract-language-availability';
describe('tesseract-runtime', () => {
beforeEach(() => {
createWorker.mockReset();
});
it('normalizes self-hosted OCR asset URLs', () => {
const config = resolveTesseractAssetConfig({
VITE_TESSERACT_WORKER_URL:
'https://internal.example.com/ocr/worker.min.js/',
VITE_TESSERACT_CORE_URL: 'https://internal.example.com/ocr/core/',
VITE_TESSERACT_LANG_URL: 'https://internal.example.com/ocr/lang-data/',
});
expect(config).toEqual({
workerPath: 'https://internal.example.com/ocr/worker.min.js',
corePath: 'https://internal.example.com/ocr/core',
langPath: 'https://internal.example.com/ocr/lang-data',
});
expect(hasConfiguredTesseractOverrides(config)).toBe(true);
expect(hasCompleteTesseractOverrides(config)).toBe(true);
});
it('returns logger-only options when no self-hosted OCR assets are configured', () => {
const logger = vi.fn();
expect(buildTesseractWorkerOptions(logger, {})).toEqual({ logger });
expect(
hasConfiguredTesseractOverrides(resolveTesseractAssetConfig({}))
).toBe(false);
});
it('throws on partial OCR asset configuration', () => {
const env = {
VITE_TESSERACT_WORKER_URL:
'https://internal.example.com/ocr/worker.min.js',
VITE_TESSERACT_CORE_URL: 'https://internal.example.com/ocr/core',
};
expect(
getIncompleteTesseractOverrideKeys(resolveTesseractAssetConfig(env))
).toEqual(['VITE_TESSERACT_LANG_URL']);
expect(() => buildTesseractWorkerOptions(undefined, env)).toThrow(
'Self-hosted OCR assets are partially configured'
);
});
it('passes configured OCR asset URLs to Tesseract.createWorker', async () => {
const logger = vi.fn();
createWorker.mockResolvedValue({ id: 'worker' });
await createConfiguredTesseractWorker('eng', 1, logger, {
VITE_TESSERACT_WORKER_URL:
'https://internal.example.com/ocr/worker.min.js',
VITE_TESSERACT_CORE_URL: 'https://internal.example.com/ocr/core',
VITE_TESSERACT_LANG_URL: 'https://internal.example.com/ocr/lang-data',
});
expect(createWorker).toHaveBeenCalledWith('eng', 1, {
logger,
workerPath: 'https://internal.example.com/ocr/worker.min.js',
corePath: 'https://internal.example.com/ocr/core',
langPath: 'https://internal.example.com/ocr/lang-data',
gzip: true,
});
});
it('filters OCR language entries when the build restricts bundled languages', () => {
expect(
getAvailableTesseractLanguageEntries({
VITE_TESSERACT_AVAILABLE_LANGUAGES: 'eng,deu',
})
).toEqual([
['eng', 'English'],
['deu', 'German'],
]);
});
it('reports unavailable OCR languages for restricted air-gap builds', () => {
expect(
getUnavailableTesseractLanguages('eng+fra', {
VITE_TESSERACT_AVAILABLE_LANGUAGES: 'eng,deu',
})
).toEqual(['fra']);
expect(() =>
assertTesseractLanguagesAvailable('eng+fra', {
VITE_TESSERACT_AVAILABLE_LANGUAGES: 'eng,deu',
})
).toThrow(UnsupportedOcrLanguageError);
});
it('blocks worker creation when OCR requests an unbundled language', async () => {
await expect(
createConfiguredTesseractWorker('fra', 1, undefined, {
VITE_TESSERACT_AVAILABLE_LANGUAGES: 'eng,deu',
})
).rejects.toThrow('This BentoPDF build only bundles OCR data for');
expect(createWorker).not.toHaveBeenCalled();
});
});