Files
familienarchiv/frontend/src/routes/login/page.svelte.spec.ts
Marcel d816e94a90 feat(auth): migrate frontend from username to email-only authentication
- Login page: email input replaces username field (type=email, name=email)
- Login server action: reads email, uses i18n error for missing credentials
- AccountSection: email input (type=email) replaces username text field
- New user server action: sends email as required field, drops username
- UsersListPanel: displays and searches by email instead of username
- Admin edit user page: heading and delete confirm use email
- Profile page: fullName fallback uses email, drops @username display
- app.d.ts: email required on User, username removed
- Generated API types: AppUser.email required, username removed; CreateUserRequest.email required, username removed
- i18n: login_label_email, login_error_missing_credentials, admin_col_login updated (de/en/es)
- errors.ts: MISSING_CREDENTIALS → login_error_missing_credentials

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:55 +02:00

99 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { afterEach, describe, expect, it } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import LoginPage from './+page.svelte';
const tick = () => new Promise((r) => setTimeout(r, 0));
afterEach(cleanup);
describe('Login page rendering', () => {
it('renders the page title', async () => {
render(LoginPage, {});
await expect
.element(page.getByRole('link', { name: 'Familienarchiv' }).first())
.toBeInTheDocument();
await page.screenshot({ path: 'test-results/screenshots/login-default.png' });
});
it('renders the submit button', async () => {
render(LoginPage, {});
await expect.element(page.getByRole('button', { name: 'Anmelden' })).toBeInTheDocument();
});
it('renders the email input', async () => {
render(LoginPage, {});
await tick();
const input = document.querySelector<HTMLInputElement>('input[name="email"]');
expect(input).not.toBeNull();
});
it('renders the password input', async () => {
render(LoginPage, {});
await tick();
const input = document.querySelector<HTMLInputElement>('input[name="password"]');
expect(input).not.toBeNull();
});
it('email field is required', async () => {
render(LoginPage, {});
await tick();
const input = document.querySelector<HTMLInputElement>('input[name="email"]');
expect(input?.required).toBe(true);
});
it('password field is required', async () => {
render(LoginPage, {});
await tick();
const input = document.querySelector<HTMLInputElement>('input[name="password"]');
expect(input?.required).toBe(true);
});
it('email field has type="email"', async () => {
render(LoginPage, {});
await tick();
const input = document.querySelector<HTMLInputElement>('input[name="email"]');
expect(input?.type).toBe('email');
});
it('password field has type="password"', async () => {
render(LoginPage, {});
await tick();
const input = document.querySelector<HTMLInputElement>('input[name="password"]');
expect(input?.type).toBe('password');
});
it('form submits to the login action', async () => {
render(LoginPage, {});
await tick();
const form = document.querySelector<HTMLFormElement>('form');
expect(form?.action).toMatch(/\?\/login$/);
});
});
describe('Login page error state', () => {
it('shows no error when form is undefined', async () => {
render(LoginPage, {});
await tick();
expect(document.querySelector('.text-red-600')).toBeNull();
});
it('shows no error when form has no error property', async () => {
render(LoginPage, { form: {} });
await tick();
expect(document.querySelector('.text-red-600')).toBeNull();
});
it('displays the error message from the form action', async () => {
render(LoginPage, { form: { error: 'Ungültige Anmeldedaten.' } });
await expect.element(page.getByText('Ungültige Anmeldedaten.')).toBeInTheDocument();
await page.screenshot({ path: 'test-results/screenshots/login-error.png' });
});
it('applies red styling to the error text', async () => {
render(LoginPage, { form: { error: 'Fehler!' } });
await tick();
expect(document.querySelector('.text-red-600')).not.toBeNull();
});
});