fix(document): configure pdf.js wasmUrl so CCITT/JBIG2 scans stop rendering blank (#708) #713

Merged
marcel merged 15 commits from feat/issue-708-pdfjs-wasmurl into main 2026-06-01 21:25:57 +02:00
2 changed files with 27 additions and 4 deletions
Showing only changes of commit 229c1b0539 - Show all commits

View File

@@ -7,11 +7,22 @@ import { m } from '$lib/paraglide/messages.js';
afterEach(cleanup);
function makeFailingLibLoader() {
// Document loads fine, but rendering the page rejects with a non-cancellation
// error — exactly the wasm-decode failure class from #708. Exercises the real
// renderCurrentPage path, not the load path.
function makeRenderFailingLibLoader() {
const page = {
getViewport: vi.fn().mockReturnValue({ width: 100, height: 100 }),
render: vi.fn().mockReturnValue({
promise: Promise.reject(new Error('JBig2 failed to initialize')),
cancel: vi.fn()
}),
streamTextContent: vi.fn().mockReturnValue(new ReadableStream())
};
const lib = {
GlobalWorkerOptions: { workerSrc: '' },
getDocument: vi.fn().mockReturnValue({
promise: Promise.reject(new Error('JBig2 failed to initialize'))
promise: Promise.resolve({ numPages: 1, getPage: vi.fn().mockResolvedValue(page) })
}),
TextLayer: class {
render() {
@@ -24,16 +35,27 @@ function makeFailingLibLoader() {
}
describe('PdfViewer — render failure', () => {
it('shows the localized failure message and a download link, not a blank canvas', async () => {
it('shows the localized failure message and a download link when the page render rejects', async () => {
render(PdfViewer, {
url: '/api/documents/test/file',
documentId: 'test',
libLoader: makeFailingLibLoader()
libLoader: makeRenderFailingLibLoader()
});
await expect.element(page.getByText(m.doc_render_failed())).toBeVisible();
await expect.element(page.getByRole('link', { name: m.doc_download_link() })).toBeVisible();
});
it('does not show the failure message when the page renders successfully', async () => {
render(PdfViewer, {
url: '/api/documents/test/file',
documentId: 'test',
libLoader: makeFakeLibLoader()
});
await expect.element(page.getByRole('button', { name: 'Zurück' })).toBeVisible();
expect(document.body.textContent).not.toContain(m.doc_render_failed());
});
});
describe('PdfViewer — empty / error states', () => {

View File

@@ -111,6 +111,7 @@ export function createPdfRenderer(libLoader: LibLoader = defaultLibLoader) {
// A real decode/render failure (e.g. a wasm decoder that could not
// initialise) — surface a localized message instead of leaving a
// silent blank canvas. Never leak the raw pdf.js error text.
renderTask = null;
error = m.doc_render_failed();
return;
}