use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct SeatAssignmentListRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SeatAssignment {
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub seat_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assigned_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SeatActivityListRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_time: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SeatActivity {
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub activity_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub activity_level: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AuditLogListRequest {
pub app_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operation_type: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AuditLog {
#[serde(skip_serializing_if = "Option::is_none")]
pub log_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operator_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operator_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operation_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operation_object: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operation_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub operation_result: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DataChangeLogListRequest {
pub app_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object_api_name: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DataChangeLog {
#[serde(skip_serializing_if = "Option::is_none")]
pub log_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub record_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object_api_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub change_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub change_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub changed_by: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub before_data: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub after_data: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RoleMemberAuthorizationRequest {
pub app_id: String,
pub role_api_name: String,
pub user_ids: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RoleMember {
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub role_api_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub authorized_time: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RecordPermissionMemberAuthorizationRequest {
pub app_id: String,
pub record_permission_api_name: String,
pub user_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub record_ids: Option<Vec<String>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct OqlQueryRequest {
pub app_id: String,
pub oql: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct OqlQueryResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Vec<serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_count: Option<i32>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RecordSearchRequest {
pub app_id: String,
pub object_api_name: String,
pub keyword: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RecordQueryRequest {
pub app_id: String,
pub object_api_name: String,
pub record_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<Vec<String>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RecordCreateRequest {
pub app_id: String,
pub object_api_name: String,
pub data: serde_json::Value,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RecordUpdateRequest {
pub app_id: String,
pub object_api_name: String,
pub record_id: String,
pub data: serde_json::Value,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RecordDeleteRequest {
pub app_id: String,
pub object_api_name: String,
pub record_id: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchRecordRequest {
pub app_id: String,
pub object_api_name: String,
pub records: Vec<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchRecordQueryRequest {
pub app_id: String,
pub object_api_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub filter: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Record {
#[serde(skip_serializing_if = "Option::is_none")]
pub record_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_time: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FunctionInvokeRequest {
pub app_id: String,
pub function_api_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FunctionInvokeResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct EnvironmentVariableQueryRequest {
pub app_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct EnvironmentVariableGetRequest {
pub app_id: String,
pub variable_name: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct EnvironmentVariable {
#[serde(skip_serializing_if = "Option::is_none")]
pub variable_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub variable_value: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_time: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FlowExecuteRequest {
pub app_id: String,
pub flow_api_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FlowExecuteResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub instance_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTaskQueryRequest {
pub app_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTaskActionRequest {
pub app_id: String,
pub task_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTaskTransferRequest {
pub app_id: String,
pub task_id: String,
pub target_user_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTaskAddAssigneeRequest {
pub app_id: String,
pub task_id: String,
pub assignee_user_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTaskCcRequest {
pub app_id: String,
pub task_id: String,
pub cc_user_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTaskRollbackRequest {
pub app_id: String,
pub task_id: String,
pub target_node_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTaskChatGroupRequest {
pub app_id: String,
pub task_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub group_name: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserTask {
#[serde(skip_serializing_if = "Option::is_none")]
pub task_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub task_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instance_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignee: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub due_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RollbackPoint {
#[serde(skip_serializing_if = "Option::is_none")]
pub node_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub node_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub node_type: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PageResponse<T> {
#[serde(skip_serializing_if = "Option::is_none")]
pub items: Option<Vec<T>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_more: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total_count: Option<i32>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserPermissionQueryRequest {
pub user_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub resource_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub resource_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub permission_type: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct UserPermission {
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub resource_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub resource_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub permission_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub granted: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub granted_by_role: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub granted_time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_at: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AccessTokenCreateRequest {
pub app_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
pub scope: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_in: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AccessToken {
#[serde(skip_serializing_if = "Option::is_none")]
pub token_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub access_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_in: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<Vec<String>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AppAuthorizationRequest {
pub app_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
pub scope: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redirect_uri: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AppAuthorization {
#[serde(skip_serializing_if = "Option::is_none")]
pub authorization_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub redirect_uri: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_in: Option<i32>,
}
#[cfg(test)]
#[allow(unused_variables, unused_unsafe)]
mod tests {
use super::*;
use serde_json;
#[test]
fn test_seat_assignment_list_request() {
let request = SeatAssignmentListRequest {
page_size: Some(100),
page_token: Some("token123".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("100"));
assert!(json.contains("token123"));
}
#[test]
fn test_seat_assignment_complete() {
let assignment = SeatAssignment {
user_id: Some("user123".to_string()),
user_name: Some("张三".to_string()),
seat_type: Some("premium".to_string()),
assigned_time: Some("2024-01-01T00:00:00Z".to_string()),
status: Some("active".to_string()),
};
let json = serde_json::to_string(&assignment).unwrap();
assert!(json.contains("user123"));
assert!(json.contains("张三"));
assert!(json.contains("premium"));
assert!(json.contains("active"));
}
#[test]
fn test_seat_activity_list_request() {
let request = SeatActivityListRequest {
page_size: Some(50),
page_token: None,
start_time: Some("2024-01-01T00:00:00Z".to_string()),
end_time: Some("2024-01-31T23:59:59Z".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("50"));
assert!(json.contains("2024-01-01"));
assert!(json.contains("2024-01-31"));
assert!(!json.contains("page_token"));
}
#[test]
fn test_seat_activity_detailed() {
let activity = SeatActivity {
user_id: Some("user456".to_string()),
user_name: Some("李四".to_string()),
activity_time: Some("2024-01-15T10:30:00Z".to_string()),
activity_level: Some("high".to_string()),
};
let json = serde_json::to_string(&activity).unwrap();
assert!(json.contains("user456"));
assert!(json.contains("李四"));
assert!(json.contains("2024-01-15T10:30:00Z"));
assert!(json.contains("high"));
}
#[test]
fn test_audit_log_list_request() {
let request = AuditLogListRequest {
app_id: "app123".to_string(),
page_size: Some(200),
page_token: Some("audit_token".to_string()),
start_time: Some("2024-01-01T00:00:00Z".to_string()),
end_time: Some("2024-01-07T23:59:59Z".to_string()),
operation_type: Some("user_create".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("app123"));
assert!(json.contains("200"));
assert!(json.contains("audit_token"));
assert!(json.contains("user_create"));
assert!(json.contains("user_create"));
}
#[test]
fn test_audit_log_security_event() {
let log = AuditLog {
log_id: Some("log789".to_string()),
operator_id: Some("user789".to_string()),
operator_name: Some("王五".to_string()),
operation_type: Some("password_reset".to_string()),
operation_object: Some("user_account".to_string()),
operation_time: Some("2024-01-15T14:20:00Z".to_string()),
operation_result: Some("success".to_string()),
details: Some(serde_json::json!({
"reason": "forgot_password",
"method": "email_verification"
})),
};
let json = serde_json::to_string(&log).unwrap();
assert!(json.contains("log789"));
assert!(json.contains("password_reset"));
assert!(json.contains("success"));
assert!(json.contains("forgot_password"));
}
#[test]
fn test_data_change_log_list_request() {
let request = DataChangeLogListRequest {
app_id: "app987".to_string(),
page_size: Some(75),
page_token: None,
object_api_name: Some("user_profile".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("app987"));
assert!(json.contains("75"));
assert!(json.contains("user_profile"));
}
#[test]
fn test_data_change_log_detailed() {
let log = DataChangeLog {
log_id: Some("log123".to_string()),
record_id: Some("record456".to_string()),
object_api_name: Some("department".to_string()),
change_type: Some("create".to_string()),
change_time: Some("2024-01-15T16:45:00Z".to_string()),
changed_by: Some("admin456".to_string()),
before_data: None,
after_data: Some(serde_json::json!({
"name": "新技术部",
"parent_id": "company",
"status": "active"
})),
};
let json = serde_json::to_string(&log).unwrap();
assert!(json.contains("log123"));
assert!(json.contains("record456"));
assert!(json.contains("create"));
assert!(json.contains("2024-01-15T16:45:00Z"));
assert!(json.contains("admin456"));
assert!(json.contains("新技术部"));
}
#[test]
fn test_role_member_authorization_request() {
let request = RoleMemberAuthorizationRequest {
app_id: "app456".to_string(),
role_api_name: "role_admin".to_string(),
user_ids: vec!["user789".to_string(), "user456".to_string()],
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("app456"));
assert!(json.contains("role_admin"));
assert!(json.contains("user789"));
assert!(json.contains("user456"));
}
#[test]
fn test_role_member_complete() {
let member = RoleMember {
user_id: Some("user654".to_string()),
user_name: Some("赵六".to_string()),
role_api_name: Some("role456".to_string()),
authorized_time: Some("2024-01-01T09:00:00Z".to_string()),
};
let json = serde_json::to_string(&member).unwrap();
assert!(json.contains("user654"));
assert!(json.contains("赵六"));
assert!(json.contains("role456"));
assert!(json.contains("2024-01-01T09:00:00Z"));
}
#[test]
fn test_user_permission_query_request() {
let request = UserPermissionQueryRequest {
user_id: "user888".to_string(),
resource_type: Some("document".to_string()),
resource_id: Some("doc123".to_string()),
permission_type: Some("read".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("user888"));
assert!(json.contains("document"));
assert!(json.contains("doc123"));
assert!(json.contains("read"));
}
#[test]
fn test_user_permission_granted() {
let permission = UserPermission {
user_id: Some("user999".to_string()),
resource_type: Some("project".to_string()),
resource_id: Some("proj456".to_string()),
permission_type: Some("write".to_string()),
granted: Some(true),
granted_by_role: Some("project_admin".to_string()),
granted_time: Some("2024-01-10T14:00:00Z".to_string()),
expires_at: None,
};
let json = serde_json::to_string(&permission).unwrap();
assert!(json.contains("user999"));
assert!(json.contains("project"));
assert!(json.contains("write"));
assert!(json.contains("true"));
assert!(json.contains("project_admin"));
}
#[test]
fn test_access_token_create_request() {
let request = AccessTokenCreateRequest {
app_id: "app123".to_string(),
user_id: Some("user456".to_string()),
scope: vec!["read:user".to_string(), "write:document".to_string()],
expires_in: Some(3600),
description: Some("API访问令牌".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("app123"));
assert!(json.contains("user456"));
assert!(json.contains("read:user"));
assert!(json.contains("write:document"));
assert!(json.contains("3600"));
assert!(json.contains("API访问令牌"));
}
#[test]
fn test_access_token_active() {
let token = AccessToken {
token_id: Some("token789".to_string()),
access_token: Some("access_123".to_string()),
token_type: Some("Bearer".to_string()),
expires_in: Some(3600),
scope: Some(vec!["read:profile".to_string()]),
};
let json = serde_json::to_string(&token).unwrap();
assert!(json.contains("token789"));
assert!(json.contains("access_123"));
assert!(json.contains("read:profile"));
assert!(json.contains("Bearer"));
assert!(json.contains("3600"));
}
#[test]
fn test_app_authorization_request() {
let request = AppAuthorizationRequest {
app_id: "app789".to_string(),
user_id: Some("user321".to_string()),
scope: vec!["read:contact".to_string(), "write:calendar".to_string()],
redirect_uri: Some("https://app.example.com/callback".to_string()),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("app789"));
assert!(json.contains("user321"));
assert!(json.contains("read:contact"));
assert!(json.contains("write:calendar"));
assert!(json.contains("callback"));
}
#[test]
fn test_app_authorization_approved() {
let auth = AppAuthorization {
authorization_code: Some("code_abc123".to_string()),
state: Some("approved".to_string()),
redirect_uri: Some("https://app.example.com/callback".to_string()),
expires_in: Some(600),
};
let json = serde_json::to_string(&auth).unwrap();
assert!(json.contains("code_abc123"));
assert!(json.contains("approved"));
assert!(json.contains("callback"));
assert!(json.contains("600"));
}
#[test]
fn test_page_response_generic() {
let response: PageResponse<String> = PageResponse {
items: Some(vec!["item1".to_string(), "item2".to_string()]),
has_more: Some(true),
page_token: Some("next_token".to_string()),
total_count: Some(250),
};
let json = serde_json::to_string(&response).unwrap();
assert!(json.contains("item1"));
assert!(json.contains("true"));
assert!(json.contains("next_token"));
assert!(json.contains("250"));
}
}