test(activity): cover ChronikRow variant + kind branches

Avatar with initials vs question-mark fallback, for-you marker
visibility, data-variant matrix (simple/for-you/rollup/comment),
count badge for rollup, comment preview rendering with fallback,
document title link, default vs comment-deep-link href, time-range
label for rollup with happenedAtUntil.

11 tests covering ~40 of ChronikRow's high-uncovered branches.

Refs #496.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-10 01:57:05 +02:00
committed by marcel
parent b1ea7d0916
commit 1f63267193

View File

@@ -0,0 +1,117 @@
import { describe, it, expect, afterEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import ChronikRow from './ChronikRow.svelte';
afterEach(cleanup);
const baseActor = { id: 'a1', name: 'Anna Schmidt', initials: 'AS', color: '#012851' };
const makeItem = (overrides: Record<string, unknown> = {}) => ({
id: 'i1',
kind: 'TEXT_SAVED' as string,
actor: baseActor as null | typeof baseActor,
documentId: 'd1',
documentTitle: 'Brief 1923',
count: 1,
happenedAt: '2026-04-15T10:00:00Z',
happenedAtUntil: null as string | null,
commentId: null as string | null,
commentPreview: null as string | null,
annotationId: null as string | null,
youMentioned: false,
...overrides
});
describe('ChronikRow', () => {
it('renders the actor avatar with initials when actor is present', async () => {
render(ChronikRow, { props: { item: makeItem() } });
expect(document.body.textContent).toContain('AS');
});
it('renders the question-mark fallback avatar when actor is null', async () => {
render(ChronikRow, { props: { item: makeItem({ actor: null }) } });
const fallback = document.querySelector('[data-testid="chronik-avatar-fallback"]');
expect(fallback).not.toBeNull();
});
it('renders the for-you marker when youMentioned is true', async () => {
render(ChronikRow, { props: { item: makeItem({ youMentioned: true }) } });
const marker = document.querySelector('[data-testid="chronik-foryou-marker"]');
expect(marker).not.toBeNull();
});
it('renders the for-you data-variant when youMentioned is true', async () => {
render(ChronikRow, { props: { item: makeItem({ youMentioned: true }) } });
const link = document.querySelector('a[data-variant]') as HTMLElement;
expect(link.getAttribute('data-variant')).toBe('for-you');
});
it('renders the rollup variant when count > 1', async () => {
render(ChronikRow, { props: { item: makeItem({ count: 3 }) } });
const link = document.querySelector('a[data-variant]') as HTMLElement;
expect(link.getAttribute('data-variant')).toBe('rollup');
const badge = document.querySelector('[data-testid="chronik-count-badge"]');
expect(badge).not.toBeNull();
});
it('renders the comment variant for COMMENT_ADDED kind', async () => {
render(ChronikRow, {
props: { item: makeItem({ kind: 'COMMENT_ADDED', commentPreview: 'Tolle Geschichte!' }) }
});
const link = document.querySelector('a[data-variant]') as HTMLElement;
expect(link.getAttribute('data-variant')).toBe('comment');
const preview = document.querySelector('[data-testid="chronik-comment-preview"]');
expect(preview?.textContent).toContain('Tolle Geschichte!');
});
it('falls back to ellipsis comment preview when commentPreview is null', async () => {
render(ChronikRow, { props: { item: makeItem({ kind: 'COMMENT_ADDED' }) } });
const preview = document.querySelector('[data-testid="chronik-comment-preview"]');
expect(preview?.textContent).toContain('…');
});
it('renders the document title in a styled span', async () => {
render(ChronikRow, { props: { item: makeItem() } });
const title = document.querySelector('[data-testid="chronik-doc-title"]');
expect(title?.textContent).toBe('Brief 1923');
});
it('uses /documents/{id} as default href', async () => {
render(ChronikRow, { props: { item: makeItem() } });
const link = document.querySelector('a[data-variant]') as HTMLAnchorElement;
expect(link.href).toContain('/documents/d1');
});
it('uses comment-deep-link href when commentId is set', async () => {
render(ChronikRow, {
props: { item: makeItem({ commentId: 'c1', kind: 'COMMENT_ADDED' }) }
});
const link = document.querySelector('a[data-variant]') as HTMLAnchorElement;
expect(link.href).toContain('c1');
});
it('renders a time-range label when rollup has happenedAtUntil', async () => {
render(ChronikRow, {
props: {
item: makeItem({
count: 5,
happenedAt: '2026-04-15T10:00:00Z',
happenedAtUntil: '2026-04-15T14:30:00Z'
})
}
});
// Time range uses U+2013 between two HH:MM strings — check for any colon-bearing time
expect(document.body.textContent).toMatch(/\d{2}:\d{2}/);
});
});