Continuous Integration / config (pull_request) Successful in 11s
Continuous Integration / changes (pull_request) Successful in 21s
Continuous Integration / backend-build (pull_request) Skipped
Continuous Integration / backend-test (pull_request) Skipped
Continuous Integration / vulnerability-scan (pull_request) Skipped
Continuous Integration / frontend-prepare (pull_request) Successful in 1m37s
Continuous Integration / frontend-build (pull_request) Successful in 2m12s
Continuous Integration / frontend-test (pull_request) Successful in 4m42s
Continuous Integration / frontend-lint (pull_request) Successful in 2m2s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m51s
Continuous Integration / deploy-test (pull_request) Skipped
Groups auth, setup, invitation, profile, users, cms, availability and system code (services/hooks, components, schemas, mocks, pages) under src/features/<name> instead of splitting by technical layer (api/, components/, lib/schemas/, mocks/, pages/). Renames the old connection-oriented `api` layer to `services` per feature, and splits the monolithic api/types.ts into per-feature types.ts files (with ProblemDetails/ApiResult merged into lib/api-client.ts as shared infra). Layout-agnostic code (ui primitives, app shell, i18n, test utils, lib) stays at the top level. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
import { act, renderHook } from '@testing-library/react';
|
|
import { http, HttpResponse } from 'msw';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { server } from '@/mocks/server';
|
|
import { API_BASE } from '@/features/auth/mocks/fixtures';
|
|
import { useSetup } from '@/features/setup/services/useSetup';
|
|
|
|
const validSetupData = {
|
|
name: 'Test Owner',
|
|
email: 'owner@example.com',
|
|
password: 'Password1!',
|
|
language: 'nl' as const,
|
|
};
|
|
|
|
describe('useSetup', () => {
|
|
it('starts with isPending=false and no error', () => {
|
|
const { result } = renderHook(() => useSetup());
|
|
|
|
expect(result.current.isPending).toBe(false);
|
|
expect(result.current.error).toBeNull();
|
|
});
|
|
|
|
it('returns setup response on success', async () => {
|
|
const { result } = renderHook(() => useSetup());
|
|
|
|
let response: Awaited<ReturnType<typeof result.current.mutateAsync>> | undefined;
|
|
await act(async () => {
|
|
response = await result.current.mutateAsync(validSetupData);
|
|
});
|
|
|
|
expect(response?.message).toBe('System initialized');
|
|
expect(response?.user.role).toBe('Owner');
|
|
expect(result.current.isPending).toBe(false);
|
|
expect(result.current.error).toBeNull();
|
|
});
|
|
|
|
it('sets error and rethrows when API fails', async () => {
|
|
server.use(
|
|
http.post(`${API_BASE}/api/v1/Setup/owner`, () =>
|
|
HttpResponse.json(
|
|
{ title: 'Conflict', detail: 'Already initialized', status: 409 },
|
|
{ status: 409 },
|
|
),
|
|
),
|
|
);
|
|
|
|
const { result } = renderHook(() => useSetup());
|
|
|
|
let thrown: Error | undefined;
|
|
await act(async () => {
|
|
try {
|
|
await result.current.mutateAsync(validSetupData);
|
|
} catch (err) {
|
|
thrown = err as Error;
|
|
}
|
|
});
|
|
|
|
expect(thrown).toBeDefined();
|
|
expect(result.current.error).not.toBeNull();
|
|
expect(result.current.isPending).toBe(false);
|
|
});
|
|
|
|
it('resets error state on subsequent successful call', async () => {
|
|
server.use(
|
|
http.post(`${API_BASE}/api/v1/Setup/owner`, () =>
|
|
HttpResponse.json({ title: 'Error', status: 500 }, { status: 500 }),
|
|
),
|
|
);
|
|
|
|
const { result } = renderHook(() => useSetup());
|
|
|
|
await act(async () => {
|
|
try {
|
|
await result.current.mutateAsync(validSetupData);
|
|
} catch {
|
|
// expected
|
|
}
|
|
});
|
|
|
|
expect(result.current.error).not.toBeNull();
|
|
|
|
// Restore success handler and retry
|
|
server.resetHandlers();
|
|
|
|
await act(async () => {
|
|
await result.current.mutateAsync(validSetupData);
|
|
});
|
|
|
|
expect(result.current.error).toBeNull();
|
|
});
|
|
});
|