import { describe, it, expect, vi, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; const mockNavigating = { type: null }; const mockPage = { url: new URL('http://localhost/aktivitaeten') }; vi.mock('$app/state', () => ({ get navigating() { return mockNavigating; }, get page() { return mockPage; } })); vi.mock('$app/navigation', () => ({ beforeNavigate: () => {}, afterNavigate: () => {}, goto: vi.fn(), invalidate: vi.fn(), invalidateAll: vi.fn(), preloadCode: vi.fn(), preloadData: vi.fn(), pushState: vi.fn(), replaceState: vi.fn(), disableScrollHandling: vi.fn(), onNavigate: () => () => {} })); vi.mock('$lib/notification/notifications.svelte', () => ({ notificationStore: { notifications: [], init: vi.fn(), destroy: vi.fn(), markRead: vi.fn(), markAllRead: vi.fn() } })); const { default: AktivitaetenPage } = await import('./+page.svelte'); afterEach(cleanup); const baseData = (overrides: Record = {}) => ({ filter: 'alle' as const, activityFeed: [], unreadNotifications: [], loadError: null, ...overrides }); describe('aktivitaeten page', () => { it('renders the page heading', async () => { render(AktivitaetenPage, { props: { data: baseData() } }); await expect.element(page.getByRole('heading', { name: /aktivitäten/i })).toBeVisible(); }); it('renders the error card when loadError is "activity"', async () => { render(AktivitaetenPage, { props: { data: baseData({ loadError: 'activity' }) } }); // ChronikErrorCard renders some retry mechanism const main = document.querySelector('main'); expect(main).not.toBeNull(); // FuerDichBox should NOT render when loadError is set const fuerDich = document.querySelector('[data-testid="chronik-inbox-zero"]'); expect(fuerDich).toBeNull(); }); it('renders the FuerDichBox and FilterPills when loadError is null', async () => { render(AktivitaetenPage, { props: { data: baseData() } }); // FuerDichBox shows the inbox-zero state when no unread const fuerDich = document.querySelector('[data-testid="chronik-inbox-zero"]'); expect(fuerDich).not.toBeNull(); // FilterPills present const radiogroup = document.querySelector('[role="radiogroup"]'); expect(radiogroup).not.toBeNull(); }); it('renders the first-run empty state when activityFeed is empty', async () => { render(AktivitaetenPage, { props: { data: baseData() } }); const empty = document.querySelector('[data-testid="chronik-empty-state"]'); expect(empty?.getAttribute('data-variant')).toBe('first-run'); }); it('renders the filter-empty empty state when feed has items but filter rules out all', async () => { render(AktivitaetenPage, { props: { data: baseData({ filter: 'fuer-dich' as const, activityFeed: [ { kind: 'TEXT_SAVED', documentId: 'doc-1', documentTitle: 'Brief', actor: { id: 'u1', name: 'Anna', initials: 'AS', color: '#000' }, count: 1, happenedAt: '2026-01-01T00:00:00Z', happenedAtUntil: null, youMentioned: false } ] }) } }); const empty = document.querySelector('[data-testid="chronik-empty-state"]'); expect(empty?.getAttribute('data-variant')).toBe('filter-empty'); }); it('renders the timeline when displayFeed is non-empty', async () => { render(AktivitaetenPage, { props: { data: baseData({ filter: 'alle' as const, activityFeed: [ { kind: 'TEXT_SAVED', documentId: 'doc-1', documentTitle: 'Brief 1899', actor: { id: 'u1', name: 'Anna', initials: 'AS', color: '#000' }, count: 1, happenedAt: '2026-01-01T00:00:00Z', happenedAtUntil: null, youMentioned: false } ] }) } }); // Timeline renders the document title from the feed item expect(document.body.textContent).toContain('Brief 1899'); // No empty-state in this case const empty = document.querySelector('[data-testid="chronik-empty-state"]'); expect(empty).toBeNull(); }); it('renders without crashing when filter is set to a non-default value', async () => { render(AktivitaetenPage, { props: { data: baseData({ filter: 'transkription' as const }) } }); const main = document.querySelector('main'); expect(main).not.toBeNull(); }); });