新增 3 个测试文件(+23 个测试用例),总计 9 文件 75 测试: - request.test.ts: HTTP 方法、查询参数构建、缓存、错误处理 - health.test.ts: 体征录入字段映射、日常监测、阈值查找 - consultation.test.ts: 咨询会话/消息 CRUD、已读标记 - 添加 vitest setup.ts mock @tarojs/taro 和 @tarojs/runtime - vitest.config.ts 增加 setupFiles 配置 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
181 lines
5.4 KiB
TypeScript
181 lines
5.4 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
import '../helpers/mock-api';
|
|
|
|
import { api } from '@/services/request';
|
|
import {
|
|
inputVitalSign,
|
|
getTodaySummary,
|
|
getTrend,
|
|
listDailyMonitoring,
|
|
createDailyMonitoring,
|
|
findThreshold,
|
|
DEFAULT_THRESHOLDS,
|
|
} from '@/services/health';
|
|
|
|
describe('health service', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('getTodaySummary', () => {
|
|
it('calls api.get with correct path', async () => {
|
|
const mock = { blood_pressure: { systolic: 120, diastolic: 80, status: 'normal' } };
|
|
vi.mocked(api.get).mockResolvedValueOnce(mock);
|
|
|
|
const result = await getTodaySummary();
|
|
|
|
expect(api.get).toHaveBeenCalledWith('/health/vital-signs/today', {});
|
|
expect(result).toEqual(mock);
|
|
});
|
|
|
|
it('passes patient_id when provided', async () => {
|
|
vi.mocked(api.get).mockResolvedValueOnce({});
|
|
|
|
await getTodaySummary('p-123');
|
|
|
|
expect(api.get).toHaveBeenCalledWith('/health/vital-signs/today', { patient_id: 'p-123' });
|
|
});
|
|
});
|
|
|
|
describe('inputVitalSign', () => {
|
|
it('maps blood_pressure to morning fields', async () => {
|
|
vi.mocked(api.post).mockResolvedValueOnce({});
|
|
|
|
await inputVitalSign('p-1', {
|
|
indicator_type: 'blood_pressure',
|
|
value: 0,
|
|
extra: { systolic: 130, diastolic: 85 },
|
|
});
|
|
|
|
expect(api.post).toHaveBeenCalledWith(
|
|
'/health/patients/p-1/vital-signs',
|
|
expect.objectContaining({
|
|
systolic_bp_morning: 130,
|
|
diastolic_bp_morning: 85,
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('maps blood_pressure_evening to evening fields', async () => {
|
|
vi.mocked(api.post).mockResolvedValueOnce({});
|
|
|
|
await inputVitalSign('p-1', {
|
|
indicator_type: 'blood_pressure_evening',
|
|
value: 0,
|
|
extra: { systolic: 125, diastolic: 80 },
|
|
});
|
|
|
|
expect(api.post).toHaveBeenCalledWith(
|
|
'/health/patients/p-1/vital-signs',
|
|
expect.objectContaining({
|
|
systolic_bp_evening: 125,
|
|
diastolic_bp_evening: 80,
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('maps heart_rate and rounds value', async () => {
|
|
vi.mocked(api.post).mockResolvedValueOnce({});
|
|
|
|
await inputVitalSign('p-1', { indicator_type: 'heart_rate', value: 72.5 });
|
|
|
|
expect(api.post).toHaveBeenCalledWith(
|
|
'/health/patients/p-1/vital-signs',
|
|
expect.objectContaining({ heart_rate: 73 }),
|
|
);
|
|
});
|
|
|
|
it('maps spo2 and rounds value', async () => {
|
|
vi.mocked(api.post).mockResolvedValueOnce({});
|
|
|
|
await inputVitalSign('p-1', { indicator_type: 'spo2', value: 98.7 });
|
|
|
|
expect(api.post).toHaveBeenCalledWith(
|
|
'/health/patients/p-1/vital-signs',
|
|
expect.objectContaining({ spo2: 99 }),
|
|
);
|
|
});
|
|
|
|
it('includes notes when provided', async () => {
|
|
vi.mocked(api.post).mockResolvedValueOnce({});
|
|
|
|
await inputVitalSign('p-1', { indicator_type: 'weight', value: 65, note: '饭后' });
|
|
|
|
expect(api.post).toHaveBeenCalledWith(
|
|
'/health/patients/p-1/vital-signs',
|
|
expect.objectContaining({ weight: 65, notes: '饭后' }),
|
|
);
|
|
});
|
|
|
|
it('includes record_date as today', async () => {
|
|
vi.mocked(api.post).mockResolvedValueOnce({});
|
|
|
|
await inputVitalSign('p-1', { indicator_type: 'weight', value: 65 });
|
|
|
|
const callData = vi.mocked(api.post).mock.calls[0][1] as Record<string, unknown>;
|
|
expect(callData.record_date).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
});
|
|
});
|
|
|
|
describe('getTrend', () => {
|
|
it('calls api.get with indicator and range', async () => {
|
|
vi.mocked(api.get).mockResolvedValueOnce({ indicator: 'systolic_bp', data_points: [] });
|
|
|
|
await getTrend('systolic_bp', '7d');
|
|
|
|
expect(api.get).toHaveBeenCalledWith('/health/vital-signs/trend', {
|
|
indicator: 'systolic_bp',
|
|
range: '7d',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('listDailyMonitoring', () => {
|
|
it('calls api.get with patient id and pagination', async () => {
|
|
vi.mocked(api.get).mockResolvedValueOnce({ data: [], total: 0 });
|
|
|
|
await listDailyMonitoring('p-1', { page: 2, page_size: 10 });
|
|
|
|
expect(api.get).toHaveBeenCalledWith(
|
|
'/health/patients/p-1/daily-monitoring',
|
|
{ page: 2, page_size: 10 },
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('createDailyMonitoring', () => {
|
|
it('calls api.post with monitoring data', async () => {
|
|
const input = {
|
|
patient_id: 'p-1',
|
|
record_date: '2026-05-13',
|
|
morning_bp_systolic: 130,
|
|
morning_bp_diastolic: 85,
|
|
};
|
|
vi.mocked(api.post).mockResolvedValueOnce({ id: 'dm-1', ...input });
|
|
|
|
await createDailyMonitoring(input);
|
|
|
|
expect(api.post).toHaveBeenCalledWith('/health/daily-monitoring', input);
|
|
});
|
|
});
|
|
|
|
describe('findThreshold', () => {
|
|
it('finds matching active threshold', () => {
|
|
const result = findThreshold(DEFAULT_THRESHOLDS, 'systolic_bp', 'high', 'warning');
|
|
expect(result).toBeDefined();
|
|
expect(result!.threshold_value).toBe(140);
|
|
});
|
|
|
|
it('returns undefined for inactive threshold', () => {
|
|
const thresholds = [{ ...DEFAULT_THRESHOLDS[0], is_active: false }];
|
|
const result = findThreshold(thresholds, 'systolic_bp', 'high', 'warning');
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
it('returns undefined when no match', () => {
|
|
const result = findThreshold(DEFAULT_THRESHOLDS, 'unknown_indicator', 'high');
|
|
expect(result).toBeUndefined();
|
|
});
|
|
});
|
|
});
|