use super::ConsentHandler;
use super::types::ConsentResponse;
use crate::error::{HttpError, Result};
impl<A: crate::auth::Authenticator> ConsentHandler<A> {
pub async fn read_consent(&self, action: &str, ids: &[&str]) -> Result<ConsentResponse> {
let url = self
.resolve_consent_url(&format!("action/{action}"))
.await?;
let mut ids_param = String::with_capacity(ids.iter().map(|s| s.len() + 1).sum());
for (i, id) in ids.iter().enumerate() {
if i > 0 {
ids_param.push(',');
}
ids_param.push_str(id);
}
let request = self
.inner
.get(&url)
.query(&[("ids", ids_param.as_str())])
.build()
.map_err(HttpError::from)?;
self.inner
.send_request_and_decode(request, &format!("Consent read action/{action} failed"))
.await
}
pub async fn read_consent_multi(
&self,
actions: &[&str],
ids: &[&str],
) -> Result<ConsentResponse> {
let url = self.resolve_consent_url("multiaction").await?;
let mut actions_param = String::with_capacity(actions.iter().map(|s| s.len() + 1).sum());
for (i, action) in actions.iter().enumerate() {
if i > 0 {
actions_param.push(',');
}
actions_param.push_str(action);
}
let mut ids_param = String::with_capacity(ids.iter().map(|s| s.len() + 1).sum());
for (i, id) in ids.iter().enumerate() {
if i > 0 {
ids_param.push(',');
}
ids_param.push_str(id);
}
let request = self
.inner
.get(&url)
.query(&[
("actions", actions_param.as_str()),
("ids", ids_param.as_str()),
])
.build()
.map_err(HttpError::from)?;
self.inner
.send_request_and_decode(request, "Consent read multiaction failed")
.await
}
}
#[cfg(test)]
mod tests {
use crate::api::consent::{ConsentResult, ConsentValue};
use crate::test_support::{MockAuthenticator, Must};
use wiremock::matchers::{method, path, query_param};
use wiremock::{Mock, MockServer, ResponseTemplate};
async fn setup() -> (MockServer, crate::client::ForceClient<MockAuthenticator>) {
let server = MockServer::start().await;
let auth = MockAuthenticator::new("test_token", &server.uri());
let client = crate::client::builder()
.authenticate(auth)
.build()
.await
.must();
(server, client)
}
#[tokio::test]
async fn test_read_consent_success() {
let (server, client) = setup().await;
Mock::given(method("GET"))
.and(path("/services/data/v60.0/consent/action/email"))
.and(query_param("ids", "001xx000003GYk1"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"001xx000003GYk1": {
"result": "Success",
"proceed": {
"email": "Yes"
}
}
})))
.mount(&server)
.await;
let result = client
.consent()
.read_consent("email", &["001xx000003GYk1"])
.await
.must();
assert_eq!(result.len(), 1);
let record = &result["001xx000003GYk1"];
assert_eq!(record.result, ConsentResult::Success);
assert_eq!(record.proceed["email"], ConsentValue::Yes);
}
#[tokio::test]
async fn test_read_consent_multiple_ids() {
let (server, client) = setup().await;
Mock::given(method("GET"))
.and(path("/services/data/v60.0/consent/action/email"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"001xx000003GYk1": {
"result": "Success",
"proceed": {"email": "Yes"}
},
"001xx000003GYk2": {
"result": "Success",
"proceed": {"email": "No"}
}
})))
.mount(&server)
.await;
let result = client
.consent()
.read_consent("email", &["001xx000003GYk1", "001xx000003GYk2"])
.await
.must();
assert_eq!(result.len(), 2);
assert_eq!(
result["001xx000003GYk1"].proceed["email"],
ConsentValue::Yes
);
assert_eq!(result["001xx000003GYk2"].proceed["email"], ConsentValue::No);
}
#[tokio::test]
async fn test_read_consent_not_found_record() {
let (server, client) = setup().await;
Mock::given(method("GET"))
.and(path("/services/data/v60.0/consent/action/email"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"001xx000003GONE": {
"result": "NotFound",
"proceed": {}
}
})))
.mount(&server)
.await;
let result = client
.consent()
.read_consent("email", &["001xx000003GONE"])
.await
.must();
assert_eq!(result["001xx000003GONE"].result, ConsentResult::NotFound);
assert!(result["001xx000003GONE"].proceed.is_empty());
}
#[tokio::test]
async fn test_read_consent_server_error() {
let (server, client) = setup().await;
Mock::given(method("GET"))
.and(path("/services/data/v60.0/consent/action/email"))
.respond_with(ResponseTemplate::new(500))
.mount(&server)
.await;
let result = client
.consent()
.read_consent("email", &["001xx000003GYk1"])
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_read_consent_multi_success() {
let (server, client) = setup().await;
Mock::given(method("GET"))
.and(path("/services/data/v60.0/consent/multiaction"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"001xx000003GYk1": {
"result": "Success",
"proceed": {
"email": "Yes",
"track": "No",
"shouldForget": "No"
}
}
})))
.mount(&server)
.await;
let result = client
.consent()
.read_consent_multi(&["email", "track", "shouldForget"], &["001xx000003GYk1"])
.await
.must();
let record = &result["001xx000003GYk1"];
assert_eq!(record.proceed["email"], ConsentValue::Yes);
assert_eq!(record.proceed["track"], ConsentValue::No);
assert_eq!(record.proceed["shouldForget"], ConsentValue::No);
}
#[tokio::test]
async fn test_read_consent_multi_mixed_results() {
let (server, client) = setup().await;
Mock::given(method("GET"))
.and(path("/services/data/v60.0/consent/multiaction"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"001xx000003GYk1": {
"result": "Success",
"proceed": {"email": "Yes", "track": "Yes"}
},
"001xx000003GYk2": {
"result": "Success",
"proceed": {"email": "No", "track": "No"}
}
})))
.mount(&server)
.await;
let result = client
.consent()
.read_consent_multi(&["email", "track"], &["001xx000003GYk1", "001xx000003GYk2"])
.await
.must();
assert_eq!(result.len(), 2);
assert_eq!(
result["001xx000003GYk1"].proceed["email"],
ConsentValue::Yes
);
assert_eq!(result["001xx000003GYk2"].proceed["email"], ConsentValue::No);
}
#[tokio::test]
async fn test_read_consent_multi_error() {
let (server, client) = setup().await;
Mock::given(method("GET"))
.and(path("/services/data/v60.0/consent/multiaction"))
.respond_with(
ResponseTemplate::new(400).set_body_json(serde_json::json!([{
"message": "Invalid action specified",
"errorCode": "INVALID_ACTION"
}])),
)
.mount(&server)
.await;
let result = client
.consent()
.read_consent_multi(&["invalid_action"], &["001xx000003GYk1"])
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_handler_is_cloneable() {
let (_server, client) = setup().await;
let handler = client.consent();
let cloned = handler.clone();
let debug_original = format!("{handler:?}");
let debug_cloned = format!("{cloned:?}");
assert_eq!(debug_original, debug_cloned);
}
#[tokio::test]
async fn test_handler_is_debug() {
let (_server, client) = setup().await;
let handler = client.consent();
let debug = format!("{handler:?}");
assert!(debug.contains("ConsentHandler"));
}
}