import { cleanup, fireEvent, render, screen } from '@testing-library/react'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; // quick-260916-dyv: Dashboard-Seite — feste Aktionsleiste unten rechts // (Stift/Haekchen + "Widget hinzufuegen"), Grid direkt im Container p-2, // kein Abstands-Wrapper (mt-8) und kein Block oben rechts (top-2) mehr. // Muster: admin/groups/groups-page.test.tsx (next-intl-Mock mit Namensraum). const messages: Record> = { widgets: { editMode: 'Dashboard bearbeiten', saveChanges: 'Änderungen speichern', addWidget: 'Widget hinzufügen', layoutLoadError: 'Dashboard konnte nicht geladen werden. Bitte laden Sie die Seite neu.', }, }; vi.mock('next-intl', () => ({ useTranslations: (ns: string) => (key: string) => messages[ns]?.[key] ?? key, })); const mockStore = { layouts: { lg: [], md: [], sm: [], xs: [], xxs: [] }, widgets: [] as Array<{ id: string; widgetType: string; config: Record }>, isEditMode: false, isDirty: false, isLoading: false, error: null as string | null, setEditMode: vi.fn(), updateLayouts: vi.fn(), addWidget: vi.fn(), removeWidget: vi.fn(), loadDashboard: vi.fn(), saveLayout: vi.fn(), }; vi.mock('@/lib/stores/dashboard-store', () => ({ useDashboardStore: (selector?: (state: typeof mockStore) => unknown) => { if (selector) return selector(mockStore); return mockStore; }, })); vi.mock('@/components/dashboard/dashboard-grid', () => ({ DashboardGrid: (p: { isEditMode: boolean }) => (
), })); vi.mock('@/components/dashboard/widget-catalog-modal', () => ({ WidgetCatalogModal: () => null, })); vi.mock('@/components/dashboard/widgets/clock-widget', () => ({ ClockWidget: () => null })); vi.mock('@/components/dashboard/widgets/search-widget', () => ({ SearchWidget: () => null })); vi.mock('@/components/dashboard/widgets/calendar-widget', () => ({ CalendarWidget: () => null })); vi.mock('@/components/dashboard/widgets/note-widget', () => ({ NoteWidget: () => null })); vi.mock('@/components/dashboard/widgets/calculator-widget', () => ({ CalculatorWidget: () => null })); vi.mock('@/components/dashboard/widgets/stopwatch-widget', () => ({ StopwatchWidget: () => null })); vi.mock('@/components/dashboard/widgets/favorites-widget', () => ({ FavoritesWidget: () => null })); vi.mock('@/components/dashboard/widgets/link-widget', () => ({ LinkWidget: () => null })); beforeEach(() => { mockStore.isEditMode = false; mockStore.isLoading = false; mockStore.error = null; mockStore.setEditMode = vi.fn(); mockStore.loadDashboard = vi.fn(); }); afterEach(() => { cleanup(); }); describe('DashboardPage (quick-260916-dyv)', () => { it('Test 1: Ansichtsmodus — Stift in fester Leiste unten rechts, kein "Widget hinzufuegen", kein mt-8/top-2, Grid direkt im Container p-2', async () => { const { default: DashboardPage } = await import('./page'); render(); const toggle = screen.getByRole('button', { name: 'Dashboard bearbeiten' }); const bar = toggle.parentElement as HTMLElement; expect(bar.classList.contains('fixed')).toBe(true); expect(bar.classList.contains('bottom-6')).toBe(true); expect(bar.classList.contains('right-6')).toBe(true); expect(bar.classList.contains('z-20')).toBe(true); expect(screen.queryByRole('button', { name: 'Widget hinzufügen' })).toBeNull(); expect(document.querySelector('.mt-8')).toBeNull(); expect(document.querySelector('.top-2')).toBeNull(); const grid = screen.getByTestId('dashboard-grid'); expect((grid.parentElement as HTMLElement).classList.contains('p-2')).toBe(true); expect(grid.getAttribute('data-edit')).toBe('false'); }); it('Test 2: Bearbeitungsmodus — "Widget hinzufuegen" links neben dem Haekchen in derselben Leiste, Grid im Bearbeitungsmodus', async () => { mockStore.isEditMode = true; const { default: DashboardPage } = await import('./page'); render(); const toggle = screen.getByRole('button', { name: 'Änderungen speichern' }); const add = screen.getByRole('button', { name: 'Widget hinzufügen' }); expect(add.parentElement).toBe(toggle.parentElement); // "Widget hinzufuegen" steht im DOM VOR dem Umschalter (links daneben). expect(add.compareDocumentPosition(toggle) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy(); expect(screen.getByTestId('dashboard-grid').getAttribute('data-edit')).toBe('true'); }); it('Test 3: Umschalten — Klick auf "Dashboard bearbeiten" ruft setEditMode(true) genau einmal', async () => { const { default: DashboardPage } = await import('./page'); render(); fireEvent.click(screen.getByRole('button', { name: 'Dashboard bearbeiten' })); expect(mockStore.setEditMode).toHaveBeenCalledTimes(1); expect(mockStore.setEditMode).toHaveBeenCalledWith(true); }); });