import { describe, it, expect, vi, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import WhoWhenSection from './WhoWhenSection.svelte'; afterEach(cleanup); describe('WhoWhenSection — date input behavior', () => { it('marks the date input as invalid when input has text but no valid ISO', async () => { render(WhoWhenSection, {}); const dateInput = document.querySelector('input#documentDate') as HTMLInputElement; dateInput.value = '32.13'; dateInput.dispatchEvent(new Event('input', { bubbles: true })); await vi.waitFor(() => { // Invalid → border-red-400 class expect(dateInput.className).toContain('border-red-400'); expect(document.querySelector('#date-error')).not.toBeNull(); }); }); it('does not show the error before the user has typed', async () => { render(WhoWhenSection, {}); const error = document.querySelector('#date-error'); expect(error).toBeNull(); }); it('updates the hidden ISO input when typing a valid German date', async () => { render(WhoWhenSection, {}); const dateInput = document.querySelector('input#documentDate') as HTMLInputElement; dateInput.value = '15.03.2024'; dateInput.dispatchEvent(new Event('input', { bubbles: true })); await vi.waitFor(() => { const hidden = document.querySelector( 'input[name="documentDate"][type="hidden"]' ) as HTMLInputElement; expect(hidden.value).toBe('2024-03-15'); }); }); it('renders the location input outside editMode with initialLocation', async () => { render(WhoWhenSection, { editMode: false, initialLocation: 'Hamburg' }); const loc = document.querySelector('input#location') as HTMLInputElement; expect(loc.value).toBe('Hamburg'); }); it('hides the location input in editMode', async () => { render(WhoWhenSection, { editMode: true }); const loc = document.querySelector('input#location'); expect(loc).toBeNull(); }); it('shows the FieldLabelBadge for receivers in editMode', async () => { render(WhoWhenSection, { editMode: true }); // FieldLabelBadge with variant=additive is rendered (just check the heading area) const labels = Array.from(document.querySelectorAll('p, label')).filter((el) => /empfänger/i.test(el.textContent ?? '') ); expect(labels.length).toBeGreaterThan(0); }); it('renders the date asterisk indicator (required field)', async () => { render(WhoWhenSection, {}); const label = document.querySelector('label[for="documentDate"]'); expect(label?.textContent).toContain('*'); }); }); describe('WhoWhenSection — precision controls', () => { it('renders a labelled precision select', async () => { render(WhoWhenSection, {}); const label = document.querySelector('label[for="metaDatePrecision"]'); const select = document.querySelector('select#metaDatePrecision[name="metaDatePrecision"]'); expect(label).not.toBeNull(); expect(select).not.toBeNull(); }); it('hides the end-date field unless precision is RANGE', async () => { render(WhoWhenSection, { precision: 'DAY' }); expect(document.querySelector('input#metaDateEnd')).toBeNull(); }); it('reveals the end-date field when precision is RANGE', async () => { render(WhoWhenSection, { precision: 'RANGE' }); expect(document.querySelector('input#metaDateEnd')).not.toBeNull(); }); it('renders the raw cell as static text (not an editable input) and escapes it', async () => { render(WhoWhenSection, { rawDate: 'Sommer 1916' }); const raw = document.querySelector('[data-testid="who-when-raw"]'); expect(raw).not.toBeNull(); // Verbatim shown as escaped text; no injected element. expect(raw?.textContent).toContain('Sommer 1916'); expect(raw?.querySelector('b')).toBeNull(); }); }); describe('WhoWhenSection — end-before-start inline validation (#678)', () => { it('shows an inline error on the end-date field when end is before start (AC1)', async () => { render(WhoWhenSection, { precision: 'RANGE', dateIso: '1917-01-11', endDateIso: '1917-01-10' }); const end = document.querySelector('input#metaDateEnd') as HTMLInputElement; await vi.waitFor(() => { expect(document.querySelector('#end-date-error')).not.toBeNull(); expect(end.getAttribute('aria-invalid')).toBe('true'); expect(end.className).toContain('border-red-400'); }); }); it('clears the inline error once the end date is corrected, without reload (AC5)', async () => { render(WhoWhenSection, { precision: 'RANGE', dateIso: '1917-01-11', endDateIso: '1917-01-10' }); await vi.waitFor(() => expect(document.querySelector('#end-date-error')).not.toBeNull()); const end = document.querySelector('input#metaDateEnd') as HTMLInputElement; end.value = '12.01.1917'; // now after the start end.dispatchEvent(new Event('input', { bubbles: true })); await vi.waitFor(() => { expect(document.querySelector('#end-date-error')).toBeNull(); expect(end.getAttribute('aria-invalid')).not.toBe('true'); }); }); it('does not show the inline error when precision is not RANGE', async () => { render(WhoWhenSection, { precision: 'DAY', dateIso: '1917-01-11', endDateIso: '1917-01-10' }); expect(document.querySelector('#end-date-error')).toBeNull(); }); });