Files
familienarchiv/frontend/src/lib/shared/primitives/DateInput.svelte.spec.ts
2026-05-05 14:40:14 +02:00

211 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
});
});
// ─── 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<HTMLInputElement>(
'input[type="hidden"][name="documentDate"]'
);
await expect.poll(() => hidden?.value).toBe('2024-12-20');
});
});