Files
familienarchiv/frontend/src/routes/admin/users/new/page.svelte.spec.ts
Marcel 9e7861fa03 feat(geschichten): frontend foundation — canBlogWrite, sanitize util, nav, i18n
- Derives canBlogWrite in +layout.server.ts the same way as canAnnotate.
- Adds Geschichten link to AppNav (desktop + mobile, between Stammbaum and Admin).
- Adds error_geschichte_not_found mapping to errors.ts and translation keys
  for the Geschichten index, detail, editor, and confirmation copy in
  de/en/es.
- Adds isomorphic-dompurify-backed safeHtml() helper with allow-list
  matching the backend OWASP policy (p/br/strong/em/h2/h3/ul/ol/li),
  plus Vitest spec.
- Updates legacy spec test data so the new required canBlogWrite layout
  prop type-checks.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 17:43:29 +02:00

69 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { afterEach, describe, expect, it, vi } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import Page from './+page.svelte';
vi.mock('$app/forms', () => ({ enhance: () => () => {} }));
const groups = [
{ id: 'g1', name: 'Editoren', permissions: ['WRITE_ALL'] },
{ id: 'g2', name: 'Admins', permissions: ['ADMIN'] }
];
const baseData = {
user: undefined,
canWrite: true,
canAnnotate: false,
canBlogWrite: false,
groups
};
afterEach(cleanup);
// ─── Rendering ────────────────────────────────────────────────────────────────
describe('Admin new user page rendering', () => {
it('renders the page heading', async () => {
render(Page, { data: baseData, form: null });
await expect.element(page.getByText(/Neuen Benutzer anlegen/i)).toBeInTheDocument();
});
it('renders the email input', async () => {
render(Page, { data: baseData, form: null });
const input = document.querySelector<HTMLInputElement>('input[name="email"]');
expect(input).not.toBeNull();
});
it('renders group checkboxes for each available group', async () => {
render(Page, { data: baseData, form: null });
await expect.element(page.getByText('Editoren')).toBeInTheDocument();
await expect.element(page.getByText('Admins')).toBeInTheDocument();
});
it('cancel link points to /admin/users', async () => {
render(Page, { data: baseData, form: null });
await expect
.element(page.getByRole('link', { name: /Abbrechen/i }))
.toHaveAttribute('href', '/admin/users');
});
it('renders the create button', async () => {
render(Page, { data: baseData, form: null });
await expect.element(page.getByRole('button', { name: /Erstellen/i })).toBeInTheDocument();
});
});
// ─── Error display ────────────────────────────────────────────────────────────
describe('Admin new user page error display', () => {
it('shows the error message when form has an error', async () => {
render(Page, { data: baseData, form: { error: 'Ein Fehler ist aufgetreten.' } });
await expect.element(page.getByText('Ein Fehler ist aufgetreten.')).toBeInTheDocument();
});
it('does not show error section when form is null', async () => {
render(Page, { data: baseData, form: null });
await expect.element(page.getByText('Ein Fehler ist aufgetreten.')).not.toBeInTheDocument();
});
});