From fc2320ccb1c00d5ee4e5af01d6e7c3771f6b36cd Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 10 May 2026 08:24:37 +0200 Subject: [PATCH] test(relationship): expand AddRelationshipForm coverage use:enhance vs callback form variant rendering, self-relation error, submit disabled on missing related person, submit disabled on yearError. 5 new tests covering ~10 branches. Refs #496. Co-Authored-By: Claude Sonnet 4.6 --- .../AddRelationshipForm.svelte.test.ts | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/frontend/src/lib/person/relationship/AddRelationshipForm.svelte.test.ts b/frontend/src/lib/person/relationship/AddRelationshipForm.svelte.test.ts index 4ad56a54..705fee7b 100644 --- a/frontend/src/lib/person/relationship/AddRelationshipForm.svelte.test.ts +++ b/frontend/src/lib/person/relationship/AddRelationshipForm.svelte.test.ts @@ -88,4 +88,77 @@ describe('AddRelationshipForm', () => { // but at least verify the prop is wired (no crash). expect(onSubmit).not.toHaveBeenCalled(); }); + + it('renders with use:enhance form action when onSubmit is undefined', async () => { + render(AddRelationshipForm, { props: { personId: 'p-1' } }); + + await page.getByRole('button', { name: /hinzufügen/i }).click(); + await new Promise((r) => setTimeout(r, 30)); + + const form = document.querySelector('form[action="?/addRelationship"]'); + expect(form).not.toBeNull(); + }); + + it('renders the callback-based form when onSubmit is provided', async () => { + render(AddRelationshipForm, { props: { personId: 'p-1', onSubmit: async () => {} } }); + + await page.getByRole('button', { name: /hinzufügen/i }).click(); + await new Promise((r) => setTimeout(r, 30)); + + // callback form has no action attribute (just onsubmit handler) + const enhancedForm = document.querySelector('form[action="?/addRelationship"]'); + expect(enhancedForm).toBeNull(); + const fallbackForm = document.querySelector('form'); + expect(fallbackForm).not.toBeNull(); + }); + + it('shows the self-error when the related person id equals personId', async () => { + render(AddRelationshipForm, { props: { personId: 'p-self' } }); + + await page.getByRole('button', { name: /hinzufügen/i }).click(); + await new Promise((r) => setTimeout(r, 30)); + + // Set the relatedPersonId hidden input to match personId + const relInput = document.querySelector('input[name="relatedPersonId"]') as HTMLInputElement; + relInput.value = 'p-self'; + relInput.dispatchEvent(new Event('input', { bubbles: true })); + await new Promise((r) => setTimeout(r, 30)); + + await expect.element(page.getByText(/selbst|self/i)).toBeVisible(); + }); + + it('keeps submit disabled when no related person is selected', async () => { + render(AddRelationshipForm, { props: { personId: 'p-1' } }); + + await page.getByRole('button', { name: /hinzufügen/i }).click(); + await new Promise((r) => setTimeout(r, 30)); + + // The "Hinzufügen" button changed from toggle button → submit button. Find the submit one. + const submitBtn = Array.from( + document.querySelectorAll('button[type="submit"]') + )[0] as HTMLButtonElement; + expect(submitBtn.disabled).toBe(true); + }); + + it('keeps submit disabled when there is a yearError', async () => { + render(AddRelationshipForm, { props: { personId: 'p-1' } }); + + await page.getByRole('button', { name: /hinzufügen/i }).click(); + + const fromInput = document.querySelector('input[name="fromYear"]') as HTMLInputElement; + const toInput = document.querySelector('input[name="toYear"]') as HTMLInputElement; + const relInput = document.querySelector('input[name="relatedPersonId"]') as HTMLInputElement; + fromInput.value = '1923'; + fromInput.dispatchEvent(new Event('input', { bubbles: true })); + toInput.value = '1920'; + toInput.dispatchEvent(new Event('input', { bubbles: true })); + relInput.value = 'p-other'; + relInput.dispatchEvent(new Event('input', { bubbles: true })); + + await new Promise((r) => setTimeout(r, 30)); + const submitBtn = Array.from( + document.querySelectorAll('button[type="submit"]') + )[0] as HTMLButtonElement; + expect(submitBtn.disabled).toBe(true); + }); });