diff --git a/apps/web/src/test/mocks/handlers.ts b/apps/web/src/test/mocks/handlers.ts index 11a8580..1ba3568 100644 --- a/apps/web/src/test/mocks/handlers.ts +++ b/apps/web/src/test/mocks/handlers.ts @@ -1,4 +1,10 @@ import { http, HttpResponse } from 'msw'; +import { + patientHandlers, + alertHandlers, + appointmentHandlers, + doctorHandlers, +} from './healthHandlers'; const TOKEN_EXPIRES = 3600; @@ -27,4 +33,10 @@ export const authHandlers = [ ), ]; -export const handlers = [...authHandlers]; +export const handlers = [ + ...authHandlers, + ...patientHandlers, + ...alertHandlers, + ...appointmentHandlers, + ...doctorHandlers, +]; diff --git a/apps/web/src/test/mocks/healthHandlers.ts b/apps/web/src/test/mocks/healthHandlers.ts new file mode 100644 index 0000000..d3f8c58 --- /dev/null +++ b/apps/web/src/test/mocks/healthHandlers.ts @@ -0,0 +1,128 @@ +import { http, HttpResponse, delay } from 'msw'; + +const DEFAULT_PAGE_SIZE = 20; + +function paginatedResponse(items: T[], total: number, page: number, pageSize = DEFAULT_PAGE_SIZE) { + return HttpResponse.json({ + success: true, + data: { + data: items, + total, + page, + page_size: pageSize, + total_pages: Math.ceil(total / pageSize), + }, + }); +} + +// --- 患者列表 --- +const mockPatients = Array.from({ length: 25 }, (_, i) => ({ + id: `patient-${i + 1}`, + name: `测试患者${i + 1}`, + gender: i % 2 === 0 ? 'male' : 'female', + birth_date: '1990-01-15', + blood_type: 'A', + status: 'active', + verification_status: i < 20 ? 'verified' : 'pending', + source: 'manual', + created_at: '2026-04-01T10:00:00Z', + updated_at: '2026-04-01T10:00:00Z', + version: 1, +})); + +export const patientHandlers = [ + http.get('/api/v1/health/patients', async ({ request }) => { + await delay(50); + const url = new URL(request.url); + const page = Number(url.searchParams.get('page') || 1); + const pageSize = Number(url.searchParams.get('page_size') || DEFAULT_PAGE_SIZE); + const start = (page - 1) * pageSize; + const items = mockPatients.slice(start, start + pageSize); + return paginatedResponse(items, mockPatients.length, page, pageSize); + }), + + http.get('/api/v1/health/patients/:id', async ({ params }) => { + await delay(50); + const patient = mockPatients.find((p) => p.id === params.id); + if (!patient) return HttpResponse.json({ success: false, error: 'Not found' }, { status: 404 }); + return HttpResponse.json({ success: true, data: { ...patient, notes: '', allergy_history: '', medical_history_summary: '' } }); + }), +]; + +// --- 告警列表 --- +const mockAlerts = Array.from({ length: 12 }, (_, i) => ({ + id: `alert-${i + 1}`, + patient_id: `patient-${i + 1}`, + patient_name: `测试患者${i + 1}`, + alert_type: i % 3 === 0 ? 'vital_sign' : i % 3 === 1 ? 'lab_result' : 'overdue_followup', + severity: (['low', 'medium', 'high'] as const)[i % 3], + status: i < 8 ? 'active' : 'resolved', + message: `告警消息 ${i + 1}`, + created_at: '2026-04-01T10:00:00Z', + updated_at: '2026-04-01T10:00:00Z', + version: 1, +})); + +export const alertHandlers = [ + http.get('/api/v1/health/alerts', async ({ request }) => { + await delay(50); + const url = new URL(request.url); + const page = Number(url.searchParams.get('page') || 1); + const pageSize = Number(url.searchParams.get('page_size') || DEFAULT_PAGE_SIZE); + return paginatedResponse(mockAlerts.slice(0, pageSize), mockAlerts.length, page, pageSize); + }), +]; + +// --- 预约列表 --- +const mockAppointments = Array.from({ length: 15 }, (_, i) => ({ + id: `appt-${i + 1}`, + patient_id: `patient-${i + 1}`, + patient_name: `测试患者${i + 1}`, + doctor_id: `doctor-${(i % 5) + 1}`, + doctor_name: `测试医生${(i % 5) + 1}`, + appointment_date: '2026-05-10', + start_time: '09:00', + end_time: '09:30', + status: (['pending', 'confirmed', 'completed', 'cancelled'] as const)[i % 4], + type: 'follow_up', + notes: '', + created_at: '2026-04-01T10:00:00Z', + updated_at: '2026-04-01T10:00:00Z', + version: 1, +})); + +export const appointmentHandlers = [ + http.get('/api/v1/health/appointments', async ({ request }) => { + await delay(50); + const url = new URL(request.url); + const page = Number(url.searchParams.get('page') || 1); + const pageSize = Number(url.searchParams.get('page_size') || DEFAULT_PAGE_SIZE); + return paginatedResponse(mockAppointments.slice(0, pageSize), mockAppointments.length, page, pageSize); + }), +]; + +// --- 医生列表 --- +const mockDoctors = Array.from({ length: 8 }, (_, i) => ({ + id: `doctor-${i + 1}`, + user_id: `user-doc-${i + 1}`, + name: `测试医生${i + 1}`, + department: '内科', + title: '主治医师', + specialization: '心血管内科', + phone: `1380000${String(i + 1).padStart(4, '0')}`, + email: `doctor${i + 1}@test.com`, + status: 'online', + created_at: '2026-04-01T10:00:00Z', + updated_at: '2026-04-01T10:00:00Z', + version: 1, +})); + +export const doctorHandlers = [ + http.get('/api/v1/health/doctors', async ({ request }) => { + await delay(50); + const url = new URL(request.url); + const page = Number(url.searchParams.get('page') || 1); + const pageSize = Number(url.searchParams.get('page_size') || DEFAULT_PAGE_SIZE); + return paginatedResponse(mockDoctors.slice(0, pageSize), mockDoctors.length, page, pageSize); + }), +];