fix(web): Oberflaechentexte ohne Mandanten-Begriff, Organisationsauswahl im Marktplatz nur bei mehreren
Tessera CI/CD / Lint & Type Check (push) Successful in 57s
Tessera CI/CD / Tests (push) Successful in 1m51s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 19s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m23s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-03 02:58:50 +02:00
parent 2053dbac28
commit 3562b154f0
7 changed files with 47 additions and 31 deletions
@@ -13,7 +13,7 @@ const messages: Record<string, Record<string, unknown>> = {
title: 'Freigaben-Matrix',
searchPlaceholder: 'Module oder Gruppen durchsuchen...',
emptyModules:
'Es sind noch keine Module für diesen Mandanten aktiviert. Aktiviere zuerst ein Modul unter Module.',
'Es sind noch keine Module aktiviert. Aktiviere zuerst ein Modul unter Module.',
emptyModulesLink: 'Zu Module',
adminNote:
'ADMIN und SUPER_ADMIN haben immer Zugriff auf alle aktiven Module — diese Matrix betrifft nur die Rolle USER.',
@@ -153,7 +153,7 @@ describe('AdminModuleGrantsPage (Permission-Matrix)', () => {
render(<AdminModuleGrantsPage />);
await waitFor(() => {
expect(screen.getByText(/keine Module für diesen Mandanten aktiviert/)).toBeInTheDocument();
expect(screen.getByText(/noch keine Module aktiviert/)).toBeInTheDocument();
});
const link = screen.getByText('Zu Module');
expect(link.closest('a')).toHaveAttribute('href', '/admin/modules');
@@ -34,7 +34,8 @@ export function TenantContextSelector() {
.finally(() => setLoading(false));
}, [isSuperAdmin]);
if (!isSuperAdmin) return null;
// Nur bei mehreren Organisationen sinnvoll; im Ein-Firmen-Betrieb ausgeblendet.
if (!isSuperAdmin || (!loading && tenants.length <= 1)) return null;
return (
<div className="flex flex-wrap items-center gap-3 rounded-lg bg-card px-4 py-3 shadow-sm dark:border dark:border-border">
@@ -25,7 +25,7 @@ vi.mock('next-intl', () => ({
errorLoad: 'Module konnten nicht geladen werden.',
toastActivated: 'Modul erfolgreich aktiviert',
accessDenied: 'Zugriff verweigert',
tenantContextLabel: 'Mandanten-Kontext',
tenantContextLabel: 'Organisation',
};
let result = translations[key] ?? key;
if (params) {
@@ -27,7 +27,7 @@ vi.mock('next-intl', () => ({
toastActivated: 'Modul erfolgreich aktiviert',
toastDeactivated: 'Modul erfolgreich deaktiviert',
accessDenied: 'Zugriff verweigert',
tenantContextLabel: 'Mandanten-Kontext',
tenantContextLabel: 'Organisation',
deactivateDialogTitle: 'Modul deaktivieren',
deactivateDialogBody: 'Moechten Sie {moduleName} fuer diesen Mandanten deaktivieren?',
deactivateDialogConfirm: 'Deaktivieren',
@@ -118,6 +118,21 @@ describe('TenantContextSelector', () => {
expect(screen.getByText('Tenant Beta')).toBeInTheDocument();
});
it('blendet die Auswahl bei nur einer Organisation aus', async () => {
mockAuthStore.mockImplementation(
(selector: (state: { user: { id: string; username: string; displayName: string; role: string; tenantId: string } }) => unknown) =>
selector({
user: { id: 'u1', username: 'superadmin', displayName: 'Super', role: 'SUPER_ADMIN', tenantId: 't1' },
}),
);
vi.stubGlobal(
'fetch',
vi.fn(() => Promise.resolve({ ok: true, json: () => Promise.resolve([mockTenants[0]]) })),
);
const { container } = render(<TenantContextSelector />);
await waitFor(() => expect(container.innerHTML).toBe(''));
});
it('renders nothing for ADMIN and does not load the tenant list', () => {
mockAuthStore.mockImplementation(
(selector: (state: { user: { id: string; username: string; displayName: string; role: string; tenantId: string } }) => unknown) =>