use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct VerificationInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub app_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub app_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub app_status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub verification_status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub verification_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub verification_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expire_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scopes: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant_info: Option<TenantInfo>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TenantInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant_name: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_verification_info_creation() {
let verification_info = VerificationInfo {
app_id: Some("cli_test_app".to_string()),
app_name: Some("Test CLI Application".to_string()),
app_status: Some("active".to_string()),
verification_status: Some("verified".to_string()),
verification_type: Some("self_built".to_string()),
verification_time: Some("1642723200000".to_string()),
expire_time: Some("1674259200000".to_string()),
scopes: Some(vec!["im:read".to_string(), "contact:read".to_string()]),
tenant_info: Some(TenantInfo {
tenant_key: Some("2ed263bf32cf1651".to_string()),
tenant_name: Some("Test Organization".to_string()),
}),
};
assert_eq!(verification_info.app_id, Some("cli_test_app".to_string()));
assert_eq!(
verification_info.app_name,
Some("Test CLI Application".to_string())
);
assert_eq!(
verification_info.verification_status,
Some("verified".to_string())
);
assert_eq!(verification_info.scopes.as_ref().unwrap().len(), 2);
assert!(verification_info.tenant_info.is_some());
}
#[test]
fn test_verification_info_serialization() {
let verification_info = VerificationInfo {
app_id: Some("app_123".to_string()),
app_name: Some("Lark App".to_string()),
app_status: Some("active".to_string()),
verification_status: Some("pending".to_string()),
verification_type: Some("marketplace".to_string()),
verification_time: Some("1640995200000".to_string()),
expire_time: None,
scopes: Some(vec![
"im:write".to_string(),
"contact:write".to_string(),
"calendar:read".to_string(),
]),
tenant_info: Some(TenantInfo {
tenant_key: Some("test_tenant_key".to_string()),
tenant_name: Some("Acme Corp".to_string()),
}),
};
let json = serde_json::to_string(&verification_info).unwrap();
assert!(json.contains("app_123"));
assert!(json.contains("Lark App"));
assert!(json.contains("pending"));
assert!(json.contains("im:write"));
assert!(json.contains("test_tenant_key"));
assert!(json.contains("Acme Corp"));
assert!(!json.contains("expire_time"));
let deserialized: VerificationInfo = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.app_id, Some("app_123".to_string()));
assert_eq!(
deserialized.verification_status,
Some("pending".to_string())
);
assert_eq!(deserialized.expire_time, None);
assert_eq!(deserialized.scopes.as_ref().unwrap().len(), 3);
}
#[test]
fn test_verification_info_with_none_values() {
let verification_info = VerificationInfo {
app_id: Some("minimal_app".to_string()),
app_name: None,
app_status: None,
verification_status: None,
verification_type: None,
verification_time: None,
expire_time: None,
scopes: None,
tenant_info: None,
};
let json = serde_json::to_string(&verification_info).unwrap();
assert!(json.contains("minimal_app"));
assert!(!json.contains("app_name"));
assert!(!json.contains("app_status"));
assert!(!json.contains("verification_status"));
assert!(!json.contains("scopes"));
assert!(!json.contains("tenant_info"));
}
#[test]
fn test_verification_info_debug() {
let verification_info = VerificationInfo {
app_id: Some("debug_test".to_string()),
app_name: Some("Debug Test App".to_string()),
app_status: Some("testing".to_string()),
verification_status: Some("in_progress".to_string()),
verification_type: Some("internal".to_string()),
verification_time: Some("1672531200000".to_string()),
expire_time: Some("1704067200000".to_string()),
scopes: Some(vec!["debug:read".to_string()]),
tenant_info: Some(TenantInfo {
tenant_key: Some("debug_tenant".to_string()),
tenant_name: Some("Debug Org".to_string()),
}),
};
let debug_output = format!("{:?}", verification_info);
assert!(debug_output.contains("VerificationInfo"));
assert!(debug_output.contains("debug_test"));
assert!(debug_output.contains("Debug Test App"));
assert!(debug_output.contains("in_progress"));
}
#[test]
fn test_tenant_info_creation() {
let tenant_info = TenantInfo {
tenant_key: Some("tenant_456".to_string()),
tenant_name: Some("Sample Tenant".to_string()),
};
assert_eq!(tenant_info.tenant_key, Some("tenant_456".to_string()));
assert_eq!(tenant_info.tenant_name, Some("Sample Tenant".to_string()));
}
#[test]
fn test_tenant_info_serialization() {
let tenant_info = TenantInfo {
tenant_key: Some("serialization_test".to_string()),
tenant_name: Some("Serialization Test Org".to_string()),
};
let json = serde_json::to_string(&tenant_info).unwrap();
assert!(json.contains("serialization_test"));
assert!(json.contains("Serialization Test Org"));
let deserialized: TenantInfo = serde_json::from_str(&json).unwrap();
assert_eq!(
deserialized.tenant_key,
Some("serialization_test".to_string())
);
assert_eq!(
deserialized.tenant_name,
Some("Serialization Test Org".to_string())
);
}
#[test]
fn test_tenant_info_with_none_values() {
let tenant_info = TenantInfo {
tenant_key: None,
tenant_name: None,
};
let json = serde_json::to_string(&tenant_info).unwrap();
assert_eq!(json, "{}");
let deserialized: TenantInfo = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.tenant_key, None);
assert_eq!(deserialized.tenant_name, None);
}
#[test]
fn test_tenant_info_partial_data() {
let tenant_info_key_only = TenantInfo {
tenant_key: Some("key_only".to_string()),
tenant_name: None,
};
let json = serde_json::to_string(&tenant_info_key_only).unwrap();
assert!(json.contains("key_only"));
assert!(!json.contains("tenant_name"));
let tenant_info_name_only = TenantInfo {
tenant_key: None,
tenant_name: Some("Name Only Org".to_string()),
};
let json2 = serde_json::to_string(&tenant_info_name_only).unwrap();
assert!(json2.contains("Name Only Org"));
assert!(!json2.contains("tenant_key"));
}
#[test]
fn test_tenant_info_debug() {
let tenant_info = TenantInfo {
tenant_key: Some("debug_key".to_string()),
tenant_name: Some("Debug Tenant".to_string()),
};
let debug_output = format!("{:?}", tenant_info);
assert!(debug_output.contains("TenantInfo"));
assert!(debug_output.contains("debug_key"));
assert!(debug_output.contains("Debug Tenant"));
}
#[test]
fn test_verification_info_scopes_edge_cases() {
let empty_scopes = VerificationInfo {
app_id: Some("empty_scopes_test".to_string()),
app_name: Some("Empty Scopes Test".to_string()),
app_status: Some("active".to_string()),
verification_status: Some("verified".to_string()),
verification_type: Some("test".to_string()),
verification_time: Some("1600000000000".to_string()),
expire_time: Some("1700000000000".to_string()),
scopes: Some(vec![]),
tenant_info: None,
};
let json = serde_json::to_string(&empty_scopes).unwrap();
assert!(json.contains("\"scopes\":[]"));
let single_scope = VerificationInfo {
app_id: Some("single_scope_test".to_string()),
app_name: Some("Single Scope Test".to_string()),
app_status: Some("active".to_string()),
verification_status: Some("verified".to_string()),
verification_type: Some("test".to_string()),
verification_time: Some("1600000000000".to_string()),
expire_time: Some("1700000000000".to_string()),
scopes: Some(vec!["single:scope".to_string()]),
tenant_info: None,
};
let json2 = serde_json::to_string(&single_scope).unwrap();
assert!(json2.contains("single:scope"));
assert_eq!(single_scope.scopes.as_ref().unwrap().len(), 1);
}
#[test]
fn test_verification_info_timestamp_handling() {
let info_with_timestamps = VerificationInfo {
app_id: Some("timestamp_test".to_string()),
app_name: Some("Timestamp Test".to_string()),
app_status: Some("active".to_string()),
verification_status: Some("verified".to_string()),
verification_type: Some("automated".to_string()),
verification_time: Some("1640995200000".to_string()),
expire_time: Some("1672531200000".to_string()),
scopes: Some(vec!["time:test".to_string()]),
tenant_info: None,
};
assert!(info_with_timestamps
.verification_time
.as_ref()
.unwrap()
.parse::<u64>()
.is_ok());
assert!(info_with_timestamps
.expire_time
.as_ref()
.unwrap()
.parse::<u64>()
.is_ok());
let verification_time: u64 = info_with_timestamps
.verification_time
.unwrap()
.parse()
.unwrap();
let expire_time: u64 = info_with_timestamps.expire_time.unwrap().parse().unwrap();
assert!(expire_time > verification_time);
}
}