feat(search): render removable theme chips in InterpretationChipRow
When tagsApplied is true, each resolvedTag renders as a 'Thema: Name'
chip with optional inline color style from the tag's resolved color.
Clicking × calls onRemoveChip('theme', tag.name).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import type { components } from '$lib/generated/api';
|
||||
|
||||
type NlQueryInterpretation = components['schemas']['NlQueryInterpretation'];
|
||||
type PersonHint = components['schemas']['PersonHint'];
|
||||
type TagHint = components['schemas']['TagHint'];
|
||||
|
||||
afterEach(() => cleanup());
|
||||
|
||||
@@ -132,4 +133,79 @@ describe('InterpretationChipRow', () => {
|
||||
.element(page.getByRole('button', { name: new RegExp('Absender') }))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
|
||||
// ── theme chips ─────────────────────────────────────────────────────────────
|
||||
|
||||
const makeTag = (id: string, name: string, color?: string): TagHint => ({ id, name, color });
|
||||
|
||||
it('renders theme chips when tagsApplied is true', async () => {
|
||||
const { container } = render(InterpretationChipRow, {
|
||||
interpretation: makeInterpretation({
|
||||
resolvedTags: [makeTag('t1', 'Hochzeit')],
|
||||
tagsApplied: true
|
||||
}),
|
||||
onRemoveChip: vi.fn()
|
||||
});
|
||||
expect(container.querySelectorAll('[data-chip-type="theme"]')).toHaveLength(1);
|
||||
await expect.element(page.getByText(/Thema: Hochzeit/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders no theme chips when tagsApplied is false', async () => {
|
||||
const { container } = render(InterpretationChipRow, {
|
||||
interpretation: makeInterpretation({
|
||||
resolvedTags: [makeTag('t1', 'Hochzeit')],
|
||||
tagsApplied: false
|
||||
}),
|
||||
onRemoveChip: vi.fn()
|
||||
});
|
||||
expect(container.querySelectorAll('[data-chip-type="theme"]')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('renders exactly N theme chips for N resolved tags', async () => {
|
||||
const { container } = render(InterpretationChipRow, {
|
||||
interpretation: makeInterpretation({
|
||||
resolvedTags: [makeTag('t1', 'Krieg'), makeTag('t2', 'Hochzeit'), makeTag('t3', 'Familie')],
|
||||
tagsApplied: true
|
||||
}),
|
||||
onRemoveChip: vi.fn()
|
||||
});
|
||||
expect(container.querySelectorAll('[data-chip-type="theme"]')).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('calls onRemoveChip with "theme" and tag name when × is clicked', async () => {
|
||||
const onRemoveChip = vi.fn();
|
||||
render(InterpretationChipRow, {
|
||||
interpretation: makeInterpretation({
|
||||
resolvedTags: [makeTag('t1', 'Hochzeit')],
|
||||
tagsApplied: true
|
||||
}),
|
||||
onRemoveChip
|
||||
});
|
||||
await page.getByRole('button', { name: /Thema: Hochzeit/ }).click();
|
||||
expect(onRemoveChip).toHaveBeenCalledWith('theme', 'Hochzeit');
|
||||
});
|
||||
|
||||
it('applies inline color style for a tag with a color', async () => {
|
||||
const { container } = render(InterpretationChipRow, {
|
||||
interpretation: makeInterpretation({
|
||||
resolvedTags: [makeTag('t1', 'Hochzeit', 'sage')],
|
||||
tagsApplied: true
|
||||
}),
|
||||
onRemoveChip: vi.fn()
|
||||
});
|
||||
const chip = container.querySelector('[data-chip-type="theme"]') as HTMLElement;
|
||||
expect(chip.style.backgroundColor).toBeTruthy();
|
||||
});
|
||||
|
||||
it('omits color style for a tag with no color', async () => {
|
||||
const { container } = render(InterpretationChipRow, {
|
||||
interpretation: makeInterpretation({
|
||||
resolvedTags: [makeTag('t1', 'Hochzeit')],
|
||||
tagsApplied: true
|
||||
}),
|
||||
onRemoveChip: vi.fn()
|
||||
});
|
||||
const chip = container.querySelector('[data-chip-type="theme"]') as HTMLElement;
|
||||
expect(chip.getAttribute('style')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user