test(message): erp-message 从 45 增至 69 个单元测试 — DND 时间窗 + TransactionError + model_to_resp
Some checks failed
CI / frontend-build (push) Has been cancelled
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- module.rs: 提取 is_in_dnd_window 纯函数 + 14 个 DND 时间窗测试(正常范围/跨午夜/边界)
- error.rs: 2 个 TransactionError 转换测试(Connection/Transaction)
- message_service: 2 个 model_to_resp 字段映射测试
- template_service: 1 个 model_to_resp 字段映射测试
- subscription_service: 1 个 model_to_resp 字段映射测试
This commit is contained in:
iven
2026-04-28 18:26:36 +08:00
parent 50e63530d9
commit 26aa66d6e3
5 changed files with 236 additions and 4 deletions

View File

@@ -488,7 +488,7 @@ impl MessageService {
Ok(())
}
fn model_to_resp(m: &message::Model) -> MessageResp {
pub(crate) fn model_to_resp(m: &message::Model) -> MessageResp {
MessageResp {
id: m.id,
tenant_id: m.tenant_id,
@@ -513,3 +513,63 @@ impl MessageService {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
fn sample_model() -> message::Model {
message::Model {
id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(),
tenant_id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000002").unwrap(),
template_id: None,
sender_id: None,
sender_type: "system".to_string(),
recipient_id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap(),
recipient_type: "user".to_string(),
title: "测试消息".to_string(),
body: "消息内容".to_string(),
priority: "normal".to_string(),
business_type: None,
business_id: None,
is_read: false,
read_at: None,
is_archived: false,
archived_at: None,
sent_at: None,
status: "sent".to_string(),
created_at: Utc::now(),
updated_at: Utc::now(),
created_by: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000004").unwrap(),
updated_by: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000004").unwrap(),
deleted_at: None,
version: 1,
}
}
#[test]
fn model_to_resp_maps_all_fields() {
let m = sample_model();
let resp = MessageService::model_to_resp(&m);
assert_eq!(resp.id, m.id);
assert_eq!(resp.tenant_id, m.tenant_id);
assert_eq!(resp.title, "测试消息");
assert_eq!(resp.body, "消息内容");
assert_eq!(resp.priority, "normal");
assert_eq!(resp.is_read, false);
assert_eq!(resp.status, "sent");
assert_eq!(resp.version, 1);
}
#[test]
fn model_to_resp_preserves_optional_fields() {
let m = sample_model();
let resp = MessageService::model_to_resp(&m);
assert_eq!(resp.template_id, None);
assert_eq!(resp.sender_id, None);
assert_eq!(resp.business_type, None);
assert_eq!(resp.read_at, None);
assert_eq!(resp.sent_at, None);
}
}

View File

@@ -105,7 +105,7 @@ impl SubscriptionService {
}
}
fn model_to_resp(m: &message_subscription::Model) -> MessageSubscriptionResp {
pub(crate) fn model_to_resp(m: &message_subscription::Model) -> MessageSubscriptionResp {
MessageSubscriptionResp {
id: m.id,
tenant_id: m.tenant_id,
@@ -121,3 +121,35 @@ impl SubscriptionService {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
#[test]
fn model_to_resp_maps_all_fields() {
let m = message_subscription::Model {
id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(),
tenant_id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000002").unwrap(),
user_id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap(),
notification_types: Some(serde_json::json!(["appointment"])),
channel_preferences: Some(serde_json::json!(["in_app"])),
dnd_enabled: true,
dnd_start: Some("22:00".to_string()),
dnd_end: Some("08:00".to_string()),
created_at: Utc::now(),
updated_at: Utc::now(),
created_by: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap(),
updated_by: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap(),
deleted_at: None,
version: 1,
};
let resp = SubscriptionService::model_to_resp(&m);
assert_eq!(resp.user_id, m.user_id);
assert_eq!(resp.dnd_enabled, true);
assert_eq!(resp.dnd_start, Some("22:00".to_string()));
assert_eq!(resp.dnd_end, Some("08:00".to_string()));
assert_eq!(resp.version, 1);
}
}

View File

@@ -174,7 +174,7 @@ impl TemplateService {
result
}
fn model_to_resp(m: &message_template::Model) -> MessageTemplateResp {
pub(crate) fn model_to_resp(m: &message_template::Model) -> MessageTemplateResp {
MessageTemplateResp {
id: m.id,
tenant_id: m.tenant_id,
@@ -267,4 +267,30 @@ mod tests {
let result = TemplateService::render("你好 {{name}}", &vars);
assert_eq!(result, "你好 赵六");
}
#[test]
fn model_to_resp_maps_all_fields() {
let m = message_template::Model {
id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap(),
tenant_id: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000002").unwrap(),
name: "欢迎消息".to_string(),
code: "WELCOME".to_string(),
channel: "in_app".to_string(),
title_template: "欢迎 {{name}}".to_string(),
body_template: "{{name}},欢迎使用".to_string(),
language: "zh-CN".to_string(),
created_at: chrono::Utc::now(),
updated_at: chrono::Utc::now(),
created_by: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap(),
updated_by: uuid::Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap(),
deleted_at: None,
version: 2,
};
let resp = TemplateService::model_to_resp(&m);
assert_eq!(resp.name, "欢迎消息");
assert_eq!(resp.code, "WELCOME");
assert_eq!(resp.channel, "in_app");
assert_eq!(resp.language, "zh-CN");
assert_eq!(resp.version, 2);
}
}