Files
hms/crates/erp-server/tests/integration/health_medication_tests.rs
iven 6d5a711d2c
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: 修复测试发现的 7 个问题 + 全 workspace clippy 清零
功能修复:
1. 患者创建空名称验证:后端添加 name.trim().is_empty() 检查
2. 仪表盘统计容错:单个查询失败返回零值而非 500
3. FHIR 路由修复:从 /fhir 移到 /api/v1/fhir 保持一致
4. 冻结模块后端中间件:新增 frozen_module_middleware 拦截冻结路径
5. 积分端点权限码:health.health-data.list → health.points.list
6. 角色权限迁移:护士补充 devices.list,运营补充 points.list/manage
7. 测试结果文档:R01-R05 角色测试 + T00/T10 结果归档

Clippy 全 workspace 清零(14→0 errors):
- erp-core: 修复 empty doc line、collapsible if、redundant closure 等 9 处
- erp-health: 修复 too_many_arguments、unused var、unnecessary parens 等 58 处
- erp-ai: 修复 dead_code、unused import 等 11 处
- erp-plugin: 修复 too_many_arguments、wildcard pattern 等 11 处
- erp-server-migration: 修复 enum_variant_names 5 处
- erp-auth/config/workflow/message: 各 1-3 处

工程改进:
- lint-staged 配置迁移到 .lintstagedrc.js(函数式避免文件列表传给 clippy)
- cargo fmt 统一格式化
2026-05-07 23:43:14 +08:00

266 lines
8.2 KiB
Rust

