- 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
199 lines
4.7 KiB
TypeScript
199 lines
4.7 KiB
TypeScript
// 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,
|
||
};
|
||
}
|