12eea333ba
Neuer Schalter im Bearbeitungsmodus (neben dem Griff) setzt hideTitle in der Widget-Konfiguration (setWidgetConfig im Dashboard-Store, optimistisch mit Ruecksetzen); in der Ansicht entfaellt die Titelzeile per data-hide-title, Aktionen der Titelzeile bleiben oben rechts. Kategorien der Seitenleiste 14 px, Moduleintraege 13 px / 32 px hoch. Version 1.5.2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
113 lines
3.9 KiB
TypeScript
113 lines
3.9 KiB
TypeScript
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
// quick-260916-iex: Link-Widget entfernt — unbekannte Widget-Typen (z. B.
|
|
// eine alte Link-Kachel vor dem Einspielen der Migration) muessen weiterhin
|
|
// ohne Absturz gerendert werden.
|
|
// quick-260922-m1h: Statt des rohen Typnamens steht dort jetzt ein Satz, der
|
|
// den Fall erklaert — derselbe Fall tritt kuenftig auf, wenn eine Kachel zu
|
|
// einem Modul gehoert, das dem Benutzer nicht freigegeben ist.
|
|
vi.mock('next-intl', () => ({
|
|
useTranslations: () => (key: string) =>
|
|
key === 'unavailable'
|
|
? 'Diese Kachel steht nicht zur Verfügung — das zugehörige Modul ist nicht freigegeben.'
|
|
: key,
|
|
}));
|
|
|
|
const setWidgetConfig = vi.fn();
|
|
vi.mock('@/lib/stores/dashboard-store', () => ({
|
|
useDashboardStore: (selector: (state: { setWidgetConfig: typeof setWidgetConfig }) => unknown) =>
|
|
selector({ setWidgetConfig }),
|
|
}));
|
|
|
|
import { WidgetWrapper } from './widget-wrapper';
|
|
|
|
describe('WidgetWrapper', () => {
|
|
it('unbekannter/gesperrter Widget-Typ erklaert sich mit einem Hinweistext statt leer oder als roher Typname zu rendern', () => {
|
|
render(
|
|
<WidgetWrapper
|
|
widget={{ id: 'w-alt', widgetType: 'link', config: {} }}
|
|
isEditMode={false}
|
|
onRemove={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
const article = screen.getByRole('article');
|
|
expect(article).toHaveAttribute('aria-label', 'link');
|
|
|
|
const hint = screen.getByText(
|
|
'Diese Kachel steht nicht zur Verfügung — das zugehörige Modul ist nicht freigegeben.',
|
|
);
|
|
expect(hint.className).toContain('text-muted-foreground');
|
|
expect(hint.className).toContain('text-center');
|
|
|
|
// Der rohe Typname steht nicht mehr im Rumpf der Kachel.
|
|
expect(screen.queryByText('link')).toBeNull();
|
|
});
|
|
|
|
it('eine bekannte Kachel rendert weiterhin ihre Komponente, nicht den Hinweis', () => {
|
|
render(
|
|
<WidgetWrapper
|
|
widget={{ id: 'w-uhr', widgetType: 'clock', config: {} }}
|
|
isEditMode={false}
|
|
onRemove={vi.fn()}
|
|
/>,
|
|
);
|
|
|
|
expect(
|
|
screen.queryByText(
|
|
'Diese Kachel steht nicht zur Verfügung — das zugehörige Modul ist nicht freigegeben.',
|
|
),
|
|
).toBeNull();
|
|
});
|
|
|
|
// quick-260928-wtt: Titel je Widget ein-/ausblenden
|
|
it('Bearbeitungsmodus: Schalter blendet den Titel aus und speichert hideTitle', () => {
|
|
setWidgetConfig.mockClear();
|
|
render(
|
|
<WidgetWrapper
|
|
widget={{ id: 'w-uhr', widgetType: 'clock', config: {} }}
|
|
isEditMode={true}
|
|
onRemove={vi.fn()}
|
|
/>,
|
|
);
|
|
fireEvent.click(screen.getByRole('button', { name: 'hideTitle' }));
|
|
expect(setWidgetConfig).toHaveBeenCalledWith('w-uhr', { hideTitle: true });
|
|
// im Bearbeitungsmodus bleibt der Titel sichtbar
|
|
expect(screen.getByRole('article')).not.toHaveAttribute('data-hide-title');
|
|
});
|
|
|
|
it('ausgeblendeter Titel: Schalter blendet wieder ein, Ansicht markiert die Karte', () => {
|
|
setWidgetConfig.mockClear();
|
|
const { rerender } = render(
|
|
<WidgetWrapper
|
|
widget={{ id: 'w-uhr', widgetType: 'clock', config: { hideTitle: true } }}
|
|
isEditMode={true}
|
|
onRemove={vi.fn()}
|
|
/>,
|
|
);
|
|
fireEvent.click(screen.getByRole('button', { name: 'showTitle' }));
|
|
expect(setWidgetConfig).toHaveBeenCalledWith('w-uhr', { hideTitle: false });
|
|
|
|
rerender(
|
|
<WidgetWrapper
|
|
widget={{ id: 'w-uhr', widgetType: 'clock', config: { hideTitle: true } }}
|
|
isEditMode={false}
|
|
onRemove={vi.fn()}
|
|
/>,
|
|
);
|
|
expect(screen.getByRole('article')).toHaveAttribute('data-hide-title');
|
|
});
|
|
|
|
it('Widgets ohne Titelzeile (Suche) bekommen keinen Schalter', () => {
|
|
render(
|
|
<WidgetWrapper
|
|
widget={{ id: 'w-suche', widgetType: 'search', config: {} }}
|
|
isEditMode={true}
|
|
onRemove={vi.fn()}
|
|
/>,
|
|
);
|
|
expect(screen.queryByRole('button', { name: 'hideTitle' })).toBeNull();
|
|
});
|
|
});
|