One <section> per year with a sticky <h2> at top:4rem (REQ-006). Events render in
DTO order as pills/bands; letters render as individual cards while <= 12 (REQ-011)
or collapse to one density strip above that (REQ-012); DTO order is never re-sorted
(REQ-003). Letters carry an alternating data-side for the centered desktop axis
(REQ-004); single left column on phone (REQ-005). Derived-safe {#each} key.
Refs #779
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
import { cleanup, render } from 'vitest-browser-svelte';
|
|
import YearBand from './YearBand.svelte';
|
|
import { makeEntry, makeYear } from './test-factories';
|
|
|
|
afterEach(() => cleanup());
|
|
|
|
function manyLetters(year: number, count: number) {
|
|
return Array.from({ length: count }, (_, i) =>
|
|
makeEntry({ eventDate: `${year}-01-10`, documentId: `doc-${i}` })
|
|
);
|
|
}
|
|
|
|
describe('YearBand', () => {
|
|
it('renders a section with a sticky h2 at top:4rem showing the year (REQ-006)', () => {
|
|
render(YearBand, { year: makeYear(1914, [makeEntry()]) });
|
|
const section = document.querySelector('section');
|
|
expect(section).not.toBeNull();
|
|
const h2 = section?.querySelector('h2');
|
|
expect(h2?.textContent).toContain('1914');
|
|
const cs = getComputedStyle(h2 as HTMLElement);
|
|
expect(cs.position).toBe('sticky');
|
|
expect(cs.top).toBe('64px');
|
|
});
|
|
|
|
it('renders each letter as a card when the band holds <= 12 letters (REQ-011)', () => {
|
|
render(YearBand, { year: makeYear(1909, manyLetters(1909, 3)) });
|
|
expect(document.querySelectorAll('a')).toHaveLength(3);
|
|
expect(document.querySelector('[data-testid="strip-expand"]')).toBeNull();
|
|
});
|
|
|
|
it('renders a single strip when the band holds > 12 letters (REQ-012)', () => {
|
|
render(YearBand, { year: makeYear(1915, manyLetters(1915, 30)) });
|
|
expect(document.querySelector('[data-testid="strip-expand"]')).not.toBeNull();
|
|
// collapsed: no individual letter links yet
|
|
expect(document.querySelectorAll('a')).toHaveLength(0);
|
|
});
|
|
|
|
it('renders entries in DTO order — DAY-precision letter above a YEAR-precision letter (REQ-003)', () => {
|
|
const dayLetter = makeEntry({
|
|
precision: 'DAY',
|
|
eventDate: '1923-04-12',
|
|
title: 'Tagesgenau',
|
|
documentId: 'day'
|
|
});
|
|
const yearLetter = makeEntry({
|
|
precision: 'YEAR',
|
|
eventDate: '1923-01-01',
|
|
title: 'Nur Jahr',
|
|
documentId: 'year'
|
|
});
|
|
render(YearBand, { year: makeYear(1923, [dayLetter, yearLetter]) });
|
|
const links = Array.from(document.querySelectorAll('a'));
|
|
expect(links[0].getAttribute('href')).toBe('/documents/day');
|
|
expect(links[1].getAttribute('href')).toBe('/documents/year');
|
|
});
|
|
|
|
it('renders an EVENT as a pill and a HISTORICAL event as a band', () => {
|
|
const pill = makeEntry({
|
|
kind: 'EVENT',
|
|
derived: true,
|
|
derivedType: 'MARRIAGE',
|
|
title: 'Heirat',
|
|
senderName: '',
|
|
receiverName: '',
|
|
documentId: undefined
|
|
});
|
|
const band = makeEntry({
|
|
kind: 'EVENT',
|
|
derived: false,
|
|
type: 'HISTORICAL',
|
|
precision: 'RANGE',
|
|
eventDate: '1914-01-01',
|
|
eventDateEnd: '1918-12-31',
|
|
title: 'Erster Weltkrieg',
|
|
senderName: '',
|
|
receiverName: '',
|
|
documentId: undefined
|
|
});
|
|
render(YearBand, { year: makeYear(1914, [pill, band]) });
|
|
expect(document.body.textContent).toContain('Heirat');
|
|
expect(document.querySelector('[data-testid="world-range"]')).not.toBeNull();
|
|
});
|
|
});
|