import { afterEach, describe, it, expect, vi } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import type { NotificationItem } from '$lib/notification/notifications'; import NotificationBell from './NotificationBell.svelte'; vi.mock('$app/navigation', () => ({ goto: vi.fn(), beforeNavigate: vi.fn() })); vi.mock('$app/forms', () => ({ enhance(node: HTMLFormElement, submit?: (opts: { formData: FormData }) => unknown) { const handler = (e: Event) => { e.preventDefault(); submit?.({ formData: new FormData(node) } as never); }; node.addEventListener('submit', handler); return { destroy: () => node.removeEventListener('submit', handler) }; } })); const mockNotificationList = vi.hoisted((): { value: NotificationItem[] } => ({ value: [] })); vi.mock('$lib/notification/notifications.svelte', () => ({ notificationStore: { get notifications() { return mockNotificationList.value; }, get unreadCount() { return mockNotificationList.value.length; }, optimisticMarkRead: vi.fn(), optimisticMarkAllRead: vi.fn(), fetchNotifications: vi.fn().mockResolvedValue(undefined), init: vi.fn(), destroy: vi.fn() } })); afterEach(() => { cleanup(); vi.clearAllMocks(); mockNotificationList.value = []; }); const makeNotification = (overrides: Partial = {}): NotificationItem => ({ id: 'n1', type: 'REPLY', documentId: 'doc-1', referenceId: 'ref-1', annotationId: null, read: false, createdAt: '2026-04-21T10:00:00Z', actorName: 'Anna', documentTitle: 'Test Doc', ...overrides }); describe('NotificationBell — cursor and tooltip', () => { it('bell button has cursor-pointer class', async () => { render(NotificationBell); const btn = document.querySelector('button[aria-haspopup="true"]')!; expect(btn.classList.contains('cursor-pointer')).toBe(true); }); it('bell button title equals aria-label when unreadCount is 0', async () => { mockNotificationList.value = []; render(NotificationBell); const btn = document.querySelector('button[aria-haspopup="true"]')!; expect(btn.getAttribute('title')).toBe('Benachrichtigungen'); expect(btn.getAttribute('aria-label')).toBe(btn.getAttribute('title')); }); it('bell button title equals aria-label when unreadCount is 3', async () => { mockNotificationList.value = [ makeNotification({ id: 'n1' }), makeNotification({ id: 'n2' }), makeNotification({ id: 'n3' }) ]; render(NotificationBell); const btn = document.querySelector('button[aria-haspopup="true"]')!; expect(btn.getAttribute('title')).toBe('3 ungelesene Benachrichtigungen'); expect(btn.getAttribute('aria-label')).toBe(btn.getAttribute('title')); }); });