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:
117
frontend/src/lib/activity/ChronikRow.svelte.test.ts
Normal file
117
frontend/src/lib/activity/ChronikRow.svelte.test.ts
Normal 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}/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user