import { afterEach, describe, expect, it } from 'vitest'; // под vitest `new URL(<пакет>, import.meta.url)` из pdfjs.ts не резолвится сборщиком — воркер берём по пути от корня проекта const WORKER = new URL('../../../node_modules/pdfjs-dist/legacy/build/pdf.worker.min.mjs', import.meta.url).href; /** Минимальный PDF из одной страницы с корректной таблицей xref. */ function minimalPdf(): Uint8Array { const objects = [ '<< /Type /Catalog /Pages 2 0 R >>', '<< /Type /Pages /Kids [3 0 R] /Count 1 >>', '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 100] >>', ]; let body = '%PDF-1.4\n'; const offsets: number[] = []; objects.forEach((obj, i) => { offsets.push(body.length); body += `${i + 1} 0 obj\n${obj}\nendobj\n`; }); const xref = body.length; body += `xref\n0 ${objects.length + 1}\n0000000000 65535 f \n`; for (const o of offsets) { body += `${String(o).padStart(10, '0')} 00000 n \n`; } body += `trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`; return new TextEncoder().encode(body); } type ToHexProto = { toHex?: unknown }; const proto = Uint8Array.prototype as ToHexProto; const nativeToHex = proto.toHex; afterEach(() => { if (nativeToHex === undefined) { delete proto.toHex; } else { proto.toHex = nativeToHex; } }); describe('pdfjs (сборка для браузеров без Uint8Array.prototype.toHex)', () => { // Яндекс Браузер (ядро Chromium < 140) не имеет Uint8Array.prototype.toHex; обычная сборка pdf.js 5.x вызывает его // при открытии документа (отпечаток) и падает «a.toHex is not a function». Legacy-сборка несёт полифилл. it('открывает PDF, когда Uint8Array.prototype.toHex отсутствует', async () => { delete proto.toHex; const { pdfjsLib } = await import('./pdfjs'); pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER; const doc = await pdfjsLib.getDocument({ data: minimalPdf() }).promise; try { expect(doc.numPages).toBe(1); } finally { await doc.destroy(); } }); });