import { describe, it, expect, vi, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import ChronikFuerDichBox from './ChronikFuerDichBox.svelte'; import type { NotificationItem } from '$lib/notification/notifications'; afterEach(cleanup); const mention = (overrides: Partial = {}): NotificationItem => ({ id: 'n-1', type: 'MENTION', documentId: 'doc-1', referenceId: 'ref-1', annotationId: null, read: false, createdAt: new Date().toISOString(), actorName: 'Anna', documentTitle: 'Brief 1899', ...overrides }); describe('ChronikFuerDichBox', () => { it('renders the inbox-zero state when there are no unread', async () => { render(ChronikFuerDichBox, { props: { unread: [], onMarkRead: () => {}, onMarkAllRead: () => {} } }); await expect.element(page.getByText(/keine neuen erwähnungen/i)).toBeVisible(); const link = document.querySelector('a[href="/aktivitaeten?filter=fuer-dich"]'); expect(link).not.toBeNull(); }); it('renders the count badge with the unread count', async () => { render(ChronikFuerDichBox, { props: { unread: [mention(), mention({ id: 'n-2' }), mention({ id: 'n-3' })], onMarkRead: () => {}, onMarkAllRead: () => {} } }); const badge = document.querySelector('[data-testid="chronik-fuerdich-count"]'); expect(badge?.textContent).toContain('3'); }); it('uses the @ glyph for MENTION and ↩ for REPLY', async () => { render(ChronikFuerDichBox, { props: { unread: [mention({ id: 'n-m', type: 'MENTION' }), mention({ id: 'n-r', type: 'REPLY' })], onMarkRead: () => {}, onMarkAllRead: () => {} } }); const items = document.querySelectorAll('ul[role="list"] li'); expect(items.length).toBe(2); expect(items[0].textContent).toContain('@'); expect(items[1].textContent).toContain('↩'); }); it('renders MENTION verb text from paraglide messages', async () => { render(ChronikFuerDichBox, { props: { unread: [mention({ actorName: 'Bertha' })], onMarkRead: () => {}, onMarkAllRead: () => {} } }); await expect .element(page.getByText(/bertha hat dich in einem kommentar erwähnt/i)) .toBeVisible(); }); it('renders REPLY verb text from paraglide messages', async () => { render(ChronikFuerDichBox, { props: { unread: [mention({ type: 'REPLY', actorName: 'Carl' })], onMarkRead: () => {}, onMarkAllRead: () => {} } }); await expect .element(page.getByText(/carl hat auf deinen kommentar geantwortet/i)) .toBeVisible(); }); it('calls onMarkRead with the notification when its dismiss button is clicked', async () => { const onMarkRead = vi.fn(); const item = mention({ id: 'n-7' }); render(ChronikFuerDichBox, { props: { unread: [item], onMarkRead, onMarkAllRead: () => {} } }); const dismiss = document.querySelector( '[data-testid="chronik-fuerdich-dismiss"]' ) as HTMLElement; dismiss.click(); expect(onMarkRead).toHaveBeenCalledWith(item); }); it('calls onMarkAllRead when the mark-all-read button is clicked', async () => { const onMarkAllRead = vi.fn(); render(ChronikFuerDichBox, { props: { unread: [mention()], onMarkRead: () => {}, onMarkAllRead } }); const btn = document.querySelector('[data-testid="chronik-mark-all-read"]') as HTMLElement; btn.click(); expect(onMarkAllRead).toHaveBeenCalledOnce(); }); it('builds a deep-link href to the comment for each notification', async () => { render(ChronikFuerDichBox, { props: { unread: [mention({ documentId: 'doc-x', referenceId: 'ref-y', annotationId: null })], onMarkRead: () => {}, onMarkAllRead: () => {} } }); const link = document.querySelector('ul[role="list"] li a') as HTMLAnchorElement; expect(link.getAttribute('href')).toContain('doc-x'); }); });