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'); + }); +});