From f39f16d96c619010c42c28563c0a50571bc48153 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 12 May 2026 13:01:50 +0200 Subject: [PATCH] =?UTF-8?q?test(pdf-renderer):=20eliminate=20real=20pdfjs-?= =?UTF-8?q?dist=20loading=20from=20browser=20tests=20=E2=80=94=20use=20fak?= =?UTF-8?q?e=20libLoader=20for=20all=20init()=20calls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five tests in usePdfRenderer.svelte.test.ts called createPdfRenderer() without a libLoader, causing init() to dynamically import pdfjs-dist in the browser. Every dynamic import goes through Playwright's route handler, which calls resolveManualMock via birpc to check for mocks. If the RPC closes during teardown while one of these imports is in flight, the birpc race fires — even though pdfjs-dist was never explicitly vi.mock()-ed. Replace all bare createPdfRenderer() calls that invoke init() with createPdfRenderer(makeFakeLibLoader()), identical to the pattern already used in PdfViewer.svelte.test.ts. No real module loads, no route-handler calls, no birpc exposure. Co-Authored-By: Claude Sonnet 4.6 --- .../viewer/usePdfRenderer.svelte.test.ts | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts b/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts index 7bdf387d..2a1c9f90 100644 --- a/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts +++ b/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts @@ -1,6 +1,25 @@ import { describe, it, expect, vi } from 'vitest'; +import type { LibLoader } from './usePdfRenderer.svelte'; import { createPdfRenderer } from './usePdfRenderer.svelte'; +function makeFakeLibLoader(): LibLoader { + return vi.fn().mockResolvedValue([ + { + GlobalWorkerOptions: { workerSrc: '' }, + getDocument: vi.fn().mockReturnValue({ + promise: Promise.resolve({ numPages: 1, getPage: vi.fn() }) + }), + TextLayer: class { + render() { + return Promise.resolve(); + } + cancel() {} + } + } as unknown as typeof import('pdfjs-dist'), + { default: '' } + ] as const); +} + // Note: init() and loadDocument() require pdfjsLib (browser module). // These tests cover pure state logic only — bounds clamping and zoom limits. @@ -122,39 +141,36 @@ describe('createPdfRenderer', () => { expect(r.scale).toBe(before); }); - it('init() is callable and resolves without throwing in browser env', async () => { - const r = createPdfRenderer(); + it('init() sets pdfjsReady to true when loader resolves', async () => { + const r = createPdfRenderer(makeFakeLibLoader()); await expect(r.init()).resolves.toBeUndefined(); - // pdfjsReady is now true expect(r.pdfjsReady).toBe(true); }); - it('after init, loadDocument with a bogus URL sets error', async () => { - const r = createPdfRenderer(); + it('after init, loadDocument completes and loading returns to false', async () => { + const r = createPdfRenderer(makeFakeLibLoader()); await r.init(); - await r.loadDocument('about:invalid-pdf'); - // Either error is set or loading flips back to false — both are acceptable + await r.loadDocument('/some/path'); expect(r.loading).toBe(false); }); it('renderCurrentPage is a no-op when canvasEl is null but pdfjsLib is initialized', async () => { - const r = createPdfRenderer(); + const r = createPdfRenderer(makeFakeLibLoader()); await r.init(); // Without setElements, canvasEl is null — early return await expect(r.renderCurrentPage()).resolves.toBeUndefined(); }); it('renderCurrentPage is a no-op when textLayerEl is null', async () => { - const r = createPdfRenderer(); + const r = createPdfRenderer(makeFakeLibLoader()); await r.init(); - // Set only canvas, leave textLayer unset is not directly testable; - // confirm calling without elements wired returns early. + // Without setElements, textLayerEl is null — early return await expect(r.renderCurrentPage()).resolves.toBeUndefined(); }); it('init() can be called multiple times safely', async () => { - const r = createPdfRenderer(); + const r = createPdfRenderer(makeFakeLibLoader()); await r.init(); await r.init(); expect(r.pdfjsReady).toBe(true);