//! erp-health 用药记录集成测试
//!
//! 验证用药记录 CRUD、列表按患者过滤、租户隔离、乐观锁。
use erp_health::dto::medication_record_dto::*;
use erp_health::service::medication_record_service;
use super::test_fixture::TestApp;
fn default_create_medication_req(patient_id: uuid::Uuid) -> CreateMedicationRecordReq {
CreateMedicationRecordReq {
patient_id,
medication_name: "缬沙坦".to_string(),
generic_name: Some("Valsartan".to_string()),
dosage: Some("80mg".to_string()),
unit: Some("mg".to_string()),
frequency: Some("daily".to_string()),
route: Some("oral".to_string()),
start_date: chrono::NaiveDate::from_ymd_opt(2026, 1, 1),
end_date: None,
is_current: Some(true),
prescribed_by: None,
notes: None,
}
}
async fn seed_medication(app: &TestApp, patient_id: uuid::Uuid) -> MedicationRecordResp {
medication_record_service::create_medication(
app.health_state(),
app.tenant_id(),
Some(app.operator_id()),
default_create_medication_req(patient_id),
)
.await
.expect("创建用药记录应成功")
}
// ---------------------------------------------------------------------------
// 测试 1: 创建用药记录
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_create() {
let app = TestApp::new().await;
let patient_id = app.create_patient("用药患者").await;
let med = seed_medication(&app, patient_id).await;
assert_eq!(med.patient_id, patient_id);
assert_eq!(med.medication_name, "缬沙坦");
assert_eq!(med.frequency, Some("daily".to_string()));
assert!(med.is_current);
assert_eq!(med.version, 1);
}
// ---------------------------------------------------------------------------
// 测试 2: 查询用药记录
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_get() {
let app = TestApp::new().await;
let patient_id = app.create_patient("用药查询患者").await;
let med = seed_medication(&app, patient_id).await;
let fetched =
medication_record_service::get_medication(app.health_state(), app.tenant_id(), med.id)
.await
.expect("查询应成功");
assert_eq!(fetched.id, med.id);
assert_eq!(fetched.medication_name, "缬沙坦");
}
// ---------------------------------------------------------------------------
// 测试 3: 更新用药记录
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_update() {
let app = TestApp::new().await;
let patient_id = app.create_patient("用药更新患者").await;
let med = seed_medication(&app, patient_id).await;
let updated = medication_record_service::update_medication(
app.health_state(),
app.tenant_id(),
med.id,
Some(app.operator_id()),
UpdateMedicationRecordReq {
dosage: Some("160mg".to_string()),
is_current: Some(false),
medication_name: None,
generic_name: None,
unit: None,
frequency: None,
route: None,
start_date: None,
end_date: None,
prescribed_by: None,
notes: None,
},
med.version,
)
.await
.expect("更新应成功");
assert_eq!(updated.dosage, Some("160mg".to_string()));
assert!(!updated.is_current);
assert_eq!(updated.version, 2);
}
// ---------------------------------------------------------------------------
// 测试 4: 列表按患者过滤
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_list_by_patient() {
let app = TestApp::new().await;
let patient_a = app.create_patient("用药列表A").await;
let patient_b = app.create_patient("用药列表B").await;
seed_medication(&app, patient_a).await;
seed_medication(&app, patient_b).await;
let list_a = medication_record_service::list_medications(
app.health_state(),
app.tenant_id(),
patient_a,
1,
20,
)
.await
.unwrap();
assert_eq!(list_a.total, 1);
let list_b = medication_record_service::list_medications(
app.health_state(),
app.tenant_id(),
patient_b,
1,
20,
)
.await
.unwrap();
assert_eq!(list_b.total, 1);
}
// ---------------------------------------------------------------------------
// 测试 5: 软删除
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_soft_delete() {
let app = TestApp::new().await;
let patient_id = app.create_patient("用药删除患者").await;
let med = seed_medication(&app, patient_id).await;
medication_record_service::delete_medication(
app.health_state(),
app.tenant_id(),
med.id,
Some(app.operator_id()),
med.version,
)
.await
.expect("删除应成功");
let result =
medication_record_service::get_medication(app.health_state(), app.tenant_id(), med.id)
.await;
assert!(result.is_err(), "软删除后查询应失败");
}
// ---------------------------------------------------------------------------
// 测试 6: 租户隔离
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_tenant_isolation() {
let app = TestApp::new().await;
let patient_id = app.create_patient("用药隔离患者").await;
seed_medication(&app, patient_id).await;
let other_tenant = uuid::Uuid::new_v4();
let list = medication_record_service::list_medications(
app.health_state(),
other_tenant,
patient_id,
1,
20,
)
.await
.unwrap();
assert_eq!(list.total, 0, "不同租户不应看到用药记录");
}
// ---------------------------------------------------------------------------
// 测试 7: 乐观锁冲突
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_version_conflict() {
let app = TestApp::new().await;
let patient_id = app.create_patient("用药锁患者").await;
let med = seed_medication(&app, patient_id).await;
// 先更新一次
medication_record_service::update_medication(
app.health_state(),
app.tenant_id(),
med.id,
Some(app.operator_id()),
UpdateMedicationRecordReq {
dosage: Some("160mg".to_string()),
medication_name: None,
generic_name: None,
unit: None,
frequency: None,
route: None,
start_date: None,
end_date: None,
is_current: None,
prescribed_by: None,
notes: None,
},
med.version,
)
.await
.unwrap();
// 用旧 version 再更新应失败
let result = medication_record_service::update_medication(
app.health_state(),
app.tenant_id(),
med.id,
Some(app.operator_id()),
UpdateMedicationRecordReq {
dosage: Some("320mg".to_string()),
medication_name: None,
generic_name: None,
unit: None,
frequency: None,
route: None,
start_date: None,
end_date: None,
is_current: None,
prescribed_by: None,
notes: None,
},
med.version,
)
.await;
assert!(result.is_err(), "乐观锁冲突应返回错误");
}
// ---------------------------------------------------------------------------
// 测试 8: 无效患者创建用药记录返回错误
// ---------------------------------------------------------------------------
#[tokio::test]
async fn test_medication_invalid_patient() {
let app = TestApp::new().await;
let fake_patient = uuid::Uuid::new_v4();
let result = medication_record_service::create_medication(
app.health_state(),
app.tenant_id(),
None,
default_create_medication_req(fake_patient),
)
.await;
assert!(result.is_err(), "无效患者应返回错误");
}