Files
hms/apps/web/e2e/fixtures/test-data.ts
iven a491eb19a6
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
fix(web+health): E2E flow 测试全面修复 — 15/15 通过
- test-data: 接口对齐后端 DTO(VitalSigns/AlertRule/Schedule/FollowUp)
- api-client: 增强 HTTP 错误处理(parseJson 统一防护非 JSON 响应)
- auth.fixture: 每个测试获取新 token,避免共享 token 过期
- patient-detail: tab 名称修正为 '健康数据' → '体征数据'
- patient-list: DrawerForm 选择器适配(无 phone 字段、保存按钮在 extra)
- vital-signs-flow: API 录入 + 页面验证,避免复杂 DatePicker 交互
- alert-flow: 简化为规则 CRUD + 页面导航,condition_params 对齐后端格式
- follow-up-template handler: 权限码从 health.follow-up-template.* 修正为 health.follow-up.*
- playwright.config: workers=1 串行执行避免并发登录
- check-readiness: 健康端点路径修正为 /api/v1/health
2026-04-29 06:04:22 +08:00

199 lines
4.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// apps/web/e2e/fixtures/test-data.ts
export interface PatientData {
name: string;
gender?: string;
birth_date?: string;
blood_type?: string;
id_number?: string;
allergy_history?: string;
medical_history_summary?: string;
emergency_contact_name?: string;
emergency_contact_phone?: string;
source?: string;
notes?: string;
}
export interface DoctorData {
name: string;
department?: string;
title?: string;
specialty?: string;
phone?: string;
license_number?: string;
status?: string;
}
export interface VitalSignsData {
record_date: string;
systolic_bp_morning?: number;
diastolic_bp_morning?: number;
heart_rate?: number;
body_temperature?: number;
spo2?: number;
blood_sugar?: number;
weight?: number;
water_intake_ml?: number;
urine_output_ml?: number;
notes?: string;
source?: string;
}
export interface ScheduleData {
doctor_id: string;
schedule_date: string;
start_time: string;
end_time: string;
max_appointments?: number;
period_type?: string;
}
export interface AppointmentData {
patient_id: string;
doctor_id: string;
schedule_id: string;
appointment_date: string;
start_time: string;
end_time: string;
reason?: string;
}
export interface FollowUpTemplateData {
name: string;
description?: string;
follow_up_type: string;
applicable_scope?: string;
fields?: Array<{
label: string;
field_key: string;
field_type: string;
required?: boolean;
options?: string;
}>;
}
export interface FollowUpTaskData {
patient_id: string;
follow_up_type: string;
planned_date: string;
assigned_to?: string;
content_template?: string;
}
export interface AlertRuleData {
name: string;
device_type: string;
condition_type: string;
condition_params: Record<string, unknown>;
severity?: string;
description?: string;
apply_tags?: Record<string, unknown>;
notify_roles?: Array<string>;
cooldown_minutes?: number;
}
let counter = 0;
function uid(): string {
counter += 1;
return `${Date.now()}_${counter}_${Math.random().toString(36).slice(2, 6)}`;
}
export function makePatient(overrides?: Partial<PatientData>): PatientData {
const id = uid();
return {
name: `E2E患者_${id}`,
gender: 'male',
birth_date: '1990-01-15',
id_number: `110101199001${String(Math.random()).slice(2, 8)}`,
...overrides,
};
}
export function makeDoctor(overrides?: Partial<DoctorData>): DoctorData {
const id = uid();
return {
name: `E2E医生_${id}`,
department: '内科',
title: '主治医师',
specialty: '全科',
license_number: `DOC${id}`,
...overrides,
};
}
export function makeVitalSigns(overrides?: Partial<VitalSignsData>): VitalSignsData {
return {
record_date: new Date().toISOString().slice(0, 10),
systolic_bp_morning: 120,
diastolic_bp_morning: 80,
heart_rate: 72,
body_temperature: 36.5,
spo2: 98,
source: 'web_e2e',
...overrides,
};
}
export function makeSchedule(doctorId: string, overrides?: Partial<ScheduleData>): ScheduleData {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const date = tomorrow.toISOString().slice(0, 10);
return {
doctor_id: doctorId,
schedule_date: date,
start_time: '09:00',
end_time: '12:00',
max_appointments: 10,
...overrides,
};
}
export function makeAppointment(patientId: string, doctorId: string, scheduleId: string, overrides?: Partial<AppointmentData>): AppointmentData {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const date = tomorrow.toISOString().slice(0, 10);
return {
patient_id: patientId,
doctor_id: doctorId,
schedule_id: scheduleId,
appointment_date: date,
start_time: '09:00',
end_time: '10:00',
reason: 'E2E测试预约',
...overrides,
};
}
export function makeFollowUpTemplate(overrides?: Partial<FollowUpTemplateData>): FollowUpTemplateData {
return {
name: `E2E随访模板_${uid()}`,
description: 'E2E自动创建的随访模板',
follow_up_type: 'phone',
...overrides,
};
}
export function makeFollowUpTask(patientId: string, _templateId: string, overrides?: Partial<FollowUpTaskData>): FollowUpTaskData {
const plannedDate = new Date();
plannedDate.setDate(plannedDate.getDate() + 7);
return {
patient_id: patientId,
follow_up_type: 'phone',
planned_date: plannedDate.toISOString().slice(0, 10),
...overrides,
};
}
export function makeAlertRule(overrides?: Partial<AlertRuleData>): AlertRuleData {
return {
name: `E2E告警规则_${uid()}`,
device_type: 'heart_rate',
condition_type: 'single_threshold',
condition_params: { direction: 'above', value: 50 },
severity: 'warning',
description: 'E2E测试低阈值规则用于触发告警',
...overrides,
};
}