import { describe, it, expect, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import PersonEditForm from './PersonEditForm.svelte'; afterEach(cleanup); const personPersonal = { id: 'p1', personType: 'PERSON', title: 'Frau Dr.', firstName: 'Anna', lastName: 'Schmidt', alias: 'Anni', birthYear: 1899 as number | null, deathYear: 1972 as number | null, notes: 'Wohnte in Berlin.' }; const personInstitution = { id: 'p2', personType: 'INSTITUTION', title: null, firstName: null, lastName: 'Acme GmbH', alias: null, birthYear: null, deathYear: null, notes: null }; describe('PersonEditForm', () => { it('renders the firstName input for the PERSON personType', async () => { render(PersonEditForm, { props: { person: personPersonal } }); await expect.element(page.getByLabelText(/vorname/i)).toBeVisible(); }); it('renders the title input only for the PERSON personType', async () => { render(PersonEditForm, { props: { person: personPersonal } }); await expect.element(page.getByLabelText(/titel/i)).toBeVisible(); }); it('hides the firstName / title / alias / year fields for INSTITUTION', async () => { render(PersonEditForm, { props: { person: personInstitution } }); await expect.element(page.getByLabelText(/vorname/i)).not.toBeInTheDocument(); await expect.element(page.getByLabelText(/^titel$/i)).not.toBeInTheDocument(); await expect.element(page.getByLabelText(/rufname/i)).not.toBeInTheDocument(); await expect.element(page.getByLabelText(/geburtsjahr/i)).not.toBeInTheDocument(); await expect.element(page.getByLabelText(/todesjahr/i)).not.toBeInTheDocument(); }); it('uses the "Nachname" label for PERSON', async () => { render(PersonEditForm, { props: { person: personPersonal } }); await expect.element(page.getByLabelText(/nachname \*/i)).toBeVisible(); }); it('uses the "Name" label for INSTITUTION', async () => { render(PersonEditForm, { props: { person: personInstitution } }); await expect.element(page.getByLabelText(/^name \*$/i)).toBeVisible(); }); it('hydrates inputs from the person prop', async () => { render(PersonEditForm, { props: { person: personPersonal } }); const firstName = (await page.getByLabelText(/vorname/i).element()) as HTMLInputElement; const lastName = (await page.getByLabelText(/nachname/i).element()) as HTMLInputElement; const alias = (await page.getByLabelText(/rufname/i).element()) as HTMLInputElement; const title = (await page.getByLabelText(/^titel/i).element()) as HTMLInputElement; expect(firstName.value).toBe('Anna'); expect(lastName.value).toBe('Schmidt'); expect(alias.value).toBe('Anni'); expect(title.value).toBe('Frau Dr.'); }); it('renders birthYear and deathYear inputs with prior values', async () => { render(PersonEditForm, { props: { person: personPersonal } }); const birthYear = (await page.getByLabelText(/geburtsjahr/i).element()) as HTMLInputElement; const deathYear = (await page.getByLabelText(/todesjahr/i).element()) as HTMLInputElement; expect(birthYear.value).toBe('1899'); expect(deathYear.value).toBe('1972'); }); it('renders the notes textarea pre-filled with prior content', async () => { render(PersonEditForm, { props: { person: personPersonal } }); const notes = (await page.getByLabelText(/notizen/i).element()) as HTMLTextAreaElement; expect(notes.value).toBe('Wohnte in Berlin.'); }); it('falls back to PERSON when an unknown personType is supplied', async () => { render(PersonEditForm, { props: { person: { ...personPersonal, personType: 'NOT_A_TYPE' } } }); await expect.element(page.getByLabelText(/vorname/i)).toBeVisible(); }); it('renders empty inputs when nullable fields are null', async () => { render(PersonEditForm, { props: { person: { ...personPersonal, title: null, alias: null, birthYear: null } } }); const title = (await page.getByLabelText(/^titel/i).element()) as HTMLInputElement; const alias = (await page.getByLabelText(/rufname/i).element()) as HTMLInputElement; const birthYear = (await page.getByLabelText(/geburtsjahr/i).element()) as HTMLInputElement; expect(title.value).toBe(''); expect(alias.value).toBe(''); expect(birthYear.value).toBe(''); }); // ─── generation dropdown (#689) ───────────────────────────────────────────── it('renders the generation select with G 0…G 6 options when personType is PERSON', async () => { render(PersonEditForm, { props: { person: personPersonal } }); const select = (await page.getByLabelText(/^generation$/i).element()) as HTMLSelectElement; const labels = Array.from(select.options).map((o) => o.label.trim()); expect(labels).toEqual( expect.arrayContaining(['G 0', 'G 1', 'G 2', 'G 3', 'G 4', 'G 5', 'G 6']) ); }); it('hides the generation select for INSTITUTION', async () => { render(PersonEditForm, { props: { person: personInstitution } }); await expect.element(page.getByLabelText(/^generation$/i)).not.toBeInTheDocument(); }); it('hydrates the generation select from person.generation', async () => { render(PersonEditForm, { props: { person: { ...personPersonal, generation: 3 } as typeof personPersonal & { generation: number; } } }); const select = (await page.getByLabelText(/^generation$/i).element()) as HTMLSelectElement; expect(select.value).toBe('3'); }); it('hydrates the generation select to "" when person.generation is null', async () => { render(PersonEditForm, { props: { person: { ...personPersonal, generation: null } as typeof personPersonal & { generation: number | null; } } }); const select = (await page.getByLabelText(/^generation$/i).element()) as HTMLSelectElement; expect(select.value).toBe(''); }); });