161 lines
6.2 KiB
TypeScript
161 lines
6.2 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
import { cleanup, render } from 'vitest-browser-svelte';
|
|
import { page } from 'vitest/browser';
|
|
import AddRelationshipForm from './AddRelationshipForm.svelte';
|
|
|
|
afterEach(cleanup);
|
|
|
|
describe('AddRelationshipForm', () => {
|
|
it('renders the toggle button to open the form', async () => {
|
|
render(AddRelationshipForm, { props: { personId: 'p-1' } });
|
|
|
|
await expect.element(page.getByRole('button', { name: /hinzufügen/i })).toBeVisible();
|
|
});
|
|
|
|
it('opens the form when the toggle button is clicked', async () => {
|
|
render(AddRelationshipForm, { props: { personId: 'p-1' } });
|
|
|
|
await page.getByRole('button', { name: /hinzufügen/i }).click();
|
|
|
|
expect(document.querySelector('select[name="relationType"]')).not.toBeNull();
|
|
});
|
|
|
|
it('renders all relationship type options when open', async () => {
|
|
render(AddRelationshipForm, { props: { personId: 'p-1' } });
|
|
|
|
await page.getByRole('button', { name: /hinzufügen/i }).click();
|
|
|
|
const select = document.querySelector('select[name="relationType"]') as HTMLSelectElement;
|
|
const optionValues = Array.from(select.options).map((o) => o.value);
|
|
expect(optionValues).toContain('PARENT_OF');
|
|
expect(optionValues).toContain('SPOUSE_OF');
|
|
expect(optionValues).toContain('FRIEND');
|
|
expect(optionValues).toContain('OTHER');
|
|
});
|
|
|
|
it('shows the year-error alert when toYear is before fromYear', 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;
|
|
fromInput.value = '1923';
|
|
fromInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
toInput.value = '1920';
|
|
toInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
|
|
await expect.element(page.getByText(/bis-jahr darf nicht vor von-jahr/i)).toBeVisible();
|
|
});
|
|
|
|
it('does not show the year-error when toYear equals fromYear', 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;
|
|
fromInput.value = '1923';
|
|
fromInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
toInput.value = '1923';
|
|
toInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
|
|
await expect.element(page.getByText(/bis-jahr darf nicht/i)).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('cancel button closes the form', async () => {
|
|
render(AddRelationshipForm, { props: { personId: 'p-1' } });
|
|
|
|
await page.getByRole('button', { name: /hinzufügen/i }).click();
|
|
expect(document.querySelector('select[name="relationType"]')).not.toBeNull();
|
|
|
|
const cancelBtn = Array.from(document.querySelectorAll('button')).find((b) =>
|
|
b.textContent?.toLowerCase().includes('abbrechen')
|
|
);
|
|
expect(cancelBtn).toBeDefined();
|
|
cancelBtn?.click();
|
|
|
|
await vi.waitFor(() => {
|
|
expect(document.querySelector('select[name="relationType"]')).toBeNull();
|
|
});
|
|
});
|
|
|
|
it('does not invoke onSubmit before user submission', async () => {
|
|
const onSubmit = vi.fn().mockResolvedValue(undefined);
|
|
render(AddRelationshipForm, { props: { personId: 'p-1', onSubmit } });
|
|
|
|
// Without a person selected, the form cannot be submitted by the user.
|
|
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 vi.waitFor(() => {
|
|
expect(document.querySelector('form[action="?/addRelationship"]')).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 vi.waitFor(() => {
|
|
// callback form has no action attribute (just onsubmit handler)
|
|
expect(document.querySelector('form[action="?/addRelationship"]')).toBeNull();
|
|
expect(document.querySelector('form')).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();
|
|
const relInput = (await vi.waitFor(() => {
|
|
const el = document.querySelector('input[name="relatedPersonId"]') as HTMLInputElement;
|
|
expect(el).not.toBeNull();
|
|
return el;
|
|
})) as HTMLInputElement;
|
|
relInput.value = 'p-self';
|
|
relInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
|
|
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 vi.waitFor(() => {
|
|
const submitBtn = document.querySelector('button[type="submit"]') as HTMLButtonElement | null;
|
|
expect(submitBtn).not.toBeNull();
|
|
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 vi.waitFor(() => {
|
|
const submitBtn = document.querySelector('button[type="submit"]') as HTMLButtonElement;
|
|
expect(submitBtn.disabled).toBe(true);
|
|
});
|
|
});
|
|
});
|