import { describe, it, expect, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import PasswordChangeForm from './PasswordChangeForm.svelte'; afterEach(cleanup); describe('PasswordChangeForm', () => { it('renders the three password inputs and a save button by default', async () => { render(PasswordChangeForm, { props: { form: null } }); await expect.element(page.getByRole('heading', { name: /passwort ändern/i })).toBeVisible(); await expect.element(page.getByRole('button', { name: /speichern/i })).toBeVisible(); }); it('does not render any banner when form is null', async () => { render(PasswordChangeForm, { props: { form: null } }); await expect.element(page.getByText(/erfolgreich geändert/i)).not.toBeInTheDocument(); await expect.element(page.getByText(/stimmen nicht überein/i)).not.toBeInTheDocument(); }); it('shows the success banner when form.passwordSuccess is true', async () => { render(PasswordChangeForm, { props: { form: { passwordSuccess: true } } }); await expect.element(page.getByText('Passwort erfolgreich geändert.')).toBeVisible(); }); it('shows the localised mismatch message for the PASSWORDS_DO_NOT_MATCH error code', async () => { render(PasswordChangeForm, { props: { form: { passwordError: 'PASSWORDS_DO_NOT_MATCH' } } }); await expect .element(page.getByText('Die neuen Passwörter stimmen nicht überein.')) .toBeVisible(); }); it('shows the raw error message for any non-matching error code', async () => { render(PasswordChangeForm, { props: { form: { passwordError: 'Server-side error message' } } }); await expect.element(page.getByText('Server-side error message')).toBeVisible(); }); it('declares POST as the form method and routes to the changePassword action', async () => { render(PasswordChangeForm, { props: { form: null } }); const form = document.querySelector('form'); expect(form?.getAttribute('method')).toBe('POST'); expect(form?.getAttribute('action')).toBe('?/changePassword'); }); });