Files
familienarchiv/frontend/src/routes/admin/layout.svelte.spec.ts
Marcel daea748a20
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m37s
CI / OCR Service Tests (push) Successful in 32s
CI / OCR Service Tests (pull_request) Successful in 30s
CI / Backend Unit Tests (push) Failing after 2m47s
CI / Unit & Component Tests (pull_request) Failing after 2m29s
CI / Backend Unit Tests (pull_request) Failing after 2m46s
feat(frontend): invite-based registration UI
- Add /register route with invite code prefill, password show/hide
- Add /login?registered=1 success banner
- Add /admin/invites page: list, create, revoke, copy link
- Add Einladungen nav section to admin sidebar (ADMIN_USER perm)
- Add invite error codes to errors.ts
- Add 48 i18n keys across de/en/es
- Update hooks.server.ts to allow public access to invite/register API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:01:19 +02:00

89 lines
2.8 KiB
TypeScript

/**
* Layout shell tests — we test EntityNav.svelte directly since the layout
* itself is a thin shell that just composes EntityNav and renders children.
*/
import { afterEach, describe, it, expect, vi } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import EntityNav from './EntityNav.svelte';
vi.mock('$app/state', () => ({
page: { url: { pathname: '/admin/users' } }
}));
afterEach(cleanup);
const fullPerms = {
userCount: 4,
groupCount: 3,
tagCount: 7,
inviteCount: 2,
canManageUsers: true,
canManageTags: true,
canManagePermissions: true,
canRunMaintenance: true
};
describe('admin EntityNav — links', () => {
it('renders users nav link pointing to /admin/users', async () => {
render(EntityNav, fullPerms);
await expect
.element(page.getByRole('link', { name: /benutzer/i }))
.toHaveAttribute('href', '/admin/users');
});
it('renders groups nav link pointing to /admin/groups', async () => {
render(EntityNav, fullPerms);
await expect
.element(page.getByRole('link', { name: /gruppen/i }))
.toHaveAttribute('href', '/admin/groups');
});
it('renders tags nav link pointing to /admin/tags', async () => {
render(EntityNav, fullPerms);
await expect
.element(page.getByRole('link', { name: /schlagworte/i }))
.toHaveAttribute('href', '/admin/tags');
});
it('renders system nav link pointing to /admin/system', async () => {
render(EntityNav, fullPerms);
await expect
.element(page.getByRole('link', { name: /system/i }))
.toHaveAttribute('href', '/admin/system');
});
});
describe('admin EntityNav — permission-based rendering', () => {
it('hides users link when canManageUsers is false', async () => {
render(EntityNav, { ...fullPerms, canManageUsers: false });
await expect.element(page.getByRole('link', { name: /benutzer/i })).not.toBeInTheDocument();
});
it('hides tags link when canManageTags is false', async () => {
render(EntityNav, { ...fullPerms, canManageTags: false });
await expect.element(page.getByRole('link', { name: /schlagworte/i })).not.toBeInTheDocument();
});
it('hides system link when canRunMaintenance is false', async () => {
render(EntityNav, { ...fullPerms, canRunMaintenance: false });
await expect.element(page.getByRole('link', { name: /system/i })).not.toBeInTheDocument();
});
});
describe('admin EntityNav — active state', () => {
it('marks users link as aria-current=page when on /admin/users', async () => {
render(EntityNav, fullPerms);
await expect
.element(page.getByRole('link', { name: /benutzer/i }))
.toHaveAttribute('aria-current', 'page');
});
it('does not mark groups link as current when on /admin/users', async () => {
render(EntityNav, fullPerms);
await expect
.element(page.getByRole('link', { name: /gruppen/i }))
.not.toHaveAttribute('aria-current');
});
});