import { describe, expect, it, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import DateInput from './DateInput.svelte'; afterEach(() => cleanup()); // ─── Rendering ──────────────────────────────────────────────────────────────── describe('DateInput – rendering', () => { it('renders a text input with inputmode=numeric and maxlength=10', async () => { render(DateInput, {}); const input = page.getByRole('textbox'); await expect.element(input).toBeInTheDocument(); await expect.element(input).toHaveAttribute('inputmode', 'numeric'); await expect.element(input).toHaveAttribute('maxlength', '10'); }); it('has default placeholder from paraglide', async () => { render(DateInput, {}); const input = page.getByRole('textbox'); await expect.element(input).toHaveAttribute('placeholder', 'TT.MM.JJJJ'); }); it('accepts a custom placeholder', async () => { render(DateInput, { placeholder: 'Geburtsdatum' }); const input = page.getByRole('textbox'); await expect.element(input).toHaveAttribute('placeholder', 'Geburtsdatum'); }); it('passes id prop to the input', async () => { render(DateInput, { id: 'my-date' }); const input = page.getByRole('textbox'); await expect.element(input).toHaveAttribute('id', 'my-date'); }); }); // ─── Init from value ────────────────────────────────────────────────────────── describe('DateInput – init from value', () => { it('displays ISO value in German format on mount', async () => { render(DateInput, { value: '2024-12-20' }); const input = page.getByRole('textbox'); await expect.element(input).toHaveValue('20.12.2024'); }); it('starts empty and error-free when no value is given', async () => { let errorMessage: string | null = null; render(DateInput, { get errorMessage() { return errorMessage; }, set errorMessage(v) { errorMessage = v; } }); const input = page.getByRole('textbox'); await expect.element(input).toHaveValue(''); expect(errorMessage).toBeNull(); }); }); // ─── Typing valid date ──────────────────────────────────────────────────────── describe('DateInput – typing a valid date', () => { it('auto-formats to DD.MM.YYYY and updates value to ISO', async () => { let value = ''; let errorMessage: string | null = null; render(DateInput, { get value() { return value; }, set value(v) { value = v; }, get errorMessage() { return errorMessage; }, set errorMessage(v) { errorMessage = v; } }); const input = page.getByRole('textbox'); await input.fill('20122024'); await expect.element(input).toHaveValue('20.12.2024'); expect(value).toBe('2024-12-20'); expect(errorMessage).toBeNull(); }); }); // ─── Typing invalid month ───────────────────────────────────────────────────── describe('DateInput – typing a date with invalid month', () => { it('sets errorMessage and clears value when month > 12', async () => { let value = ''; let errorMessage: string | null = null; render(DateInput, { get value() { return value; }, set value(v) { value = v; }, get errorMessage() { return errorMessage; }, set errorMessage(v) { errorMessage = v; } }); const input = page.getByRole('textbox'); await input.fill('22222222'); await expect.element(input).toHaveValue('22.22.2222'); expect(value).toBe(''); expect(errorMessage).not.toBeNull(); }); }); // ─── Typing partial date ────────────────────────────────────────────────────── describe('DateInput – typing a partial date', () => { it('sets errorMessage and clears value when date is incomplete', async () => { let value = ''; let errorMessage: string | null = null; render(DateInput, { get value() { return value; }, set value(v) { value = v; }, get errorMessage() { return errorMessage; }, set errorMessage(v) { errorMessage = v; } }); const input = page.getByRole('textbox'); await input.fill('2212'); await expect.element(input).toHaveValue('22.12'); expect(value).toBe(''); expect(errorMessage).not.toBeNull(); }); }); // ─── Clearing date ──────────────────────────────────────────────────────────── describe('DateInput – clearing the date', () => { it('resets value and errorMessage to null when cleared', async () => { let value = ''; let errorMessage: string | null = null; render(DateInput, { get value() { return value; }, set value(v) { value = v; }, get errorMessage() { return errorMessage; }, set errorMessage(v) { errorMessage = v; } }); const input = page.getByRole('textbox'); // Type a valid date first await input.fill('20122024'); expect(value).toBe('2024-12-20'); // Now clear await input.fill(''); expect(value).toBe(''); expect(errorMessage).toBeNull(); }); it('fires onchange when the field is cleared', async () => { let called = 0; render(DateInput, { value: '2024-12-20', onchange: () => called++ }); const input = page.getByRole('textbox'); await input.fill(''); expect(called).toBeGreaterThan(0); }); }); // ─── External value changes ─────────────────────────────────────────────────── describe('DateInput – external value changes', () => { it('clears display when value prop is reset to empty externally', async () => { const { rerender } = render(DateInput, { value: '1920-01-01' }); const input = page.getByRole('textbox'); await expect.element(input).toHaveValue('01.01.1920'); await rerender({ value: '' }); await expect.element(input).toHaveValue(''); }); it('updates display when value prop changes to a new date externally', async () => { const { rerender } = render(DateInput, { value: '1920-01-01' }); const input = page.getByRole('textbox'); await expect.element(input).toHaveValue('01.01.1920'); await rerender({ value: '1945-05-08' }); await expect.element(input).toHaveValue('08.05.1945'); }); }); // ─── Hidden input ───────────────────────────────────────────────────────────── describe('DateInput – hidden input for form submission', () => { it('renders a hidden input with the given name when name prop is set', async () => { render(DateInput, { name: 'documentDate' }); const hidden = document.querySelector('input[type="hidden"][name="documentDate"]'); expect(hidden).not.toBeNull(); }); it('does not render a hidden input when name prop is absent', async () => { render(DateInput, {}); const hidden = document.querySelector('input[type="hidden"]'); expect(hidden).toBeNull(); }); it('hidden input value reflects the ISO value', async () => { render(DateInput, { name: 'documentDate', value: '' }); const input = page.getByRole('textbox'); await input.fill('20122024'); const hidden = document.querySelector( 'input[type="hidden"][name="documentDate"]' ); await expect.poll(() => hidden?.value).toBe('2024-12-20'); }); });