test(admin/tags): cover TagsListPanel branches

Tree label rendering, empty placeholder branch, top-level node
rendering, collapse-button visibility, autocollapse vs manual collapse
via localStorage, expand-on-click flow, localStorage parse path,
malformed-JSON resilience.

9 tests, ~25 branches.

Refs #496.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-09 23:06:32 +02:00
parent 4067b2310b
commit 329783a2d5

View File

@@ -0,0 +1,79 @@
import { describe, it, expect, afterEach, beforeEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import TagsListPanel from './TagsListPanel.svelte';
beforeEach(() => {
localStorage.clear();
});
afterEach(cleanup);
const baseTree = [
{ id: 't1', name: 'Personen', parentId: null, color: 'sage', children: [] },
{ id: 't2', name: 'Orte', parentId: null, color: 'sienna', children: [] }
];
describe('TagsListPanel', () => {
it('renders the expanded panel with tree and label', async () => {
render(TagsListPanel, { props: { tree: baseTree } });
await expect.element(page.getByRole('tree', { name: /schlagwörter/i })).toBeVisible();
});
it('renders the empty placeholder when tree is empty', async () => {
render(TagsListPanel, { props: { tree: [] } });
await expect.element(page.getByText('Keine Schlagworte vorhanden.')).toBeVisible();
});
it('renders one tree node per top-level tag', async () => {
render(TagsListPanel, { props: { tree: baseTree } });
await expect.element(page.getByText('Personen')).toBeVisible();
await expect.element(page.getByText('Orte')).toBeVisible();
});
it('renders the collapse button in expanded view', async () => {
render(TagsListPanel, { props: { tree: baseTree } });
await expect.element(page.getByRole('button', { name: /liste einklappen/i })).toBeVisible();
});
it('renders collapsed view when autocollapse is true', async () => {
render(TagsListPanel, { props: { tree: baseTree, autocollapse: true } });
await expect.element(page.getByRole('button', { name: /liste ausklappen/i })).toBeVisible();
});
it('honours the localStorage manual-collapse preference', async () => {
localStorage.setItem('admin_tags_list_collapsed', 'true');
render(TagsListPanel, { props: { tree: baseTree } });
await expect.element(page.getByRole('button', { name: /liste ausklappen/i })).toBeVisible();
});
it('expands the panel when the collapsed handle is clicked', async () => {
localStorage.setItem('admin_tags_list_collapsed', 'true');
render(TagsListPanel, { props: { tree: baseTree } });
await page.getByRole('button', { name: /liste ausklappen/i }).click();
await expect.element(page.getByRole('tree')).toBeVisible();
});
it('reads the collapse map from localStorage on mount', async () => {
localStorage.setItem('admin_tags_tree_state', JSON.stringify({ t1: true }));
render(TagsListPanel, { props: { tree: baseTree } });
// Just verify it doesn't crash on JSON parse
await expect.element(page.getByRole('tree')).toBeVisible();
});
it('handles malformed localStorage tree state gracefully', async () => {
localStorage.setItem('admin_tags_tree_state', 'not-valid-json{');
render(TagsListPanel, { props: { tree: baseTree } });
await expect.element(page.getByRole('tree')).toBeVisible();
});
});