A curated event with letters in its own band now becomes the contained card header (glyph, title, date, provenance, edit pencil) instead of a separate floating pill — the title reads once. Derived life-events, world-bands, and letterless event pills are unchanged (REQ-001 amended for curated-with-letters; the identity fixture now links its letter to the curated event so the letterless world band stays a band). Refs #827
99 lines
3.3 KiB
TypeScript
99 lines
3.3 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
import { cleanup, render } from 'vitest-browser-svelte';
|
|
import TimelineView from './TimelineView.svelte';
|
|
import { makeEntry, makeYear, makeTimelineDTO } from './test-factories';
|
|
import type { GroupingMode } from './timelineGrouping';
|
|
|
|
afterEach(() => cleanup());
|
|
|
|
const worldBand = (title: string) =>
|
|
makeEntry({
|
|
kind: 'EVENT',
|
|
type: 'HISTORICAL',
|
|
derived: false,
|
|
precision: 'RANGE',
|
|
eventDate: '1914-01-01',
|
|
eventDateEnd: '1918-12-31',
|
|
eventId: 'h1',
|
|
title,
|
|
senderName: '',
|
|
receiverName: '',
|
|
documentId: undefined
|
|
});
|
|
|
|
const eventPill = (title: string) =>
|
|
makeEntry({
|
|
kind: 'EVENT',
|
|
type: 'PERSONAL',
|
|
derived: false,
|
|
eventId: 'p1',
|
|
title,
|
|
senderName: '',
|
|
receiverName: '',
|
|
documentId: undefined
|
|
});
|
|
|
|
// A signature of the axis-fixed event layer: the curated/world-band titles, the world-range
|
|
// marker count, and the event-pill count — everything REQ-001 requires to stay constant when
|
|
// only the loose letters re-bundle. (No pixel-diff harness in the repo; this is the structural
|
|
// equivalent — the event-layer DOM is byte-for-byte built from the same entries in every mode.)
|
|
function eventLayerSignature(): string {
|
|
const body = document.body.textContent ?? '';
|
|
return JSON.stringify({
|
|
weltkrieg: body.includes('Erster Weltkrieg'),
|
|
hochzeit: body.includes('Hochzeit'),
|
|
worldRange: document.querySelectorAll('[data-testid="world-range"]').length
|
|
});
|
|
}
|
|
|
|
// Brief A links to the curated event p1 (Hochzeit), not the world band — so the world band
|
|
// stays letterless and renders as a plain band in every mode (REQ-001). Under the #827 redesign
|
|
// a curated event WITH letters becomes its cluster card's header, so the signature tracks the
|
|
// stable layer: the letterless world band's marker count and the two titles, which all survive
|
|
// regardless of whether Hochzeit renders as a pill (Datum) or a card header (grouped).
|
|
const mixed = () =>
|
|
makeTimelineDTO({
|
|
years: [
|
|
makeYear(1915, [
|
|
worldBand('Erster Weltkrieg'),
|
|
eventPill('Hochzeit'),
|
|
makeEntry({ documentId: 'a', title: 'Brief A', linkedEventId: 'p1' }),
|
|
makeEntry({
|
|
documentId: 'b',
|
|
title: 'Brief B',
|
|
rootTagId: 't1',
|
|
rootTagName: 'Krieg',
|
|
rootTagColor: 'sienna'
|
|
})
|
|
])
|
|
]
|
|
});
|
|
|
|
function signatureFor(mode: GroupingMode): string {
|
|
render(TimelineView, { timeline: mixed(), groupingMode: mode });
|
|
const sig = eventLayerSignature();
|
|
cleanup();
|
|
return sig;
|
|
}
|
|
|
|
describe('TimelineView event layer (REQ-001)', () => {
|
|
it('renders the event pills and world-bands identically across all three grouping modes', () => {
|
|
const dateSig = signatureFor('date');
|
|
const eventSig = signatureFor('event');
|
|
const themaSig = signatureFor('thema');
|
|
|
|
expect(eventSig).toBe(dateSig);
|
|
expect(themaSig).toBe(dateSig);
|
|
// sanity: the world-band actually rendered, so the assertion is not vacuously equal on ""
|
|
expect(dateSig).toContain('"worldRange":1');
|
|
});
|
|
|
|
it('regroups only the loose letters — buckets appear off Datum, not in it', () => {
|
|
render(TimelineView, { timeline: mixed(), groupingMode: 'date' });
|
|
expect(document.querySelector('[data-testid="letter-bucket"]')).toBeNull();
|
|
cleanup();
|
|
render(TimelineView, { timeline: mixed(), groupingMode: 'event' });
|
|
expect(document.querySelector('[data-testid="letter-bucket"]')).not.toBeNull();
|
|
});
|
|
});
|