use std::collections::HashMap;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::clients::RestClient;
use crate::rest::{
build_path, ResourceError, ResourceOperation, ResourcePath, ResourceResponse, RestResource,
};
use crate::HttpMethod;
use super::common::MetafieldOwner;
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct Metafield {
#[serde(skip_serializing)]
pub id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub value: Option<String>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub metafield_type: Option<String>,
#[serde(skip_serializing)]
pub owner_id: Option<u64>,
#[serde(skip_serializing)]
pub owner_resource: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing)]
pub created_at: Option<DateTime<Utc>>,
#[serde(skip_serializing)]
pub updated_at: Option<DateTime<Utc>>,
#[serde(skip_serializing)]
pub admin_graphql_api_id: Option<String>,
}
impl RestResource for Metafield {
type Id = u64;
type FindParams = MetafieldFindParams;
type AllParams = MetafieldListParams;
type CountParams = MetafieldCountParams;
const NAME: &'static str = "Metafield";
const PLURAL: &'static str = "metafields";
const PATHS: &'static [ResourcePath] = &[
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["product_id", "id"],
"products/{product_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["product_id"],
"products/{product_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["product_id"],
"products/{product_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["product_id"],
"products/{product_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["product_id", "id"],
"products/{product_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["product_id", "id"],
"products/{product_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["variant_id", "id"],
"variants/{variant_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["variant_id"],
"variants/{variant_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["variant_id"],
"variants/{variant_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["variant_id"],
"variants/{variant_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["variant_id", "id"],
"variants/{variant_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["variant_id", "id"],
"variants/{variant_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["customer_id", "id"],
"customers/{customer_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["customer_id"],
"customers/{customer_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["customer_id"],
"customers/{customer_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["customer_id"],
"customers/{customer_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["customer_id", "id"],
"customers/{customer_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["customer_id", "id"],
"customers/{customer_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["order_id", "id"],
"orders/{order_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["order_id"],
"orders/{order_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["order_id"],
"orders/{order_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["order_id"],
"orders/{order_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["order_id", "id"],
"orders/{order_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["order_id", "id"],
"orders/{order_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["collection_id", "id"],
"collections/{collection_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["collection_id"],
"collections/{collection_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["collection_id"],
"collections/{collection_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["collection_id"],
"collections/{collection_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["collection_id", "id"],
"collections/{collection_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["collection_id", "id"],
"collections/{collection_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["page_id", "id"],
"pages/{page_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["page_id"],
"pages/{page_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["page_id"],
"pages/{page_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["page_id"],
"pages/{page_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["page_id", "id"],
"pages/{page_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["page_id", "id"],
"pages/{page_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["blog_id", "id"],
"blogs/{blog_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["blog_id"],
"blogs/{blog_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["blog_id"],
"blogs/{blog_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["blog_id"],
"blogs/{blog_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["blog_id", "id"],
"blogs/{blog_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["blog_id", "id"],
"blogs/{blog_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["article_id", "id"],
"articles/{article_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::All,
&["article_id"],
"articles/{article_id}/metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&["article_id"],
"articles/{article_id}/metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&["article_id"],
"articles/{article_id}/metafields",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["article_id", "id"],
"articles/{article_id}/metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["article_id", "id"],
"articles/{article_id}/metafields/{id}",
),
ResourcePath::new(HttpMethod::Get, ResourceOperation::All, &[], "metafields"),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Count,
&[],
"metafields/count",
),
ResourcePath::new(
HttpMethod::Post,
ResourceOperation::Create,
&[],
"metafields",
),
ResourcePath::new(
HttpMethod::Get,
ResourceOperation::Find,
&["id"],
"metafields/{id}",
),
ResourcePath::new(
HttpMethod::Put,
ResourceOperation::Update,
&["id"],
"metafields/{id}",
),
ResourcePath::new(
HttpMethod::Delete,
ResourceOperation::Delete,
&["id"],
"metafields/{id}",
),
];
fn get_id(&self) -> Option<Self::Id> {
self.id
}
}
impl Metafield {
pub async fn all_for_owner(
client: &RestClient,
owner: MetafieldOwner,
owner_id: u64,
params: Option<MetafieldListParams>,
) -> Result<ResourceResponse<Vec<Self>>, ResourceError> {
let parent_id_name = match owner {
MetafieldOwner::Product => "product_id",
MetafieldOwner::Variant => "variant_id",
MetafieldOwner::Customer => "customer_id",
MetafieldOwner::Order => "order_id",
MetafieldOwner::Collection => "collection_id",
MetafieldOwner::Page => "page_id",
MetafieldOwner::Blog => "blog_id",
MetafieldOwner::Article => "article_id",
MetafieldOwner::Shop => {
return Self::all(client, params).await;
}
};
Self::all_with_parent(client, parent_id_name, owner_id, params).await
}
pub async fn count_for_owner(
client: &RestClient,
owner: MetafieldOwner,
owner_id: u64,
params: Option<MetafieldCountParams>,
) -> Result<u64, ResourceError> {
let (parent_id_name, path_template) = match owner {
MetafieldOwner::Product => ("product_id", "products/{product_id}/metafields/count"),
MetafieldOwner::Variant => ("variant_id", "variants/{variant_id}/metafields/count"),
MetafieldOwner::Customer => ("customer_id", "customers/{customer_id}/metafields/count"),
MetafieldOwner::Order => ("order_id", "orders/{order_id}/metafields/count"),
MetafieldOwner::Collection => (
"collection_id",
"collections/{collection_id}/metafields/count",
),
MetafieldOwner::Page => ("page_id", "pages/{page_id}/metafields/count"),
MetafieldOwner::Blog => ("blog_id", "blogs/{blog_id}/metafields/count"),
MetafieldOwner::Article => ("article_id", "articles/{article_id}/metafields/count"),
MetafieldOwner::Shop => {
return Self::count(client, params).await;
}
};
let mut ids: HashMap<&str, String> = HashMap::new();
ids.insert(parent_id_name, owner_id.to_string());
let url = build_path(path_template, &ids);
let query = params
.map(|p| serialize_to_query(&p))
.transpose()?
.filter(|q| !q.is_empty());
let response = client.get(&url, query).await?;
if !response.is_ok() {
return Err(ResourceError::from_http_response(
response.code,
&response.body,
Self::NAME,
None,
response.request_id(),
));
}
let count = response
.body
.get("count")
.and_then(serde_json::Value::as_u64)
.ok_or_else(|| {
ResourceError::Http(crate::clients::HttpError::Response(
crate::clients::HttpResponseError {
code: response.code,
message: "Missing 'count' in response".to_string(),
error_reference: response.request_id().map(ToString::to_string),
},
))
})?;
Ok(count)
}
}
fn serialize_to_query<T: Serialize>(params: &T) -> Result<HashMap<String, String>, ResourceError> {
let value = serde_json::to_value(params).map_err(|e| {
ResourceError::Http(crate::clients::HttpError::Response(
crate::clients::HttpResponseError {
code: 400,
message: format!("Failed to serialize params: {e}"),
error_reference: None,
},
))
})?;
let mut query = HashMap::new();
if let serde_json::Value::Object(map) = value {
for (key, val) in map {
match val {
serde_json::Value::Null => {}
serde_json::Value::String(s) => {
query.insert(key, s);
}
serde_json::Value::Number(n) => {
query.insert(key, n.to_string());
}
serde_json::Value::Bool(b) => {
query.insert(key, b.to_string());
}
serde_json::Value::Array(arr) => {
let values: Vec<String> = arr
.iter()
.filter_map(|v| match v {
serde_json::Value::String(s) => Some(s.clone()),
serde_json::Value::Number(n) => Some(n.to_string()),
_ => None,
})
.collect();
if !values.is_empty() {
query.insert(key, values.join(","));
}
}
serde_json::Value::Object(_) => {
query.insert(key, val.to_string());
}
}
}
}
Ok(query)
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct MetafieldFindParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct MetafieldListParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metafield_namespaces: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub since_id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fields: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_info: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at_min: Option<DateTime<Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at_max: Option<DateTime<Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at_min: Option<DateTime<Utc>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at_max: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct MetafieldCountParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::rest::{get_path, ResourceOperation};
#[test]
fn test_metafield_struct_serialization() {
let metafield = Metafield {
id: Some(12345),
namespace: Some("custom".to_string()),
key: Some("color".to_string()),
value: Some("blue".to_string()),
metafield_type: Some("single_line_text_field".to_string()),
owner_id: Some(67890),
owner_resource: Some("product".to_string()),
description: Some("Product color".to_string()),
created_at: None,
updated_at: None,
admin_graphql_api_id: Some("gid://shopify/Metafield/12345".to_string()),
};
let json = serde_json::to_string(&metafield).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["namespace"], "custom");
assert_eq!(parsed["key"], "color");
assert_eq!(parsed["value"], "blue");
assert_eq!(parsed["type"], "single_line_text_field");
assert_eq!(parsed["description"], "Product color");
assert!(parsed.get("id").is_none());
assert!(parsed.get("owner_id").is_none());
assert!(parsed.get("owner_resource").is_none());
assert!(parsed.get("created_at").is_none());
assert!(parsed.get("updated_at").is_none());
assert!(parsed.get("admin_graphql_api_id").is_none());
}
#[test]
fn test_metafield_deserialization_from_api_response() {
let json = r#"{
"id": 721389482,
"namespace": "inventory",
"key": "warehouse",
"value": "A-15",
"type": "single_line_text_field",
"description": "Warehouse location",
"owner_id": 632910392,
"owner_resource": "product",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-06-20T15:45:00Z",
"admin_graphql_api_id": "gid://shopify/Metafield/721389482"
}"#;
let metafield: Metafield = serde_json::from_str(json).unwrap();
assert_eq!(metafield.id, Some(721389482));
assert_eq!(metafield.namespace.as_deref(), Some("inventory"));
assert_eq!(metafield.key.as_deref(), Some("warehouse"));
assert_eq!(metafield.value.as_deref(), Some("A-15"));
assert_eq!(
metafield.metafield_type.as_deref(),
Some("single_line_text_field")
);
assert_eq!(metafield.description.as_deref(), Some("Warehouse location"));
assert_eq!(metafield.owner_id, Some(632910392));
assert_eq!(metafield.owner_resource.as_deref(), Some("product"));
assert!(metafield.created_at.is_some());
assert!(metafield.updated_at.is_some());
assert_eq!(
metafield.admin_graphql_api_id.as_deref(),
Some("gid://shopify/Metafield/721389482")
);
}
#[test]
fn test_polymorphic_path_selection_with_product_id() {
let all_path = get_path(Metafield::PATHS, ResourceOperation::All, &["product_id"]);
assert!(all_path.is_some());
assert_eq!(
all_path.unwrap().template,
"products/{product_id}/metafields"
);
let find_path = get_path(
Metafield::PATHS,
ResourceOperation::Find,
&["product_id", "id"],
);
assert!(find_path.is_some());
assert_eq!(
find_path.unwrap().template,
"products/{product_id}/metafields/{id}"
);
let create_path = get_path(Metafield::PATHS, ResourceOperation::Create, &["product_id"]);
assert!(create_path.is_some());
assert_eq!(
create_path.unwrap().template,
"products/{product_id}/metafields"
);
let update_path = get_path(
Metafield::PATHS,
ResourceOperation::Update,
&["product_id", "id"],
);
assert!(update_path.is_some());
assert_eq!(
update_path.unwrap().template,
"products/{product_id}/metafields/{id}"
);
let delete_path = get_path(
Metafield::PATHS,
ResourceOperation::Delete,
&["product_id", "id"],
);
assert!(delete_path.is_some());
assert_eq!(
delete_path.unwrap().template,
"products/{product_id}/metafields/{id}"
);
let count_path = get_path(Metafield::PATHS, ResourceOperation::Count, &["product_id"]);
assert!(count_path.is_some());
assert_eq!(
count_path.unwrap().template,
"products/{product_id}/metafields/count"
);
}
#[test]
fn test_polymorphic_path_selection_with_customer_id() {
let all_path = get_path(Metafield::PATHS, ResourceOperation::All, &["customer_id"]);
assert!(all_path.is_some());
assert_eq!(
all_path.unwrap().template,
"customers/{customer_id}/metafields"
);
let find_path = get_path(
Metafield::PATHS,
ResourceOperation::Find,
&["customer_id", "id"],
);
assert!(find_path.is_some());
assert_eq!(
find_path.unwrap().template,
"customers/{customer_id}/metafields/{id}"
);
let create_path = get_path(
Metafield::PATHS,
ResourceOperation::Create,
&["customer_id"],
);
assert!(create_path.is_some());
assert_eq!(
create_path.unwrap().template,
"customers/{customer_id}/metafields"
);
}
#[test]
fn test_standalone_path_metafields_id_fallback() {
let find_path = get_path(Metafield::PATHS, ResourceOperation::Find, &["id"]);
assert!(find_path.is_some());
assert_eq!(find_path.unwrap().template, "metafields/{id}");
let update_path = get_path(Metafield::PATHS, ResourceOperation::Update, &["id"]);
assert!(update_path.is_some());
assert_eq!(update_path.unwrap().template, "metafields/{id}");
let delete_path = get_path(Metafield::PATHS, ResourceOperation::Delete, &["id"]);
assert!(delete_path.is_some());
assert_eq!(delete_path.unwrap().template, "metafields/{id}");
}
#[test]
fn test_shop_level_metafield_paths() {
let all_path = get_path(Metafield::PATHS, ResourceOperation::All, &[]);
assert!(all_path.is_some());
assert_eq!(all_path.unwrap().template, "metafields");
let count_path = get_path(Metafield::PATHS, ResourceOperation::Count, &[]);
assert!(count_path.is_some());
assert_eq!(count_path.unwrap().template, "metafields/count");
let create_path = get_path(Metafield::PATHS, ResourceOperation::Create, &[]);
assert!(create_path.is_some());
assert_eq!(create_path.unwrap().template, "metafields");
}
#[test]
fn test_metafield_list_params_serialization() {
let params = MetafieldListParams {
namespace: Some("custom".to_string()),
key: Some("color".to_string()),
metafield_namespaces: Some("custom,inventory".to_string()),
limit: Some(50),
since_id: Some(12345),
fields: Some("id,namespace,key,value".to_string()),
page_info: None,
created_at_min: None,
created_at_max: None,
updated_at_min: None,
updated_at_max: None,
};
let json = serde_json::to_value(¶ms).unwrap();
assert_eq!(json["namespace"], "custom");
assert_eq!(json["key"], "color");
assert_eq!(json["metafield_namespaces"], "custom,inventory");
assert_eq!(json["limit"], 50);
assert_eq!(json["since_id"], 12345);
assert_eq!(json["fields"], "id,namespace,key,value");
let empty_params = MetafieldListParams::default();
let empty_json = serde_json::to_value(&empty_params).unwrap();
assert_eq!(empty_json, serde_json::json!({}));
}
#[test]
fn test_namespace_and_key_filtering() {
let params = MetafieldListParams {
namespace: Some("inventory".to_string()),
key: Some("warehouse".to_string()),
..Default::default()
};
let json = serde_json::to_value(¶ms).unwrap();
assert_eq!(json["namespace"], "inventory");
assert_eq!(json["key"], "warehouse");
}
#[test]
fn test_value_type_field_serialization_with_rename() {
let metafield = Metafield {
metafield_type: Some("json".to_string()),
..Default::default()
};
let json = serde_json::to_string(&metafield).unwrap();
assert!(json.contains("\"type\":\"json\""));
assert!(!json.contains("metafield_type"));
let json_input = r#"{"type":"number_integer"}"#;
let parsed: Metafield = serde_json::from_str(json_input).unwrap();
assert_eq!(parsed.metafield_type.as_deref(), Some("number_integer"));
}
#[test]
fn test_all_for_owner_method_signature() {
fn _assert_all_for_owner_signature<F, Fut>(f: F)
where
F: Fn(&RestClient, MetafieldOwner, u64, Option<MetafieldListParams>) -> Fut,
Fut: std::future::Future<
Output = Result<ResourceResponse<Vec<Metafield>>, ResourceError>,
>,
{
let _ = f;
}
}
#[test]
fn test_all_owner_type_paths() {
let variant_all = get_path(Metafield::PATHS, ResourceOperation::All, &["variant_id"]);
assert!(variant_all.is_some());
assert_eq!(
variant_all.unwrap().template,
"variants/{variant_id}/metafields"
);
let order_all = get_path(Metafield::PATHS, ResourceOperation::All, &["order_id"]);
assert!(order_all.is_some());
assert_eq!(order_all.unwrap().template, "orders/{order_id}/metafields");
let collection_all = get_path(Metafield::PATHS, ResourceOperation::All, &["collection_id"]);
assert!(collection_all.is_some());
assert_eq!(
collection_all.unwrap().template,
"collections/{collection_id}/metafields"
);
let page_all = get_path(Metafield::PATHS, ResourceOperation::All, &["page_id"]);
assert!(page_all.is_some());
assert_eq!(page_all.unwrap().template, "pages/{page_id}/metafields");
let blog_all = get_path(Metafield::PATHS, ResourceOperation::All, &["blog_id"]);
assert!(blog_all.is_some());
assert_eq!(blog_all.unwrap().template, "blogs/{blog_id}/metafields");
let article_all = get_path(Metafield::PATHS, ResourceOperation::All, &["article_id"]);
assert!(article_all.is_some());
assert_eq!(
article_all.unwrap().template,
"articles/{article_id}/metafields"
);
}
#[test]
fn test_metafield_get_id_returns_correct_value() {
let metafield_with_id = Metafield {
id: Some(123456789),
namespace: Some("custom".to_string()),
key: Some("test".to_string()),
..Default::default()
};
assert_eq!(metafield_with_id.get_id(), Some(123456789));
let metafield_without_id = Metafield {
id: None,
namespace: Some("custom".to_string()),
key: Some("new_key".to_string()),
..Default::default()
};
assert_eq!(metafield_without_id.get_id(), None);
}
#[test]
fn test_metafield_resource_constants() {
assert_eq!(Metafield::NAME, "Metafield");
assert_eq!(Metafield::PLURAL, "metafields");
assert!(Metafield::PATHS.len() > 50); }
#[test]
fn test_metafield_count_params_serialization() {
let params = MetafieldCountParams {
namespace: Some("custom".to_string()),
key: Some("color".to_string()),
};
let json = serde_json::to_value(¶ms).unwrap();
assert_eq!(json["namespace"], "custom");
assert_eq!(json["key"], "color");
let empty_params = MetafieldCountParams::default();
let empty_json = serde_json::to_value(&empty_params).unwrap();
assert_eq!(empty_json, serde_json::json!({}));
}
}