Files
hms/crates/erp-server/tests/integration/workflow_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

248 lines
7.0 KiB
Rust
Raw 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.
use erp_core::events::EventBus;
use erp_core::types::Pagination;
use erp_workflow::dto::{
CompleteTaskReq, CreateProcessDefinitionReq, EdgeDef, NodeDef, NodeType, StartInstanceReq,
};
use erp_workflow::service::definition_service::DefinitionService;
use erp_workflow::service::instance_service::InstanceService;
use erp_workflow::service::task_service::TaskService;
use super::test_db::TestDb;
/// 构建一个最简单的线性流程:开始 → 审批 → 结束
/// assignee 指向 operator_id使 list_pending 能查到任务
fn make_simple_definition(
name: &str,
key: &str,
assignee_id: Option<uuid::Uuid>,
) -> CreateProcessDefinitionReq {
CreateProcessDefinitionReq {
name: name.to_string(),
key: key.to_string(),
category: Some("test".to_string()),
description: Some("集成测试流程".to_string()),
nodes: vec![
NodeDef {
id: "start".to_string(),
node_type: NodeType::StartEvent,
name: "开始".to_string(),
assignee_id: None,
candidate_groups: None,
service_type: None,
service_config: None,
position: None,
},
NodeDef {
id: "approve".to_string(),
node_type: NodeType::UserTask,
name: "审批".to_string(),
assignee_id,
candidate_groups: None,
service_type: None,
service_config: None,
position: None,
},
NodeDef {
id: "end".to_string(),
node_type: NodeType::EndEvent,
name: "结束".to_string(),
assignee_id: None,
candidate_groups: None,
service_type: None,
service_config: None,
position: None,
},
],
edges: vec![
EdgeDef {
id: "e1".to_string(),
source: "start".to_string(),
target: "approve".to_string(),
condition: None,
label: None,
},
EdgeDef {
id: "e2".to_string(),
source: "approve".to_string(),
target: "end".to_string(),
condition: None,
label: None,
},
],
}
}
#[tokio::test]
async fn test_workflow_definition_crud() {
let test_db = TestDb::new().await;
let db = test_db.db();
let tenant_id = uuid::Uuid::new_v4();
let operator_id = uuid::Uuid::new_v4();
let event_bus = EventBus::new(100);
let def = DefinitionService::create(
tenant_id,
operator_id,
&make_simple_definition("测试流程", "test-flow-1", None),
db,
&event_bus,
)
.await
.expect("创建流程定义失败");
assert_eq!(def.name, "测试流程");
assert_eq!(def.status, "draft");
let (defs, total) = DefinitionService::list(
tenant_id,
&Pagination {
page: Some(1),
page_size: Some(10),
},
db,
)
.await
.expect("查询流程定义列表失败");
assert_eq!(total, 1);
assert_eq!(defs[0].name, "测试流程");
let found = DefinitionService::get_by_id(def.id, tenant_id, db)
.await
.expect("查询流程定义失败");
assert_eq!(found.id, def.id);
let published = DefinitionService::publish(def.id, tenant_id, operator_id, db, &event_bus)
.await
.expect("发布流程定义失败");
assert_eq!(published.status, "published");
}
#[tokio::test]
async fn test_workflow_instance_lifecycle() {
let test_db = TestDb::new().await;
let db = test_db.db();
let tenant_id = uuid::Uuid::new_v4();
let operator_id = uuid::Uuid::new_v4();
let event_bus = EventBus::new(100);
let def = DefinitionService::create(
tenant_id,
operator_id,
&make_simple_definition("生命周期测试", "lifecycle-flow", Some(operator_id)),
db,
&event_bus,
)
.await
.expect("创建流程定义失败");
let def = DefinitionService::publish(def.id, tenant_id, operator_id, db, &event_bus)
.await
.expect("发布流程定义失败");
let instance = InstanceService::start(
tenant_id,
operator_id,
&StartInstanceReq {
definition_id: def.id,
business_key: Some("测试实例".to_string()),
variables: None,
},
db,
&event_bus,
)
.await
.expect("启动流程实例失败");
assert_eq!(instance.status, "running");
let (tasks, task_total) = TaskService::list_pending(
tenant_id,
operator_id,
&Pagination {
page: Some(1),
page_size: Some(10),
},
db,
)
.await
.expect("查询待办任务失败");
assert_eq!(task_total, 1);
assert_eq!(tasks[0].status, "pending");
let completed = TaskService::complete(
tasks[0].id,
tenant_id,
operator_id,
&CompleteTaskReq {
outcome: "approved".to_string(),
form_data: Some(serde_json::json!({"comment": "同意"})),
},
db,
&event_bus,
)
.await
.expect("完成任务失败");
assert_eq!(completed.status, "completed");
}
#[tokio::test]
async fn test_workflow_tenant_isolation() {
let test_db = TestDb::new().await;
let db = test_db.db();
let tenant_a = uuid::Uuid::new_v4();
let tenant_b = uuid::Uuid::new_v4();
let operator_id = uuid::Uuid::new_v4();
let event_bus = EventBus::new(100);
let def_a = DefinitionService::create(
tenant_a,
operator_id,
&make_simple_definition("租户A流程", "tenant-a-flow", None),
db,
&event_bus,
)
.await
.expect("创建流程定义失败");
let (defs_b, total_b) = DefinitionService::list(
tenant_b,
&Pagination {
page: Some(1),
page_size: Some(10),
},
db,
)
.await
.expect("查询流程定义列表失败");
assert_eq!(total_b, 0);
assert!(defs_b.is_empty());
let result = DefinitionService::get_by_id(def_a.id, tenant_b, db).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_event_bus_pub_sub() {
let event_bus = EventBus::new(100);
let tenant_id = uuid::Uuid::new_v4();
let (mut receiver, _handle) = event_bus.subscribe_filtered("user.".to_string());
let event = erp_core::events::DomainEvent::new(
"user.created",
tenant_id,
serde_json::json!({"username": "test"}),
);
event_bus.broadcast(event);
let other_event =
erp_core::events::DomainEvent::new("workflow.started", tenant_id, serde_json::json!({}));
event_bus.broadcast(other_event);
let received = receiver.recv().await;
assert!(received.is_some());
let received = received.unwrap();
assert_eq!(received.event_type, "user.created");
assert_eq!(received.payload["username"], "test");
}