import { describe, it, expect } from 'vitest'; import { getInitials, abbreviateName, formatXsMeta, personAvatarColor, statusDotClass, statusLabel } from './personFormat'; import { formatDate } from './date'; // ─── getInitials ───────────────────────────────────────────────────────────── describe('getInitials', () => { it('returns first chars of first and last word uppercased', () => { expect(getInitials('Marcel Raddatz')).toBe('MR'); }); it('returns single char for a single-word name', () => { expect(getInitials('Raddatz')).toBe('R'); }); it('returns empty string for an empty name', () => { expect(getInitials('')).toBe(''); }); it('splits on whitespace only — hyphenated first word counts as one', () => { expect(getInitials('Anna-Maria Raddatz')).toBe('AR'); }); it('ignores extra whitespace between words', () => { expect(getInitials(' Karl Raddatz ')).toBe('KR'); }); }); // ─── abbreviateName ────────────────────────────────────────────────────────── describe('abbreviateName', () => { it('abbreviates first name to initial + last name', () => { expect(abbreviateName({ firstName: 'Karl', lastName: 'Raddatz' })).toBe('K. Raddatz'); }); it('returns single name as-is when no last name', () => { expect(abbreviateName({ firstName: 'Elfriede', lastName: '' })).toBe('Elfriede'); }); it('preserves hyphenated last name', () => { expect(abbreviateName({ firstName: 'Karl', lastName: 'Müller-Schmidt' })).toBe( 'K. Müller-Schmidt' ); }); it('handles leading/trailing whitespace in names', () => { expect(abbreviateName({ firstName: ' Karl ', lastName: ' Raddatz ' })).toBe('K. Raddatz'); }); }); // ─── formatXsMeta ──────────────────────────────────────────────────────────── type Doc = { sender?: { firstName: string; lastName: string } | null; receivers?: { firstName: string; lastName: string }[]; documentDate?: string | null; }; describe('formatXsMeta', () => { const sender = { firstName: 'Karl', lastName: 'Raddatz' }; const receiver1 = { firstName: 'Elfriede', lastName: 'Raddatz' }; const receiver2 = { firstName: 'Anna', lastName: 'Müller' }; const receiver3 = { firstName: 'Hans', lastName: 'Schmidt' }; it('formats sender with no receivers and date', () => { const doc: Doc = { sender, receivers: [], documentDate: '1943-12-24' }; expect(formatXsMeta(doc)).toBe('K.Raddatz · 24.12.1943'); }); it('formats sender with one receiver and date', () => { const doc: Doc = { sender, receivers: [receiver1], documentDate: '1943-12-24' }; expect(formatXsMeta(doc)).toBe('K.Raddatz → E.Raddatz · 24.12.1943'); }); it('formats sender with three receivers showing +2', () => { const doc: Doc = { sender, receivers: [receiver1, receiver2, receiver3], documentDate: '1943-12-24' }; expect(formatXsMeta(doc)).toBe('K.Raddatz → E.Raddatz +2 · 24.12.1943'); }); it('formats without sender', () => { const doc: Doc = { sender: null, receivers: [receiver1], documentDate: '1943-12-24' }; expect(formatXsMeta(doc)).toBe('E.Raddatz · 24.12.1943'); }); it('formats without date', () => { const doc: Doc = { sender, receivers: [], documentDate: null }; expect(formatXsMeta(doc)).toBe('K.Raddatz'); }); it('formats with no sender and no date', () => { const doc: Doc = { sender: null, receivers: [receiver1], documentDate: null }; expect(formatXsMeta(doc)).toBe('E.Raddatz'); }); }); // ─── personAvatarColor ─────────────────────────────────────────────────────── const PALETTE = ['#012851', '#5A3080', '#007596', '#2A6040', '#803020']; describe('personAvatarColor', () => { it('returns a value from the palette', () => { expect(PALETTE).toContain(personAvatarColor('abc')); }); it('is deterministic — same id always returns same color', () => { const id = '550e8400-e29b-41d4-a716-446655440000'; expect(personAvatarColor(id)).toBe(personAvatarColor(id)); }); it('all 5 palette entries are reachable across 1000 random UUIDs', () => { const seen = new Set(); for (let i = 0; i < 1000; i++) { seen.add(personAvatarColor(crypto.randomUUID())); } expect(seen.size).toBe(5); }); }); // ─── formatDate ────────────────────────────────────────────────────────────── describe('formatDate', () => { it('formats short date as dd.mm.yyyy', () => { expect(formatDate('1943-12-24', 'short')).toBe('24.12.1943'); }); it('formats long date with German month name', () => { expect(formatDate('1943-12-24', 'long')).toBe('24. Dezember 1943'); }); it('does not shift Dec 31 to Jan 1 (UTC off-by-one guard)', () => { expect(formatDate('1943-12-31', 'short')).toBe('31.12.1943'); }); it('does not shift Jan 1 to Dec 31 (UTC off-by-one guard)', () => { expect(formatDate('1944-01-01', 'short')).toBe('01.01.1944'); }); }); // ─── statusDotClass ────────────────────────────────────────────────────────── describe('statusDotClass', () => { it('PLACEHOLDER → bg-gray-400', () => { expect(statusDotClass('PLACEHOLDER')).toBe('bg-gray-400'); }); it('UPLOADED → bg-emerald-500', () => { expect(statusDotClass('UPLOADED')).toBe('bg-emerald-500'); }); it('TRANSCRIBED → bg-blue-400', () => { expect(statusDotClass('TRANSCRIBED')).toBe('bg-blue-400'); }); it('REVIEWED → bg-amber-400', () => { expect(statusDotClass('REVIEWED')).toBe('bg-amber-400'); }); it('ARCHIVED → bg-emerald-600', () => { expect(statusDotClass('ARCHIVED')).toBe('bg-emerald-600'); }); }); // ─── statusLabel ───────────────────────────────────────────────────────────── describe('statusLabel', () => { it('PLACEHOLDER → "Platzhalter"', () => { expect(statusLabel('PLACEHOLDER')).toBe('Platzhalter'); }); it('UPLOADED → "Hochgeladen"', () => { expect(statusLabel('UPLOADED')).toBe('Hochgeladen'); }); it('TRANSCRIBED → "Transkribiert"', () => { expect(statusLabel('TRANSCRIBED')).toBe('Transkribiert'); }); it('REVIEWED → "Geprüft"', () => { expect(statusLabel('REVIEWED')).toBe('Geprüft'); }); it('ARCHIVED → "Archiviert"', () => { expect(statusLabel('ARCHIVED')).toBe('Archiviert'); }); });