Files
familienarchiv/frontend/src/routes/persons/[id]/edit/NameHistoryEditCard.svelte.spec.ts
Marcel 1a519eedd6
Some checks failed
CI / Unit & Component Tests (push) Failing after 4s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 3s
CI / Backend Unit Tests (pull_request) Failing after 2s
refactor(persons): replace inline delete modal with ConfirmService in NameHistoryEditCard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 14:19:33 +02:00

119 lines
4.6 KiB
TypeScript

import { describe, it, expect, vi, afterEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import NameHistoryEditCard from './NameHistoryEditCard.svelte';
import { createConfirmService, CONFIRM_KEY } from '$lib/services/confirm.svelte.js';
vi.mock('$app/forms', () => ({ enhance: () => () => {} }));
afterEach(cleanup);
const aliases = [
{ id: 'a1', lastName: 'Müller', firstName: 'Anna', type: 'BIRTH', sortOrder: 0 },
{ id: 'a2', lastName: 'Schmidt', firstName: null, type: 'MARRIED', sortOrder: 1 }
];
function renderCard(overrides: Record<string, unknown> = {}) {
const service = createConfirmService();
const result = render(NameHistoryEditCard, {
props: { aliases, canWrite: true, ...overrides },
context: new Map([[CONFIRM_KEY, service]])
});
return { ...result, service };
}
// ─── Rendering ────────────────────────────────────────────────────────────────
describe('NameHistoryEditCard — rendering', () => {
it('renders alias last names', async () => {
renderCard();
await expect.element(page.getByText('Müller')).toBeInTheDocument();
await expect.element(page.getByText('Schmidt')).toBeInTheDocument();
});
it('renders delete buttons when canWrite', async () => {
renderCard();
const btns = document.querySelectorAll('button[type="button"]');
expect(btns.length).toBeGreaterThanOrEqual(2);
});
it('does not render delete buttons when canWrite is false', async () => {
renderCard({ canWrite: false });
const btns = document.querySelectorAll<HTMLButtonElement>('button[type="button"]');
expect(btns.length).toBe(0);
});
it('does not show the inline delete modal (replaced by ConfirmService)', async () => {
renderCard();
// The old inline modal div with "fixed inset-0" should not exist
const modal = document.querySelector('.fixed.inset-0');
expect(modal).toBeNull();
});
});
// ─── Delete confirmation ──────────────────────────────────────────────────────
describe('NameHistoryEditCard — delete confirmation', () => {
it('opens confirm dialog when delete button is clicked', async () => {
const { service } = renderCard();
const deleteBtn = document.querySelector<HTMLButtonElement>('button[type="button"]')!;
deleteBtn.click();
await vi.waitFor(() => expect(service.options).not.toBeNull());
expect(service.options?.destructive).toBe(true);
service.settle(false);
});
it('submits removeAlias form when user confirms', async () => {
const { service } = renderCard();
const requestSubmit = vi
.spyOn(HTMLFormElement.prototype, 'requestSubmit')
.mockImplementation(() => {});
const deleteBtn = document.querySelector<HTMLButtonElement>('button[type="button"]')!;
deleteBtn.click();
await vi.waitFor(() => expect(service.options).not.toBeNull());
service.settle(true);
// Wait for the async handleDelete callback to call requestSubmit
await vi.waitFor(() => expect(requestSubmit).toHaveBeenCalledOnce());
requestSubmit.mockRestore();
});
it('does not submit form when user cancels', async () => {
const { service } = renderCard();
const requestSubmit = vi
.spyOn(HTMLFormElement.prototype, 'requestSubmit')
.mockImplementation(() => {});
const deleteBtn = document.querySelector<HTMLButtonElement>('button[type="button"]')!;
deleteBtn.click();
await vi.waitFor(() => expect(service.options).not.toBeNull());
service.settle(false);
await vi.waitFor(() => expect(service.options).toBeNull());
// Allow pending microtasks to flush before asserting
await Promise.resolve();
expect(requestSubmit).not.toHaveBeenCalled();
requestSubmit.mockRestore();
});
it('submits with the correct aliasId when second alias is deleted', async () => {
const { service } = renderCard();
const requestSubmit = vi
.spyOn(HTMLFormElement.prototype, 'requestSubmit')
.mockImplementation(() => {});
// Click delete button for the second alias (Schmidt)
const deleteBtns = document.querySelectorAll<HTMLButtonElement>('button[type="button"]');
deleteBtns[1].click();
await vi.waitFor(() => expect(service.options).not.toBeNull());
service.settle(true);
await vi.waitFor(() => expect(requestSubmit).toHaveBeenCalledOnce());
const submittedForm = requestSubmit.mock.instances[0] as HTMLFormElement;
const aliasIdInput = submittedForm.querySelector<HTMLInputElement>('input[name="aliasId"]');
expect(aliasIdInput?.value).toBe('a2');
requestSubmit.mockRestore();
});
});