test(web): API 契约测试 — 25 个模块 244 个测试全覆盖
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

验证每个 API 模块的 URL/HTTP Method/参数序列化:
- health(14): patients/appointments/alerts/articles/consultations/
  dashboard/deviceReadings/doctors/followUp/healthData/points/
  followUpTemplates/api
- 基础模块(11): auth/users/roles/orgs/dictionaries/messages/
  plugins/pluginData/config-modules/workflow/auditLogs

前端测试总数: 140(store) + 244(api) = 384
This commit is contained in:
iven
2026-05-03 20:09:49 +08:00
parent bc6206c0df
commit 6d1a7fba98
24 changed files with 2697 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
/**
* AI 模块 API 契约测试analysis + prompts + suggestions + usage
*/
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 { analysisApi } from './analysis'
import { promptApi } from './prompts'
import { suggestionApi } from './suggestions'
import { usageApi } from './usage'
beforeEach(() => {
vi.clearAllMocks()
})
describe('analysisApi', () => {
const fakeRes = { data: { data: {} } }
it('list 应调用 GET /ai/analysis/history 并传递查询参数', async () => {
mockGet.mockResolvedValue(fakeRes)
await analysisApi.list({ patient_id: 'p-001', analysis_type: 'lab-report', page: 1, page_size: 10 })
expect(mockGet).toHaveBeenCalledWith('/ai/analysis/history', {
params: { patient_id: 'p-001', analysis_type: 'lab-report', page: 1, page_size: 10 },
})
})
it('get 应调用 GET /ai/analysis/:id', async () => {
mockGet.mockResolvedValue(fakeRes)
await analysisApi.get('ana-001')
expect(mockGet).toHaveBeenCalledWith('/ai/analysis/ana-001')
})
})
describe('promptApi', () => {
const fakeRes = { data: { data: {} } }
it('list 应调用 GET /ai/prompts 并传递查询参数', async () => {
mockGet.mockResolvedValue(fakeRes)
await promptApi.list({ category: 'analysis', page: 1, page_size: 10 })
expect(mockGet).toHaveBeenCalledWith('/ai/prompts', {
params: { category: 'analysis', page: 1, page_size: 10 },
})
})
it('create 应调用 POST /ai/prompts 并传递请求体', async () => {
mockPost.mockResolvedValue(fakeRes)
const req = { name: '化验解读', system_prompt: '你是专业医生', user_prompt_template: '解读: {report}', model_config: {}, category: 'analysis' }
await promptApi.create(req)
expect(mockPost).toHaveBeenCalledWith('/ai/prompts', req)
})
it('activate 应调用 POST /ai/prompts/:id/activate', async () => {
mockPost.mockResolvedValue(fakeRes)
await promptApi.activate('prompt-001')
expect(mockPost).toHaveBeenCalledWith('/ai/prompts/prompt-001/activate')
})
it('rollback 应调用 POST /ai/prompts/:id/rollback', async () => {
mockPost.mockResolvedValue(fakeRes)
await promptApi.rollback('prompt-001')
expect(mockPost).toHaveBeenCalledWith('/ai/prompts/prompt-001/rollback')
})
})
describe('suggestionApi', () => {
const fakeRes = { data: { data: {} } }
it('list 应调用 GET /ai/suggestions 并传递查询参数', async () => {
mockGet.mockResolvedValue(fakeRes)
await suggestionApi.list({ analysis_id: 'ana-001', status: 'pending' })
expect(mockGet).toHaveBeenCalledWith('/ai/suggestions', {
params: { analysis_id: 'ana-001', status: 'pending' },
})
})
it('approve 应调用 POST /ai/suggestions/:id/approve 并传递 action', async () => {
mockPost.mockResolvedValue(fakeRes)
await suggestionApi.approve('sug-001', 'approve')
expect(mockPost).toHaveBeenCalledWith('/ai/suggestions/sug-001/approve', { action: 'approve' })
})
it('getComparison 应调用 GET /ai/suggestions/:id/comparison', async () => {
mockGet.mockResolvedValue(fakeRes)
await suggestionApi.getComparison('sug-001')
expect(mockGet).toHaveBeenCalledWith('/ai/suggestions/sug-001/comparison')
})
})
describe('usageApi', () => {
const fakeRes = { data: { data: {} } }
it('overview 应调用 GET /ai/usage/overview', async () => {
mockGet.mockResolvedValue(fakeRes)
await usageApi.overview()
expect(mockGet).toHaveBeenCalledWith('/ai/usage/overview')
})
it('byType 应调用 GET /ai/usage/by-type', async () => {
mockGet.mockResolvedValue(fakeRes)
await usageApi.byType()
expect(mockGet).toHaveBeenCalledWith('/ai/usage/by-type')
})
})