test(09-02): add shell render tests for CertManagerPage (GREEN)

- 7 tests passing: title, all 4 tab labels, hidden password field, per-tab empty states
- Tests use vi.mock('next-intl') pattern per project convention (matches sidebar, VehicleTable tests)
- Validates T-09-02 threat mitigation: password field absent on initial render
This commit is contained in:
2026-07-01 23:23:17 +02:00
parent 42a41f77d0
commit 2cb01f743d
@@ -0,0 +1,101 @@
import { cleanup, render, screen, fireEvent } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
// Mock next-intl — provide certManager namespace keys
vi.mock('next-intl', () => ({
useTranslations: (ns: string) => (key: string) => {
const certManager: Record<string, string> = {
'title': 'Zertifikat-Manager',
'description': 'Zertifikate analysieren, aufteilen, zusammenfuehren und konvertieren.',
'tabs.inspect': 'Analysieren',
'tabs.split': 'Aufteilen',
'tabs.merge': 'Zusammenfuehren',
'tabs.convert': 'Konvertieren',
'dropZone.placeholder': 'Datei hierher ziehen oder klicken',
'dropZone.formats': '.pem, .crt, .cer, .der, .pfx, .p12, .p7b, .p7c',
'paste.placeholder': 'PEM-Inhalt einfuegen (-----BEGIN ...)',
'password.label': 'Passwort (PFX/P12)',
'or': 'oder',
'actions.inspect': 'Analysieren',
'actions.split': 'Aufteilen',
'actions.merge': 'Zusammenfuehren',
'actions.convert': 'Konvertieren',
'actions.download': 'Herunterladen',
'actions.processing': 'Wird verarbeitet...',
'emptyState.inspect': 'Kein Zertifikat geladen.',
'emptyState.inspectBody': 'Lade eine Datei hoch oder fuege PEM-Text ein.',
'emptyState.split': 'Keine Datei geladen.',
'emptyState.splitBody': 'Lade eine Fullchain- oder P7B-Datei hoch.',
'emptyState.merge': 'Keine Zertifikate ausgewaehlt.',
'emptyState.mergeBody': 'Lade mindestens zwei Dateien hoch.',
'emptyState.convert': 'Keine Datei geladen.',
'emptyState.convertBody': 'Lade eine Datei hoch und waehle ein Ausgabeformat.',
'error.generic': 'Verarbeitung fehlgeschlagen. Pruefe das Dateiformat oder das Passwort.',
'error.wrongPassword': 'Falsches Passwort. PFX/P12-Datei konnte nicht entschluesselt werden.',
'error.unknownFormat': 'Unbekanntes Format. Die Datei konnte nicht als Zertifikat erkannt werden.',
};
if (ns === 'certManager') {
return certManager[key] ?? key;
}
return key;
},
}));
import CertManagerPage from './page';
afterEach(() => {
cleanup();
});
describe('CertManagerPage shell', () => {
it('renders the page title and description', () => {
render(<CertManagerPage />);
expect(screen.getByText('Zertifikat-Manager')).toBeInTheDocument();
expect(screen.getByText('Zertifikate analysieren, aufteilen, zusammenfuehren und konvertieren.')).toBeInTheDocument();
});
it('renders all four tab labels', () => {
render(<CertManagerPage />);
expect(screen.getByText('Analysieren')).toBeInTheDocument();
expect(screen.getByText('Aufteilen')).toBeInTheDocument();
expect(screen.getByText('Zusammenfuehren')).toBeInTheDocument();
expect(screen.getByText('Konvertieren')).toBeInTheDocument();
});
it('does NOT render the password field on initial render (no PFX file selected)', () => {
render(<CertManagerPage />);
// Password field label should not be in document when no PFX is selected
expect(screen.queryByText('Passwort (PFX/P12)')).not.toBeInTheDocument();
});
it('shows Inspect tab empty state on initial render', () => {
render(<CertManagerPage />);
expect(screen.getByText('Kein Zertifikat geladen.')).toBeInTheDocument();
expect(screen.getByText('Lade eine Datei hoch oder fuege PEM-Text ein.')).toBeInTheDocument();
});
it('shows Split tab empty state when Split tab is active', () => {
render(<CertManagerPage />);
// Click the "Aufteilen" tab button (second one in nav)
const tabButtons = screen.getAllByText('Aufteilen');
// The tab nav button is the one that triggers tab change
fireEvent.click(tabButtons[0]);
expect(screen.getByText('Keine Datei geladen.')).toBeInTheDocument();
expect(screen.getByText('Lade eine Fullchain- oder P7B-Datei hoch.')).toBeInTheDocument();
});
it('shows Merge tab empty state when Merge tab is active', () => {
render(<CertManagerPage />);
fireEvent.click(screen.getByText('Zusammenfuehren'));
expect(screen.getByText('Keine Zertifikate ausgewaehlt.')).toBeInTheDocument();
expect(screen.getByText('Lade mindestens zwei Dateien hoch.')).toBeInTheDocument();
});
it('shows Convert tab empty state when Convert tab is active', () => {
render(<CertManagerPage />);
// "Konvertieren" appears once as tab label
fireEvent.click(screen.getByText('Konvertieren'));
expect(screen.getAllByText('Keine Datei geladen.').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('Lade eine Datei hoch und waehle ein Ausgabeformat.')).toBeInTheDocument();
});
});