Align PersonCard's "unbestätigt" badge with the authoritative provisional flag so the badge, the "Zu prüfen (N)" count and the /persons/review triage list can never disagree. Empty/"?" name handling is now a separate crash-safety concern: it still routes to the neutral placeholder glyph (never a "?" initial) but no longer implies a badge on its own. Refs #667 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
88 lines
3.2 KiB
TypeScript
88 lines
3.2 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
import { cleanup, render } from 'vitest-browser-svelte';
|
|
import { page } from 'vitest/browser';
|
|
import PersonCard from './PersonCard.svelte';
|
|
import type { components } from '$lib/generated/api';
|
|
|
|
type Person = components['schemas']['PersonSummaryDTO'];
|
|
|
|
const makePerson = (overrides: Partial<Person> = {}): Person => ({
|
|
id: 'p-1',
|
|
firstName: 'Anna',
|
|
lastName: 'Schmidt',
|
|
displayName: 'Anna Schmidt',
|
|
personType: 'PERSON',
|
|
familyMember: false,
|
|
provisional: false,
|
|
documentCount: 0,
|
|
...overrides
|
|
});
|
|
|
|
afterEach(cleanup);
|
|
|
|
describe('PersonCard — confirmed person', () => {
|
|
it('renders the display name', async () => {
|
|
render(PersonCard, { props: { person: makePerson() } });
|
|
await expect.element(page.getByText('Anna Schmidt')).toBeVisible();
|
|
});
|
|
|
|
it('does not show an unconfirmed badge for a confirmed person', async () => {
|
|
render(PersonCard, { props: { person: makePerson() } });
|
|
await expect.element(page.getByText('unbestätigt')).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('PersonCard — unconfirmed badge keys off provisional only (badge ⇔ count ⇔ triage parity)', () => {
|
|
it('renders without throwing when lastName is null', async () => {
|
|
// Before the fix, `lastName[0]` threw at render for a null lastName. Empty-name
|
|
// crash-safety is a SEPARATE concern from the badge: the placeholder glyph renders
|
|
// regardless, but the "unbestätigt" badge only fires when provisional is true.
|
|
const person = makePerson({
|
|
lastName: null as unknown as string,
|
|
displayName: '?',
|
|
provisional: true
|
|
});
|
|
render(PersonCard, { props: { person } });
|
|
// No throw + provisional → the badge is shown.
|
|
await expect.element(page.getByText('unbestätigt')).toBeVisible();
|
|
});
|
|
|
|
it('shows an unbestätigt badge for a provisional person', async () => {
|
|
render(PersonCard, { props: { person: makePerson({ provisional: true }) } });
|
|
await expect.element(page.getByText('unbestätigt')).toBeVisible();
|
|
});
|
|
|
|
it('does NOT show the badge for a "?" name when not provisional', async () => {
|
|
// Empty/"?" name alone is no longer treated as unconfirmed — only `provisional` is.
|
|
// This keeps the badge in lockstep with needsReviewCount and the /persons/review list.
|
|
render(PersonCard, {
|
|
props: {
|
|
person: makePerson({ firstName: undefined, lastName: '?', displayName: '?' })
|
|
}
|
|
});
|
|
await expect.element(page.getByText('unbestätigt')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('does NOT show the badge for an UNKNOWN type when not provisional', async () => {
|
|
render(PersonCard, {
|
|
props: { person: makePerson({ personType: 'UNKNOWN', displayName: 'Unklar' }) }
|
|
});
|
|
await expect.element(page.getByText('unbestätigt')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('renders the placeholder glyph (never a "?" initial) for an empty name even without provisional', async () => {
|
|
// Crash-safety branch: a null/empty lastName must not throw and must not show "?".
|
|
render(PersonCard, {
|
|
props: {
|
|
person: makePerson({
|
|
firstName: undefined,
|
|
lastName: null as unknown as string,
|
|
displayName: 'Unbekannt'
|
|
})
|
|
}
|
|
});
|
|
await expect.element(page.getByText('Unbekannt')).toBeVisible();
|
|
await expect.element(page.getByText('unbestätigt')).not.toBeInTheDocument();
|
|
});
|
|
});
|