use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::rest::{ReadOnlyResource, ResourceOperation, ResourcePath, RestResource};
use crate::HttpMethod;
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct Policy {
#[serde(skip_serializing)]
pub title: Option<String>,
#[serde(skip_serializing)]
pub body: Option<String>,
#[serde(skip_serializing)]
pub handle: Option<String>,
#[serde(skip_serializing)]
pub url: Option<String>,
#[serde(skip_serializing)]
pub created_at: Option<DateTime<Utc>>,
#[serde(skip_serializing)]
pub updated_at: Option<DateTime<Utc>>,
}
impl RestResource for Policy {
type Id = String;
type FindParams = ();
type AllParams = ();
type CountParams = ();
const NAME: &'static str = "Policy";
const PLURAL: &'static str = "policies";
const PATHS: &'static [ResourcePath] = &[
ResourcePath::new(HttpMethod::Get, ResourceOperation::All, &[], "policies"),
];
fn get_id(&self) -> Option<Self::Id> {
self.handle.clone()
}
}
impl ReadOnlyResource for Policy {}
#[cfg(test)]
mod tests {
use super::*;
use crate::rest::{get_path, ReadOnlyResource, ResourceOperation, RestResource};
#[test]
fn test_policy_implements_read_only_resource() {
fn assert_read_only<T: ReadOnlyResource>() {}
assert_read_only::<Policy>();
}
#[test]
fn test_policy_deserialization() {
let json = r#"{
"title": "Refund Policy",
"body": "<p>We offer a 30-day return policy...</p>",
"handle": "refund-policy",
"url": "https://example.myshopify.com/policies/refund-policy",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-06-20T15:45:00Z"
}"#;
let policy: Policy = serde_json::from_str(json).unwrap();
assert_eq!(policy.title, Some("Refund Policy".to_string()));
assert_eq!(
policy.body,
Some("<p>We offer a 30-day return policy...</p>".to_string())
);
assert_eq!(policy.handle, Some("refund-policy".to_string()));
assert_eq!(
policy.url,
Some("https://example.myshopify.com/policies/refund-policy".to_string())
);
assert!(policy.created_at.is_some());
assert!(policy.updated_at.is_some());
}
#[test]
fn test_policy_read_only_paths() {
let all_path = get_path(Policy::PATHS, ResourceOperation::All, &[]);
assert!(all_path.is_some());
assert_eq!(all_path.unwrap().template, "policies");
let find_path = get_path(Policy::PATHS, ResourceOperation::Find, &["id"]);
assert!(find_path.is_none());
let count_path = get_path(Policy::PATHS, ResourceOperation::Count, &[]);
assert!(count_path.is_none());
let create_path = get_path(Policy::PATHS, ResourceOperation::Create, &[]);
assert!(create_path.is_none());
let update_path = get_path(Policy::PATHS, ResourceOperation::Update, &["id"]);
assert!(update_path.is_none());
let delete_path = get_path(Policy::PATHS, ResourceOperation::Delete, &["id"]);
assert!(delete_path.is_none());
}
#[test]
fn test_policy_has_no_standard_id() {
let policy = Policy {
title: Some("Privacy Policy".to_string()),
handle: Some("privacy-policy".to_string()),
..Default::default()
};
assert_eq!(policy.get_id(), Some("privacy-policy".to_string()));
let policy_without_handle = Policy {
title: Some("Some Policy".to_string()),
handle: None,
..Default::default()
};
assert_eq!(policy_without_handle.get_id(), None);
}
#[test]
fn test_policy_constants() {
assert_eq!(Policy::NAME, "Policy");
assert_eq!(Policy::PLURAL, "policies");
}
#[test]
fn test_policy_all_fields_are_read_only() {
let policy = Policy {
title: Some("Test Policy".to_string()),
body: Some("<p>Content</p>".to_string()),
handle: Some("test-policy".to_string()),
url: Some("https://example.com/policies/test".to_string()),
created_at: Some(
DateTime::parse_from_rfc3339("2024-01-15T10:30:00Z")
.unwrap()
.with_timezone(&Utc),
),
updated_at: Some(
DateTime::parse_from_rfc3339("2024-06-20T15:45:00Z")
.unwrap()
.with_timezone(&Utc),
),
};
let json = serde_json::to_value(&policy).unwrap();
assert_eq!(json, serde_json::json!({}));
}
}