Files
familienarchiv/frontend/src/routes/admin/groups/[id]/page.server.spec.ts
Marcel 567612761d refactor: move lib-root files to lib/shared/ and finalize domain structure
- Move api.server.ts, errors.ts, types.ts, utils.ts, relativeTime.ts to lib/shared/
- Move person relationship components to lib/person/relationship/
- Move Stammbaum components to lib/person/genealogy/
- Move HelpPopover to lib/shared/primitives/
- Update all import paths across routes, specs, and lib files
- Update vi.mock() paths in server-project test files
- Remove now-empty legacy directories (components/, hooks/, server/, etc.)
- Update vite.config.ts coverage include paths for new structure
- Update frontend/CLAUDE.md to reflect domain-based lib/ layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:53:31 +02:00

88 lines
2.5 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { actions } from './+page.server';
const mockApi = {
PATCH: vi.fn(),
DELETE: vi.fn()
};
vi.mock('$lib/shared/api.server', () => ({
createApiClient: () => mockApi
}));
beforeEach(() => vi.clearAllMocks());
// ─── update action ─────────────────────────────────────────────────────────────
describe('groups/[id] — update action', () => {
it('returns success: true when API responds ok', async () => {
mockApi.PATCH.mockResolvedValue({ response: { ok: true }, data: {} });
const formData = new FormData();
formData.set('name', 'Editors');
formData.append('permissions', 'WRITE_ALL');
const result = await actions.update({
params: { id: 'g1' },
request: { formData: async () => formData },
fetch
} as never);
expect(result).toEqual({ success: true });
});
it('returns fail with error message when API responds not ok', async () => {
mockApi.PATCH.mockResolvedValue({
response: { ok: false, status: 409 },
error: { code: 'GROUP_NOT_FOUND' }
});
const formData = new FormData();
formData.set('name', 'Editors');
const result = await actions.update({
params: { id: 'g1' },
request: { formData: async () => formData },
fetch
} as never);
expect((result as { status: number }).status).toBe(409);
});
});
// ─── delete action ─────────────────────────────────────────────────────────────
describe('groups/[id] — delete action', () => {
it('redirects to /admin/groups on successful delete', async () => {
mockApi.DELETE.mockResolvedValue({ response: { ok: true } });
let redirectUrl: string | null = null;
try {
await actions.delete({
params: { id: 'g1' },
fetch
} as never);
} catch (e: unknown) {
// SvelteKit redirect throws a Response-like object
const r = e as { location?: string; status?: number };
redirectUrl = r.location ?? null;
}
expect(redirectUrl).toBe('/admin/groups');
});
it('returns fail with error message when delete API responds not ok', async () => {
mockApi.DELETE.mockResolvedValue({
response: { ok: false, status: 403 },
error: { code: 'FORBIDDEN' }
});
const result = await actions.delete({
params: { id: 'g1' },
fetch
} as never);
expect((result as { status: number }).status).toBe(403);
});
});