feat: Q4 测试覆盖 + 插件生态 — 集成测试/E2E/进销存插件/热更新
Q4 成熟度路线图全部完成:
1. 集成测试框架 (Testcontainers + PostgreSQL):
- auth_tests: 用户 CRUD、租户隔离、用户名唯一性
- plugin_tests: 动态表创建查询、租户数据隔离
2. Playwright E2E 测试:
- 登录页面渲染和表单验证测试
- 用户管理、插件管理、多租户隔离占位测试
3. 进销存插件 (erp-plugin-inventory):
- 6 实体: 产品/仓库/库存/供应商/采购单/销售单
- 12 权限、6 页面、完整 manifest
- WASM 编译验证通过
4. 插件热更新:
- POST /api/v1/admin/plugins/{id}/upgrade
- manifest 对比 + 增量 DDL + WASM 热加载
- 失败保持旧版本继续运行
5. 文档更新: CLAUDE.md + wiki/index.md 同步 Q2-Q4 进度
This commit is contained in:
129
crates/erp-server/tests/integration/auth_tests.rs
Normal file
129
crates/erp-server/tests/integration/auth_tests.rs
Normal file
@@ -0,0 +1,129 @@
|
||||
use erp_auth::dto::CreateUserReq;
|
||||
use erp_auth::service::user_service::UserService;
|
||||
use erp_core::events::EventBus;
|
||||
use erp_core::types::Pagination;
|
||||
|
||||
use super::test_db::TestDb;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_user_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 user = UserService::create(
|
||||
tenant_id,
|
||||
operator_id,
|
||||
&CreateUserReq {
|
||||
username: "testuser".to_string(),
|
||||
password: "TestPass123".to_string(),
|
||||
email: Some("test@example.com".to_string()),
|
||||
phone: None,
|
||||
display_name: Some("测试用户".to_string()),
|
||||
},
|
||||
db,
|
||||
&event_bus,
|
||||
)
|
||||
.await
|
||||
.expect("创建用户失败");
|
||||
|
||||
assert_eq!(user.username, "testuser");
|
||||
assert_eq!(user.status, "active");
|
||||
|
||||
// 按 ID 查询
|
||||
let found = UserService::get_by_id(user.id, tenant_id, db)
|
||||
.await
|
||||
.expect("查询用户失败");
|
||||
assert_eq!(found.username, "testuser");
|
||||
assert_eq!(found.email, Some("test@example.com".to_string()));
|
||||
|
||||
// 列表查询
|
||||
let (users, total) = UserService::list(
|
||||
tenant_id,
|
||||
&Pagination {
|
||||
page: Some(1),
|
||||
page_size: Some(10),
|
||||
},
|
||||
None,
|
||||
db,
|
||||
)
|
||||
.await
|
||||
.expect("用户列表查询失败");
|
||||
assert_eq!(total, 1);
|
||||
assert_eq!(users[0].username, "testuser");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_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);
|
||||
|
||||
// 租户 A 创建用户
|
||||
let user_a = UserService::create(
|
||||
tenant_a,
|
||||
operator_id,
|
||||
&CreateUserReq {
|
||||
username: "user_a".to_string(),
|
||||
password: "Pass123456".to_string(),
|
||||
email: None,
|
||||
phone: None,
|
||||
display_name: None,
|
||||
},
|
||||
db,
|
||||
&event_bus,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// 租户 B 列表查询不应看到租户 A 的用户
|
||||
let (users_b, total_b) = UserService::list(
|
||||
tenant_b,
|
||||
&Pagination {
|
||||
page: Some(1),
|
||||
page_size: Some(10),
|
||||
},
|
||||
None,
|
||||
db,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(total_b, 0);
|
||||
assert!(users_b.is_empty());
|
||||
|
||||
// 租户 B 通过 ID 查询租户 A 的用户应返回错误
|
||||
let result = UserService::get_by_id(user_a.id, tenant_b, db).await;
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_username_uniqueness_within_tenant() {
|
||||
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 req = CreateUserReq {
|
||||
username: "duplicate".to_string(),
|
||||
password: "Pass123456".to_string(),
|
||||
email: None,
|
||||
phone: None,
|
||||
display_name: None,
|
||||
};
|
||||
|
||||
// 第一次创建成功
|
||||
UserService::create(tenant_id, operator_id, &req, db, &event_bus)
|
||||
.await
|
||||
.expect("创建用户应成功");
|
||||
|
||||
// 同租户重复用户名应失败
|
||||
let result = UserService::create(tenant_id, operator_id, &req, db, &event_bus).await;
|
||||
assert!(result.is_err());
|
||||
}
|
||||
Reference in New Issue
Block a user