mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 18:23:42 +00:00
test: add hook tests for useDashboard and useCases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
159ac0a26c
commit
6ede0d93ed
2 changed files with 342 additions and 0 deletions
291
frontend/src/hooks/__tests__/useCases.test.ts
Normal file
291
frontend/src/hooks/__tests__/useCases.test.ts
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import { waitFor, act } from '@testing-library/react'
|
||||
import { http, HttpResponse } from 'msw'
|
||||
import { server } from '@/test/mocks/server'
|
||||
import { renderHookWithProviders } from '@/test/utils'
|
||||
import {
|
||||
mockCase,
|
||||
mockCaseListResponse,
|
||||
mockEmptyCaseList,
|
||||
} from '@/test/mocks/data'
|
||||
import {
|
||||
useCases,
|
||||
usePendingIcdCases,
|
||||
useCaseUpdate,
|
||||
useKvnrUpdate,
|
||||
useIcdUpdate,
|
||||
} from '@/hooks/useCases'
|
||||
import type { CaseFilters } from '@/hooks/useCases'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// useCases
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('useCases', () => {
|
||||
const defaultFilters: CaseFilters = { page: 1, per_page: 20 }
|
||||
|
||||
it('fetches cases with default filters (success)', async () => {
|
||||
const { result } = renderHookWithProviders(() => useCases(defaultFilters))
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(result.current.data).toEqual(mockCaseListResponse)
|
||||
expect(result.current.data!.items).toHaveLength(2)
|
||||
expect(result.current.data!.total).toBe(2)
|
||||
})
|
||||
|
||||
it('passes filter params to the API (search, jahr, fallgruppe, has_icd)', async () => {
|
||||
const capturedParams: Record<string, string | null> = {}
|
||||
|
||||
server.use(
|
||||
http.get('/api/cases/', ({ request }) => {
|
||||
const url = new URL(request.url)
|
||||
capturedParams.search = url.searchParams.get('search')
|
||||
capturedParams.jahr = url.searchParams.get('jahr')
|
||||
capturedParams.fallgruppe = url.searchParams.get('fallgruppe')
|
||||
capturedParams.has_icd = url.searchParams.get('has_icd')
|
||||
capturedParams.page = url.searchParams.get('page')
|
||||
capturedParams.per_page = url.searchParams.get('per_page')
|
||||
return HttpResponse.json(mockCaseListResponse)
|
||||
}),
|
||||
)
|
||||
|
||||
const filters: CaseFilters = {
|
||||
page: 2,
|
||||
per_page: 10,
|
||||
search: 'Meier',
|
||||
jahr: 2026,
|
||||
fallgruppe: 'onko',
|
||||
has_icd: 'true',
|
||||
}
|
||||
|
||||
const { result } = renderHookWithProviders(() => useCases(filters))
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(capturedParams.search).toBe('Meier')
|
||||
expect(capturedParams.jahr).toBe('2026')
|
||||
expect(capturedParams.fallgruppe).toBe('onko')
|
||||
expect(capturedParams.has_icd).toBe('true')
|
||||
expect(capturedParams.page).toBe('2')
|
||||
expect(capturedParams.per_page).toBe('10')
|
||||
})
|
||||
|
||||
it('does not send optional params when they are undefined', async () => {
|
||||
const capturedParams: Record<string, string | null> = {}
|
||||
|
||||
server.use(
|
||||
http.get('/api/cases/', ({ request }) => {
|
||||
const url = new URL(request.url)
|
||||
capturedParams.search = url.searchParams.get('search')
|
||||
capturedParams.jahr = url.searchParams.get('jahr')
|
||||
capturedParams.fallgruppe = url.searchParams.get('fallgruppe')
|
||||
capturedParams.has_icd = url.searchParams.get('has_icd')
|
||||
return HttpResponse.json(mockCaseListResponse)
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useCases(defaultFilters))
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(capturedParams.search).toBeNull()
|
||||
expect(capturedParams.jahr).toBeNull()
|
||||
expect(capturedParams.fallgruppe).toBeNull()
|
||||
expect(capturedParams.has_icd).toBeNull()
|
||||
})
|
||||
|
||||
it('respects enabled: false (fetchStatus === "idle")', () => {
|
||||
const { result } = renderHookWithProviders(() =>
|
||||
useCases(defaultFilters, { enabled: false }),
|
||||
)
|
||||
|
||||
expect(result.current.fetchStatus).toBe('idle')
|
||||
expect(result.current.data).toBeUndefined()
|
||||
})
|
||||
|
||||
it('handles empty response', async () => {
|
||||
server.use(
|
||||
http.get('/api/cases/', () => {
|
||||
return HttpResponse.json(mockEmptyCaseList)
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useCases(defaultFilters))
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(result.current.data!.items).toHaveLength(0)
|
||||
expect(result.current.data!.total).toBe(0)
|
||||
})
|
||||
|
||||
it('handles server error (500)', async () => {
|
||||
server.use(
|
||||
http.get('/api/cases/', () => {
|
||||
return new HttpResponse(null, { status: 500 })
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useCases(defaultFilters))
|
||||
|
||||
await waitFor(() => expect(result.current.isError).toBe(true))
|
||||
|
||||
expect(result.current.data).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// usePendingIcdCases
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('usePendingIcdCases', () => {
|
||||
it('fetches pending ICD cases (success)', async () => {
|
||||
const { result } = renderHookWithProviders(() => usePendingIcdCases(1, 20))
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(result.current.data!.items).toHaveLength(1)
|
||||
expect(result.current.data!.items[0].icd).toBeNull()
|
||||
expect(result.current.data!.total).toBe(1)
|
||||
})
|
||||
|
||||
it('respects enabled: false', () => {
|
||||
const { result } = renderHookWithProviders(() =>
|
||||
usePendingIcdCases(1, 20, { enabled: false }),
|
||||
)
|
||||
|
||||
expect(result.current.fetchStatus).toBe('idle')
|
||||
expect(result.current.data).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// useCaseUpdate
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('useCaseUpdate', () => {
|
||||
it('updates a case and returns the result', async () => {
|
||||
const { result } = renderHookWithProviders(() => useCaseUpdate())
|
||||
|
||||
let updated: unknown
|
||||
await act(async () => {
|
||||
updated = await result.current.mutateAsync({
|
||||
id: 1,
|
||||
data: { kommentar: 'Neuer Kommentar' },
|
||||
})
|
||||
})
|
||||
|
||||
expect((updated as { id: number }).id).toBe(1)
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
})
|
||||
|
||||
it('handles error (403 Forbidden)', async () => {
|
||||
server.use(
|
||||
http.put('/api/cases/:id', () => {
|
||||
return HttpResponse.json(
|
||||
{ detail: 'Forbidden' },
|
||||
{ status: 403 },
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useCaseUpdate())
|
||||
|
||||
await act(async () => {
|
||||
try {
|
||||
await result.current.mutateAsync({ id: 1, data: { kommentar: 'x' } })
|
||||
} catch {
|
||||
// expected
|
||||
}
|
||||
})
|
||||
|
||||
await waitFor(() => expect(result.current.isError).toBe(true))
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// useKvnrUpdate
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('useKvnrUpdate', () => {
|
||||
it('updates KVNR and returns the updated case', async () => {
|
||||
const { result } = renderHookWithProviders(() => useKvnrUpdate())
|
||||
|
||||
let updated: unknown
|
||||
await act(async () => {
|
||||
updated = await result.current.mutateAsync({
|
||||
id: 1,
|
||||
kvnr: 'C111222333',
|
||||
})
|
||||
})
|
||||
|
||||
expect((updated as { kvnr: string }).kvnr).toBe('C111222333')
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
})
|
||||
|
||||
it('handles null KVNR', async () => {
|
||||
server.use(
|
||||
http.put('/api/cases/:id/kvnr', ({ params }) => {
|
||||
const id = Number(params.id)
|
||||
return HttpResponse.json({ ...mockCase, id, kvnr: null })
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useKvnrUpdate())
|
||||
|
||||
let updated: unknown
|
||||
await act(async () => {
|
||||
updated = await result.current.mutateAsync({
|
||||
id: 1,
|
||||
kvnr: null,
|
||||
})
|
||||
})
|
||||
|
||||
expect((updated as { kvnr: string | null }).kvnr).toBeNull()
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// useIcdUpdate
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('useIcdUpdate', () => {
|
||||
it('updates ICD and returns the updated case', async () => {
|
||||
const { result } = renderHookWithProviders(() => useIcdUpdate())
|
||||
|
||||
let updated: unknown
|
||||
await act(async () => {
|
||||
updated = await result.current.mutateAsync({
|
||||
id: 1,
|
||||
icd: 'C61',
|
||||
})
|
||||
})
|
||||
|
||||
expect((updated as { icd: string }).icd).toBe('C61')
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
})
|
||||
|
||||
it('handles error (422 Unprocessable Entity)', async () => {
|
||||
server.use(
|
||||
http.put('/api/cases/:id/icd', () => {
|
||||
return HttpResponse.json(
|
||||
{ detail: 'Invalid ICD code' },
|
||||
{ status: 422 },
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useIcdUpdate())
|
||||
|
||||
await act(async () => {
|
||||
try {
|
||||
await result.current.mutateAsync({ id: 1, icd: 'INVALID' })
|
||||
} catch {
|
||||
// expected
|
||||
}
|
||||
})
|
||||
|
||||
await waitFor(() => expect(result.current.isError).toBe(true))
|
||||
})
|
||||
})
|
||||
51
frontend/src/hooks/__tests__/useDashboard.test.ts
Normal file
51
frontend/src/hooks/__tests__/useDashboard.test.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { describe, it, expect } from 'vitest'
|
||||
import { waitFor } from '@testing-library/react'
|
||||
import { http, HttpResponse } from 'msw'
|
||||
import { server } from '@/test/mocks/server'
|
||||
import { renderHookWithProviders } from '@/test/utils'
|
||||
import { mockDashboardResponse } from '@/test/mocks/data'
|
||||
import { useDashboard } from '@/hooks/useDashboard'
|
||||
|
||||
describe('useDashboard', () => {
|
||||
it('fetches dashboard data for the given year', async () => {
|
||||
const { result } = renderHookWithProviders(() => useDashboard(2026))
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(result.current.data).toEqual(mockDashboardResponse)
|
||||
expect(result.current.data!.kpis.total_cases).toBe(142)
|
||||
expect(result.current.data!.weekly).toHaveLength(6)
|
||||
})
|
||||
|
||||
it('includes the year parameter in the API call', async () => {
|
||||
let capturedJahr: string | null = null
|
||||
|
||||
server.use(
|
||||
http.get('/api/reports/dashboard', ({ request }) => {
|
||||
const url = new URL(request.url)
|
||||
capturedJahr = url.searchParams.get('jahr')
|
||||
return HttpResponse.json(mockDashboardResponse)
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useDashboard(2025))
|
||||
|
||||
await waitFor(() => expect(result.current.isSuccess).toBe(true))
|
||||
|
||||
expect(capturedJahr).toBe('2025')
|
||||
})
|
||||
|
||||
it('handles server error (500)', async () => {
|
||||
server.use(
|
||||
http.get('/api/reports/dashboard', () => {
|
||||
return new HttpResponse(null, { status: 500 })
|
||||
}),
|
||||
)
|
||||
|
||||
const { result } = renderHookWithProviders(() => useDashboard(2026))
|
||||
|
||||
await waitFor(() => expect(result.current.isError).toBe(true))
|
||||
|
||||
expect(result.current.data).toBeUndefined()
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue