use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PermissionOption {
pub option_id: String,
#[serde(alias = "name")]
pub label: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PermissionRequest {
pub request_id: String,
pub description: String,
pub options: Vec<PermissionOption>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PermissionResponse {
pub request_id: String,
pub option_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ChannelRequestPermission {
pub request_id: String,
pub session_id: String,
pub description: String,
pub options: Vec<PermissionOption>,
}
#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;
#[test]
fn when_serializing_permission_option_then_uses_camel_case() {
let opt = PermissionOption {
option_id: "allow_once".into(),
label: "Allow once".into(),
};
let json = serde_json::to_value(&opt).unwrap();
assert_eq!(json["optionId"], "allow_once");
assert_eq!(json["label"], "Allow once");
assert!(json.get("option_id").is_none());
let deser: PermissionOption = serde_json::from_value(json).unwrap();
assert_eq!(deser, opt);
}
#[test]
fn when_serializing_permission_request_then_uses_camel_case() {
let req = PermissionRequest {
request_id: "perm-1".into(),
description: "Allow file write?".into(),
options: vec![
PermissionOption {
option_id: "allow".into(),
label: "Allow".into(),
},
PermissionOption {
option_id: "deny".into(),
label: "Deny".into(),
},
],
};
let json = serde_json::to_value(&req).unwrap();
assert_eq!(json["requestId"], "perm-1");
assert_eq!(json["description"], "Allow file write?");
assert_eq!(json["options"].as_array().unwrap().len(), 2);
assert!(json.get("request_id").is_none());
let deser: PermissionRequest = serde_json::from_value(json).unwrap();
assert_eq!(deser, req);
}
#[test]
fn when_serializing_permission_response_then_uses_camel_case() {
let resp = PermissionResponse {
request_id: "perm-1".into(),
option_id: "allow_once".into(),
};
let json = serde_json::to_value(&resp).unwrap();
assert_eq!(json["requestId"], "perm-1");
assert_eq!(json["optionId"], "allow_once");
assert!(json.get("request_id").is_none());
let deser: PermissionResponse = serde_json::from_value(json).unwrap();
assert_eq!(deser, resp);
}
#[test]
fn when_deserializing_permission_option_with_name_alias_then_maps_to_label() {
let json = serde_json::json!({"optionId": "once", "name": "Allow once"});
let opt: PermissionOption = serde_json::from_value(json).unwrap();
assert_eq!(opt.label, "Allow once");
assert_eq!(opt.option_id, "once");
}
#[test]
fn when_serializing_channel_request_permission_then_uses_camel_case() {
let req = ChannelRequestPermission {
request_id: "req-1".into(),
session_id: "sess-1".into(),
description: "Allow file write?".into(),
options: vec![PermissionOption {
option_id: "allow".into(),
label: "Allow".into(),
}],
};
let json = serde_json::to_value(&req).unwrap();
assert_eq!(json["requestId"], "req-1");
assert_eq!(json["sessionId"], "sess-1");
assert!(json.get("request_id").is_none());
assert!(json.get("session_id").is_none());
let deser: ChannelRequestPermission = serde_json::from_value(json).unwrap();
assert_eq!(deser, req);
}
#[rstest]
fn when_permission_option_round_trips_then_identical() {
let original = PermissionOption {
option_id: "allow_once".into(),
label: "Allow once".into(),
};
let json = serde_json::to_value(&original).unwrap();
let restored: PermissionOption = serde_json::from_value(json).unwrap();
assert_eq!(original, restored);
}
#[rstest]
fn when_permission_request_round_trips_then_identical() {
let original = PermissionRequest {
request_id: "perm-1".into(),
description: "Allow file write to /tmp?".into(),
options: vec![
PermissionOption {
option_id: "allow".into(),
label: "Allow".into(),
},
PermissionOption {
option_id: "deny".into(),
label: "Deny".into(),
},
],
};
let json = serde_json::to_value(&original).unwrap();
let restored: PermissionRequest = serde_json::from_value(json).unwrap();
assert_eq!(original, restored);
}
#[rstest]
fn when_permission_request_empty_options_round_trips_then_identical() {
let original = PermissionRequest {
request_id: "perm-2".into(),
description: "No options".into(),
options: vec![],
};
let json = serde_json::to_value(&original).unwrap();
let restored: PermissionRequest = serde_json::from_value(json).unwrap();
assert_eq!(original, restored);
}
#[rstest]
fn when_permission_response_round_trips_then_identical() {
let original = PermissionResponse {
request_id: "perm-1".into(),
option_id: "allow_once".into(),
};
let json = serde_json::to_value(&original).unwrap();
let restored: PermissionResponse = serde_json::from_value(json).unwrap();
assert_eq!(original, restored);
}
#[rstest]
fn when_channel_request_permission_round_trips_then_identical() {
let original = ChannelRequestPermission {
request_id: "req-1".into(),
session_id: "sess-1".into(),
description: "Allow network access?".into(),
options: vec![PermissionOption {
option_id: "allow".into(),
label: "Allow".into(),
}],
};
let json = serde_json::to_value(&original).unwrap();
let restored: ChannelRequestPermission = serde_json::from_value(json).unwrap();
assert_eq!(original, restored);
}
}