test(admin/groups): cover GroupsListPanel branches
Expanded list with header, per-group rendering with permission count, empty placeholder branch, new-group link, aria-current matrix, collapsed view via autocollapse prop, localStorage preference path, expand-on-click flow. 8 tests covering ~25 branches (collapsed/expanded × autocollapse × localStorage × empty × active matrix). Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
109
frontend/src/routes/admin/groups/GroupsListPanel.svelte.test.ts
Normal file
109
frontend/src/routes/admin/groups/GroupsListPanel.svelte.test.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page as browserPage } from 'vitest/browser';
|
||||
|
||||
const mockPage = { url: new URL('http://localhost/admin/groups') };
|
||||
|
||||
vi.mock('$app/state', () => ({
|
||||
get page() {
|
||||
return mockPage;
|
||||
}
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
async function loadComponent() {
|
||||
return (await import('./GroupsListPanel.svelte')).default;
|
||||
}
|
||||
|
||||
const baseGroups = [
|
||||
{ id: 'g1', name: 'Familie', permissions: ['READ_ALL'] },
|
||||
{ id: 'g2', name: 'Admins', permissions: ['ADMIN', 'WRITE_ALL'] }
|
||||
];
|
||||
|
||||
describe('GroupsListPanel', () => {
|
||||
it('renders the expanded list with header by default', async () => {
|
||||
mockPage.url = new URL('http://localhost/admin/groups');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: baseGroups } });
|
||||
|
||||
await expect.element(browserPage.getByText('Alle Gruppen')).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders one row per group with permission count', async () => {
|
||||
mockPage.url = new URL('http://localhost/admin/groups');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: baseGroups } });
|
||||
|
||||
await expect.element(browserPage.getByText('Familie')).toBeVisible();
|
||||
await expect.element(browserPage.getByText('Admins')).toBeVisible();
|
||||
await expect.element(browserPage.getByText('1 Berechtigungen')).toBeVisible();
|
||||
await expect.element(browserPage.getByText('2 Berechtigungen')).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders the empty placeholder when groups is empty', async () => {
|
||||
mockPage.url = new URL('http://localhost/admin/groups');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: [] } });
|
||||
|
||||
await expect.element(browserPage.getByText('Keine Gruppen vorhanden.')).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders the new-group link to /admin/groups/new', async () => {
|
||||
mockPage.url = new URL('http://localhost/admin/groups');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: baseGroups } });
|
||||
|
||||
await expect
|
||||
.element(browserPage.getByRole('link', { name: /neue gruppe/i }))
|
||||
.toHaveAttribute('href', '/admin/groups/new');
|
||||
});
|
||||
|
||||
it('marks the active group with aria-current=page', async () => {
|
||||
mockPage.url = new URL('http://localhost/admin/groups/g2');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: baseGroups } });
|
||||
|
||||
const links = Array.from(
|
||||
document.querySelectorAll('a[href^="/admin/groups/"]')
|
||||
) as HTMLAnchorElement[];
|
||||
const adminsLink = links.find((a) => a.href.endsWith('/admin/groups/g2'));
|
||||
expect(adminsLink?.getAttribute('aria-current')).toBe('page');
|
||||
});
|
||||
|
||||
it('renders collapsed view when autocollapse is true', async () => {
|
||||
mockPage.url = new URL('http://localhost/admin/groups');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: baseGroups, autocollapse: true } });
|
||||
|
||||
await expect
|
||||
.element(browserPage.getByRole('button', { name: /liste ausklappen/i }))
|
||||
.toBeVisible();
|
||||
});
|
||||
|
||||
it('honours the localStorage manual-collapse preference', async () => {
|
||||
localStorage.setItem('admin_groups_list_collapsed', 'true');
|
||||
mockPage.url = new URL('http://localhost/admin/groups');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: baseGroups } });
|
||||
|
||||
await expect
|
||||
.element(browserPage.getByRole('button', { name: /liste ausklappen/i }))
|
||||
.toBeVisible();
|
||||
});
|
||||
|
||||
it('expands the panel when the collapsed handle is clicked', async () => {
|
||||
localStorage.setItem('admin_groups_list_collapsed', 'true');
|
||||
mockPage.url = new URL('http://localhost/admin/groups');
|
||||
const Panel = await loadComponent();
|
||||
render(Panel, { props: { groups: baseGroups } });
|
||||
|
||||
await browserPage.getByRole('button', { name: /liste ausklappen/i }).click();
|
||||
|
||||
await expect.element(browserPage.getByText('Alle Gruppen')).toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user