diff --git a/frontend/src/lib/activity/ChronikFuerDichBox.svelte.test.ts b/frontend/src/lib/activity/ChronikFuerDichBox.svelte.test.ts new file mode 100644 index 00000000..6b887a86 --- /dev/null +++ b/frontend/src/lib/activity/ChronikFuerDichBox.svelte.test.ts @@ -0,0 +1,132 @@ +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'); + }); +});