diff --git a/frontend/src/lib/document/viewer/PdfViewer.svelte.test.ts b/frontend/src/lib/document/viewer/PdfViewer.svelte.test.ts index a4b49ba9..17d1827c 100644 --- a/frontend/src/lib/document/viewer/PdfViewer.svelte.test.ts +++ b/frontend/src/lib/document/viewer/PdfViewer.svelte.test.ts @@ -1,40 +1,11 @@ import { describe, it, expect, vi, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; -import type { LibLoader } from '$lib/document/viewer/usePdfRenderer.svelte'; import PdfViewer from './PdfViewer.svelte'; +import { makeFakeLibLoader } from './testHelpers'; afterEach(cleanup); -function makeFakePdfjsLib() { - class TextLayerMock { - render() { - return Promise.resolve(); - } - cancel() {} - } - - return { - GlobalWorkerOptions: { workerSrc: '' }, - getDocument: vi.fn().mockReturnValue({ - promise: Promise.resolve({ - numPages: 2, - getPage: vi.fn().mockResolvedValue({ - getViewport: vi.fn().mockReturnValue({ width: 595, height: 842 }), - render: vi.fn().mockReturnValue({ promise: Promise.resolve() }), - streamTextContent: vi.fn().mockReturnValue(new ReadableStream()) - }) - }) - }), - TextLayer: TextLayerMock - } as unknown as typeof import('pdfjs-dist'); -} - -function makeFakeLibLoader(): LibLoader { - const fakePdfjs = makeFakePdfjsLib(); - return vi.fn().mockResolvedValue([fakePdfjs, { default: '' }] as const); -} - describe('PdfViewer — empty / error states', () => { it('renders the no-file placeholder when url is empty', async () => { render(PdfViewer, { url: '', libLoader: makeFakeLibLoader() }); @@ -293,18 +264,18 @@ describe('PdfViewer — loaded state', () => { it('shows previous and next page navigation buttons', async () => { render(PdfViewer, { url: '/api/documents/test-id/file', libLoader: makeFakeLibLoader() }); - await expect.element(page.getByRole('button', { name: /zurück/i })).toBeInTheDocument(); - await expect.element(page.getByRole('button', { name: /weiter/i })).toBeInTheDocument(); + await expect.element(page.getByRole('button', { name: /zurück/i })).toBeVisible(); + await expect.element(page.getByRole('button', { name: /weiter/i })).toBeVisible(); }); it('shows zoom controls', async () => { render(PdfViewer, { url: '/api/documents/test-id/file', libLoader: makeFakeLibLoader() }); - await expect.element(page.getByRole('button', { name: /vergrößern/i })).toBeInTheDocument(); - await expect.element(page.getByRole('button', { name: /verkleinern/i })).toBeInTheDocument(); + await expect.element(page.getByRole('button', { name: /vergrößern/i })).toBeVisible(); + await expect.element(page.getByRole('button', { name: /verkleinern/i })).toBeVisible(); }); it('displays the page counter once the PDF has loaded', async () => { render(PdfViewer, { url: '/api/documents/test-id/file', libLoader: makeFakeLibLoader() }); - await expect.element(page.getByText(/1\s*\/\s*2/)).toBeInTheDocument(); + await expect.element(page.getByText(/1\s*\/\s*2/)).toBeVisible(); }); }); diff --git a/frontend/src/lib/document/viewer/testHelpers.ts b/frontend/src/lib/document/viewer/testHelpers.ts new file mode 100644 index 00000000..f7e5c295 --- /dev/null +++ b/frontend/src/lib/document/viewer/testHelpers.ts @@ -0,0 +1,31 @@ +import { vi } from 'vitest'; +import type { LibLoader } from './usePdfRenderer.svelte'; + +export function makeFakePdfjsLib() { + class TextLayerMock { + render() { + return Promise.resolve(); + } + cancel() {} + } + + return { + GlobalWorkerOptions: { workerSrc: '' }, + getDocument: vi.fn().mockReturnValue({ + promise: Promise.resolve({ + numPages: 2, + getPage: vi.fn().mockResolvedValue({ + getViewport: vi.fn().mockReturnValue({ width: 595, height: 842 }), + render: vi.fn().mockReturnValue({ promise: Promise.resolve() }), + streamTextContent: vi.fn().mockReturnValue(new ReadableStream()) + }) + }) + }), + TextLayer: TextLayerMock + } as unknown as typeof import('pdfjs-dist'); +} + +export function makeFakeLibLoader(): LibLoader { + const fakePdfjs = makeFakePdfjsLib(); + return vi.fn().mockResolvedValue([fakePdfjs, { default: '' }] as const); +} diff --git a/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts b/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts index 2a1c9f90..6b48c3f8 100644 --- a/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts +++ b/frontend/src/lib/document/viewer/usePdfRenderer.svelte.test.ts @@ -1,24 +1,6 @@ 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); -} +import { makeFakeLibLoader } from './testHelpers'; // Note: init() and loadDocument() require pdfjsLib (browser module). // These tests cover pure state logic only — bounds clamping and zoom limits. @@ -222,4 +204,24 @@ describe('createPdfRenderer', () => { await r.init(); expect(fakeLoader).toHaveBeenCalledOnce(); }); + + it('loadDocument sets error and loading=false when getDocument().promise rejects', async () => { + const failingLib = { + GlobalWorkerOptions: { workerSrc: '' }, + getDocument: vi.fn().mockReturnValue({ + promise: Promise.reject(new Error('PDF not found')) + }), + TextLayer: class { + render() { + return Promise.resolve(); + } + cancel() {} + } + } as unknown as typeof import('pdfjs-dist'); + const r = createPdfRenderer(vi.fn().mockResolvedValue([failingLib, { default: '' }] as const)); + await r.init(); + await r.loadDocument('/bad/path'); + expect(r.loading).toBe(false); + expect(r.error).toBe('PDF not found'); + }); });