import { describe, it, expect, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import ChronikTimeline from './ChronikTimeline.svelte'; import type { components } from '$lib/generated/api'; type ActivityFeedItemDTO = components['schemas']['ActivityFeedItemDTO']; afterEach(cleanup); function item(partial: Partial): ActivityFeedItemDTO { return { kind: 'TEXT_SAVED', actor: { initials: 'AB', color: '#123456', name: 'Anna Beta' }, documentId: 'doc-x', documentTitle: 'Some document', happenedAt: new Date().toISOString(), youMentioned: false, count: 1, ...partial }; } function atOffsetDays(days: number): string { const d = new Date(); d.setDate(d.getDate() - days); return d.toISOString(); } describe('ChronikTimeline', () => { it('renders nothing / no bucket headers when items is empty', async () => { render(ChronikTimeline, { items: [] }); expect(document.querySelector('[data-testid="chronik-bucket-today"]')).toBeNull(); expect(document.querySelector('[data-testid="chronik-bucket-yesterday"]')).toBeNull(); expect(document.querySelector('[data-testid="chronik-bucket-thisWeek"]')).toBeNull(); expect(document.querySelector('[data-testid="chronik-bucket-older"]')).toBeNull(); }); it('places today items in the today bucket with a "Heute" header', async () => { render(ChronikTimeline, { items: [ item({ documentId: 'doc-today', documentTitle: 'Frisches Dokument', happenedAt: new Date().toISOString() }) ] }); const today = document.querySelector('[data-testid="chronik-bucket-today"]'); expect(today).not.toBeNull(); await expect.element(page.getByText('Heute', { exact: true })).toBeInTheDocument(); // The row for the today item should be inside the today bucket. expect(today?.textContent).toContain('Frisches Dokument'); }); it('does not render an empty bucket header when no items fall into it', async () => { render(ChronikTimeline, { items: [item({ happenedAt: new Date().toISOString() })] }); // Only today bucket should exist. expect(document.querySelector('[data-testid="chronik-bucket-today"]')).not.toBeNull(); expect(document.querySelector('[data-testid="chronik-bucket-older"]')).toBeNull(); }); it('places older items in the older bucket', async () => { render(ChronikTimeline, { items: [ item({ documentId: 'doc-old', documentTitle: 'Alt Doc', happenedAt: atOffsetDays(30) }) ] }); const older = document.querySelector('[data-testid="chronik-bucket-older"]'); expect(older).not.toBeNull(); expect(older?.textContent).toContain('Alt Doc'); }); it('groups multiple items into their respective buckets', async () => { render(ChronikTimeline, { items: [ item({ documentId: 'd1', documentTitle: 'Heute Item', happenedAt: new Date().toISOString() }), item({ documentId: 'd2', documentTitle: 'Alt Item', happenedAt: atOffsetDays(30) }) ] }); const today = document.querySelector('[data-testid="chronik-bucket-today"]'); const older = document.querySelector('[data-testid="chronik-bucket-older"]'); expect(today?.textContent).toContain('Heute Item'); expect(today?.textContent).not.toContain('Alt Item'); expect(older?.textContent).toContain('Alt Item'); expect(older?.textContent).not.toContain('Heute Item'); }); });