Files
hms/apps/web/src/api/health/consultations.test.ts
iven fa1dc764a3 feat(health+ai): P2 咨询联动 + AI 巡检消费 — 全链路打通
业务链路打通 5/5 断点全部完成:
- 咨询→随访:医生端新增"创建随访"按钮,从咨询会话直接创建随访任务
- 咨询→AI:医生端新增"AI 分析"按钮,对咨询上下文触发 AI 分析
- 告警→咨询:小程序告警详情页新增"在线咨询"快捷入口
- AI 巡检消费:erp-ai 新增 patrol_consumer,订阅 ai.patrol.requested 事件
- 前端联动:Web ConsultationDetail + 小程序 alerts 页面联动实现

后端:2 新 API + 2 handler + 1 service + AI event consumer
前端:Web 2 API + 1 页面改造 + 小程序 2 页面改造
测试:Web consultations.test.ts 9/9 通过
2026-05-20 17:50:49 +08:00

99 lines
3.7 KiB
TypeScript

/**
* consultations API 契约测试
*/
import { describe, it, expect, vi, beforeEach } from 'vitest'
const mockGet = vi.fn()
const mockPost = vi.fn()
const mockPut = vi.fn()
const mockDelete = vi.fn()
vi.mock('../client', () => ({
default: {
get: (...args: unknown[]) => mockGet(...args),
post: (...args: unknown[]) => mockPost(...args),
put: (...args: unknown[]) => mockPut(...args),
delete: (...args: unknown[]) => mockDelete(...args),
},
}))
import { consultationApi } from './consultations'
beforeEach(() => {
vi.clearAllMocks()
})
describe('consultationApi', () => {
const fakeRes = { data: { success: true, data: {} } }
it('listSessions 应调用 GET /health/consultation-sessions 并传递查询参数', async () => {
mockGet.mockResolvedValue(fakeRes)
await consultationApi.listSessions({ page: 1, page_size: 20, status: 'active', patient_id: 'p-001' })
expect(mockGet).toHaveBeenCalledWith('/health/consultation-sessions', {
params: { page: 1, page_size: 20, status: 'active', patient_id: 'p-001' },
})
})
it('createSession 应调用 POST /health/consultation-sessions', async () => {
mockPost.mockResolvedValue(fakeRes)
const req = { patient_id: 'p-001', doctor_id: 'd-001', consultation_type: 'online' }
await consultationApi.createSession(req)
expect(mockPost).toHaveBeenCalledWith('/health/consultation-sessions', req)
})
it('getSession 应调用 GET /health/consultation-sessions/:id', async () => {
mockGet.mockResolvedValue(fakeRes)
await consultationApi.getSession('sess-001')
expect(mockGet).toHaveBeenCalledWith('/health/consultation-sessions/sess-001')
})
it('closeSession 应调用 PUT /health/consultation-sessions/:id/close', async () => {
mockPut.mockResolvedValue(fakeRes)
await consultationApi.closeSession('sess-001', { version: 1 })
expect(mockPut).toHaveBeenCalledWith('/health/consultation-sessions/sess-001/close', { version: 1 })
})
it('listMessages 应调用 GET /health/consultation-sessions/:id/messages 并传递分页参数', async () => {
mockGet.mockResolvedValue(fakeRes)
await consultationApi.listMessages('sess-001', { page: 2, page_size: 50, after_id: 'msg-100' })
expect(mockGet).toHaveBeenCalledWith('/health/consultation-sessions/sess-001/messages', {
params: { page: 2, page_size: 50, after_id: 'msg-100' },
})
})
it('createMessage 应调用 POST /health/consultation-messages', async () => {
mockPost.mockResolvedValue(fakeRes)
const req = { session_id: 'sess-001', content_type: 'text', content: '你好' }
await consultationApi.createMessage(req)
expect(mockPost).toHaveBeenCalledWith('/health/consultation-messages', req)
})
it('createFollowUpFromSession 应调用 POST /health/consultation-sessions/:id/follow-up', async () => {
mockPost.mockResolvedValue(fakeRes)
const req = { follow_up_type: 'phone', planned_date: '2026-06-01' }
await consultationApi.createFollowUpFromSession('sess-001', req)
expect(mockPost).toHaveBeenCalledWith('/health/consultation-sessions/sess-001/follow-up', req)
})
it('triggerAiAnalysisFromSession 应调用 POST /health/consultation-sessions/:id/ai-analysis', async () => {
mockPost.mockResolvedValue(fakeRes)
await consultationApi.triggerAiAnalysisFromSession('sess-001')
expect(mockPost).toHaveBeenCalledWith('/health/consultation-sessions/sess-001/ai-analysis', {})
})
it('triggerAiAnalysisFromSession 传入 analysis_type 时应携带参数', async () => {
mockPost.mockResolvedValue(fakeRes)
await consultationApi.triggerAiAnalysisFromSession('sess-001', { analysis_type: 'trend' })
expect(mockPost).toHaveBeenCalledWith('/health/consultation-sessions/sess-001/ai-analysis', { analysis_type: 'trend' })
})
})