test(07-06): add failing SMTP settings form tests (RED — DKV-05)
Tessera CI/CD / Build & Deploy (push) Blocked by required conditions
Tessera CI/CD / Lint & Type Check (push) Successful in 38s
Tessera CI/CD / Tests (push) Waiting to run

- 5 Vitest tests for SmtpSettingsForm: load config, save, test success/failure, password toggle
- Mocks @/lib/settings-api (fetchSmtp/saveSmtp/testSmtp) and next-intl
- Mirrors calendar-settings.test.tsx mocking pattern
- RED: SmtpSettingsForm does not yet exist
This commit is contained in:
2026-06-27 17:00:27 +02:00
parent 5c191c8d10
commit a96d79ad52
@@ -0,0 +1,192 @@
import { cleanup, render, screen, waitFor, fireEvent } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
// Mock next-intl — returns a short readable string for each key
vi.mock('next-intl', () => ({
useTranslations: (ns: string) => (key: string) => {
const map: Record<string, Record<string, string>> = {
settings: {
'smtp.title': 'SMTP-Konfiguration',
'smtp.host': 'Host',
'smtp.port': 'Port',
'smtp.encryption': 'Verschluesselung',
'smtp.username': 'Benutzername',
'smtp.password': 'Passwort',
'smtp.fromAddress': 'Absenderadresse (Von)',
'smtp.fromAddressHelp': 'Die E-Mail-Adresse, die als Absender angezeigt wird.',
'smtp.save': 'Einstellungen speichern',
'smtp.test': 'Verbindung testen',
'smtp.showPassword': 'Passwort anzeigen',
'smtp.hidePassword': 'Passwort verbergen',
'smtp.testTesting': 'Verbindung wird getestet...',
'smtp.testSuccess': 'Verbindung erfolgreich',
'smtp.testFailed': 'Verbindung fehlgeschlagen',
},
};
return map[ns]?.[key] ?? key;
},
}));
// Mock @/lib/settings-api
const mockFetchSmtp = vi.fn();
const mockSaveSmtp = vi.fn();
const mockTestSmtp = vi.fn();
vi.mock('@/lib/settings-api', () => ({
fetchSmtp: (...args: unknown[]) => mockFetchSmtp(...args),
saveSmtp: (...args: unknown[]) => mockSaveSmtp(...args),
testSmtp: (...args: unknown[]) => mockTestSmtp(...args),
}));
afterEach(() => {
cleanup();
vi.restoreAllMocks();
});
describe('SmtpSettingsForm', () => {
it('loads existing config and populates fields (password stays blank)', async () => {
mockFetchSmtp.mockResolvedValue({
host: 'smtp.example.com',
port: 587,
encryption: 'starttls',
username: 'user@example.com',
fromAddress: 'tessera@example.com',
hasPassword: true,
});
const { SmtpSettingsForm } = await import(
'@/components/settings/smtp-settings-form'
);
render(<SmtpSettingsForm />);
await waitFor(() => {
expect(
(screen.getByLabelText('Host') as HTMLInputElement).value,
).toBe('smtp.example.com');
});
expect((screen.getByLabelText('Port') as HTMLInputElement).value).toBe(
'587',
);
expect(
(screen.getByLabelText('Benutzername') as HTMLInputElement).value,
).toBe('user@example.com');
expect(
(screen.getByLabelText('Absenderadresse (Von)') as HTMLInputElement)
.value,
).toBe('tessera@example.com');
// T-07-17: password must never be pre-filled from server data
expect(
(screen.getByLabelText('Passwort') as HTMLInputElement).value,
).toBe('');
});
it('calls saveSmtp with form values on submit', async () => {
mockFetchSmtp.mockResolvedValue({
host: 'smtp.example.com',
port: 587,
encryption: 'starttls',
username: 'user@example.com',
fromAddress: 'tessera@example.com',
hasPassword: false,
});
mockSaveSmtp.mockResolvedValue({
host: 'smtp.example.com',
port: 587,
encryption: 'starttls',
username: 'user@example.com',
fromAddress: 'tessera@example.com',
hasPassword: false,
});
const { SmtpSettingsForm } = await import(
'@/components/settings/smtp-settings-form'
);
render(<SmtpSettingsForm />);
await waitFor(() => {
expect(
(screen.getByLabelText('Host') as HTMLInputElement).value,
).toBe('smtp.example.com');
});
fireEvent.click(screen.getByText('Einstellungen speichern'));
await waitFor(() => {
expect(mockSaveSmtp).toHaveBeenCalledWith(
expect.objectContaining({
host: 'smtp.example.com',
port: 587,
encryption: 'starttls',
}),
);
});
});
it('shows success message when testSmtp resolves { success: true }', async () => {
mockFetchSmtp.mockResolvedValue(null);
mockTestSmtp.mockResolvedValue({ success: true });
const { SmtpSettingsForm } = await import(
'@/components/settings/smtp-settings-form'
);
render(<SmtpSettingsForm />);
await waitFor(() =>
expect(screen.getByText('Verbindung testen')).toBeInTheDocument(),
);
fireEvent.click(screen.getByText('Verbindung testen'));
await waitFor(() => {
expect(
screen.getByText('Verbindung erfolgreich'),
).toBeInTheDocument();
});
});
it('shows error message when testSmtp resolves { success: false }', async () => {
mockFetchSmtp.mockResolvedValue(null);
mockTestSmtp.mockResolvedValue({ success: false });
const { SmtpSettingsForm } = await import(
'@/components/settings/smtp-settings-form'
);
render(<SmtpSettingsForm />);
await waitFor(() =>
expect(screen.getByText('Verbindung testen')).toBeInTheDocument(),
);
fireEvent.click(screen.getByText('Verbindung testen'));
await waitFor(() => {
expect(
screen.getByText('Verbindung fehlgeschlagen'),
).toBeInTheDocument();
});
});
it('toggles password input type between password and text', async () => {
mockFetchSmtp.mockResolvedValue(null);
const { SmtpSettingsForm } = await import(
'@/components/settings/smtp-settings-form'
);
render(<SmtpSettingsForm />);
await waitFor(() =>
expect(screen.getByLabelText('Passwort')).toBeInTheDocument(),
);
const passwordInput = screen.getByLabelText('Passwort') as HTMLInputElement;
expect(passwordInput.type).toBe('password');
const toggleButton = screen.getByRole('button', {
name: 'Passwort anzeigen',
});
fireEvent.click(toggleButton);
expect(passwordInput.type).toBe('text');
});
});