From 98335411af946b97a00914a1cd0075c65f839066 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sat, 9 May 2026 20:03:59 +0200 Subject: [PATCH] test(routes): cover +error and forgot-password page branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +error.svelte: vi.mock('$app/state') drives the page state so each test can assert one of the three rendering branches — populated error message, distinct status code, and the 'Internal Error' fallback when page.error is null. forgot-password/+page.svelte: prop-driven tests for the four states — default form, success banner, error message inside the form, and the back-to-login link href. Refs #496. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/routes/error.svelte.test.ts | 52 +++++++++++++++++++ .../forgot-password/page.svelte.test.ts | 46 ++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 frontend/src/routes/error.svelte.test.ts create mode 100644 frontend/src/routes/forgot-password/page.svelte.test.ts diff --git a/frontend/src/routes/error.svelte.test.ts b/frontend/src/routes/error.svelte.test.ts new file mode 100644 index 00000000..097dc3f6 --- /dev/null +++ b/frontend/src/routes/error.svelte.test.ts @@ -0,0 +1,52 @@ +import { describe, it, expect, vi, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import { page as browserPage } from 'vitest/browser'; + +const mockPage = { + status: 500, + error: { message: 'Internal Error' } as { message: string } | null +}; + +vi.mock('$app/state', () => ({ + get page() { + return mockPage; + } +})); + +afterEach(cleanup); + +async function loadComponent() { + return (await import('./+error.svelte')).default; +} + +describe('+error.svelte', () => { + it('renders the page status code prominently', async () => { + mockPage.status = 404; + mockPage.error = { message: 'Not Found' }; + + const ErrorPage = await loadComponent(); + render(ErrorPage); + + await expect.element(browserPage.getByText('404')).toBeVisible(); + }); + + it('renders the error message text from page.error.message', async () => { + mockPage.status = 500; + mockPage.error = { message: 'Database unavailable' }; + + const ErrorPage = await loadComponent(); + render(ErrorPage); + + await expect.element(browserPage.getByText('Database unavailable')).toBeVisible(); + }); + + it('falls back to the literal "Internal Error" when page.error is null', async () => { + mockPage.status = 500; + mockPage.error = null; + + const ErrorPage = await loadComponent(); + render(ErrorPage); + + await expect.element(browserPage.getByText('Internal Error')).toBeVisible(); + }); +}); diff --git a/frontend/src/routes/forgot-password/page.svelte.test.ts b/frontend/src/routes/forgot-password/page.svelte.test.ts new file mode 100644 index 00000000..d2683059 --- /dev/null +++ b/frontend/src/routes/forgot-password/page.svelte.test.ts @@ -0,0 +1,46 @@ +import { describe, it, expect, afterEach } from 'vitest'; +import { cleanup, render } from 'vitest-browser-svelte'; +import { page } from 'vitest/browser'; +import ForgotPasswordPage from './+page.svelte'; + +afterEach(cleanup); + +describe('forgot-password page', () => { + it('renders the email input form when no form prop is provided', async () => { + render(ForgotPasswordPage, { props: { form: undefined } }); + + await expect.element(page.getByRole('heading', { name: /passwort vergessen/i })).toBeVisible(); + await expect.element(page.getByLabelText('E-Mail-Adresse')).toBeVisible(); + await expect.element(page.getByRole('button', { name: /link anfordern/i })).toBeVisible(); + }); + + it('shows the success banner and hides the form when form.success is true', async () => { + render(ForgotPasswordPage, { props: { form: { success: true } } }); + + await expect + .element( + page.getByText( + 'Falls ein Konto mit dieser E-Mail-Adresse existiert, erhalten Sie in Kürze eine E-Mail mit einem Link zum Zurücksetzen Ihres Passworts.' + ) + ) + .toBeVisible(); + await expect + .element(page.getByRole('button', { name: /link anfordern/i })) + .not.toBeInTheDocument(); + }); + + it('shows the error message inside the form when form.error is set', async () => { + render(ForgotPasswordPage, { props: { form: { error: 'Server unreachable' } } }); + + await expect.element(page.getByText('Server unreachable')).toBeVisible(); + await expect.element(page.getByRole('button', { name: /link anfordern/i })).toBeVisible(); + }); + + it('always offers a back-to-login link', async () => { + render(ForgotPasswordPage, { props: { form: undefined } }); + + await expect + .element(page.getByRole('link', { name: /zurück zum login/i })) + .toHaveAttribute('href', '/login'); + }); +});