use async_trait::async_trait;
use mockito::{Matcher, Mock};
use prima_bridge::{prelude::*, RedirectPolicy};
use reqwest::Url;
#[allow(unused)]
pub fn enable_mockito_logging() {
std::env::set_var("RUST_LOG", "mockito=debug");
}
#[async_trait]
pub trait MockitoServerCreateBridgeExt {
async fn create_bridge(&mut self, status_code: usize, body: &str) -> (Mock, Bridge);
async fn create_bridge_with_base_and_path(
&mut self,
status_code: usize,
body: &str,
base: &str,
path: &str,
) -> (Mock, Bridge);
async fn create_bridge_with_path(&mut self, status_code: usize, body: &str, path: &str) -> (Mock, Bridge);
async fn create_bridge_with_path_and_header(
&mut self,
status_code: usize,
body: &str,
path: &str,
header: (&str, &str),
) -> (Mock, Bridge);
async fn create_bridge_with_raw_body_matcher(&mut self, body: &str) -> (Mock, Bridge);
async fn create_bridge_with_header_matcher(&mut self, name_value: (&str, &str)) -> (Mock, Bridge);
async fn create_bridge_with_user_agent(&mut self, user_agent: &str) -> (Mock, Bridge);
async fn create_bridge_with_json_body_matcher(&mut self, json: serde_json::Value) -> (Mock, Bridge);
async fn create_bridge_with_binary_body_matcher(&mut self, body: &[u8]) -> (Mock, Bridge);
async fn create_bridge_with_redirect(
&mut self,
status_code: usize,
body: &str,
path: &str,
redirect_to: &str,
policy: RedirectPolicy,
) -> (Mock, Bridge);
}
#[async_trait]
impl MockitoServerCreateBridgeExt for mockito::Server {
async fn create_bridge(&mut self, status_code: usize, body: &str) -> (Mock, Bridge) {
self.create_bridge_with_path(status_code, body, "/").await
}
async fn create_bridge_with_base_and_path(
&mut self,
status_code: usize,
body: &str,
base: &str,
path: &str,
) -> (Mock, Bridge) {
let mock = self
.mock("GET", format!("/{base}/{path}").as_str())
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.with_status(status_code)
.with_body(body)
.create_async()
.await;
let base_url = format!("{}/{}", self.url(), base);
let url = Url::parse(base_url.as_str()).unwrap();
let bridge = Bridge::builder().build(url);
(mock, bridge)
}
async fn create_bridge_with_path(&mut self, status_code: usize, body: &str, path: &str) -> (Mock, Bridge) {
let mock = self
.mock("GET", path)
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.with_status(status_code)
.with_body(body)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().build(url);
(mock, bridge)
}
async fn create_bridge_with_path_and_header(
&mut self,
status_code: usize,
body: &str,
path: &str,
header: (&str, &str),
) -> (Mock, Bridge) {
let mock = self
.mock("GET", path)
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.with_status(status_code)
.with_header(header.0, header.1)
.with_body(body)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().build(url);
(mock, bridge)
}
async fn create_bridge_with_raw_body_matcher(&mut self, body: &str) -> (Mock, Bridge) {
let mock = self
.mock("GET", "/")
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.match_body(Matcher::Exact(body.to_owned()))
.with_status(200)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().build(url);
(mock, bridge)
}
async fn create_bridge_with_header_matcher(&mut self, (name, value): (&str, &str)) -> (Mock, Bridge) {
let mock = self
.mock("GET", "/")
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.match_header(name, value)
.with_status(200)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().build(url);
(mock, bridge)
}
async fn create_bridge_with_user_agent(&mut self, user_agent: &str) -> (Mock, Bridge) {
let mock = self
.mock("GET", "/")
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.match_header("User-Agent", user_agent)
.with_status(200)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().with_user_agent(user_agent).build(url);
(mock, bridge)
}
async fn create_bridge_with_json_body_matcher(&mut self, json: serde_json::Value) -> (Mock, Bridge) {
let mock = self
.mock("GET", "/")
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.match_body(Matcher::Json(json))
.with_status(200)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().build(url);
(mock, bridge)
}
async fn create_bridge_with_binary_body_matcher(&mut self, body: &[u8]) -> (Mock, Bridge) {
let mock = self
.mock("GET", "/")
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.match_body(Matcher::from(body.to_vec()))
.with_status(200)
.with_body(body)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().build(url);
(mock, bridge)
}
async fn create_bridge_with_redirect(
&mut self,
status_code: usize,
body: &str,
path: &str,
redirect_to: &str,
policy: RedirectPolicy,
) -> (Mock, Bridge) {
let mock = self
.mock("GET", path)
.match_header(
"x-request-id",
Matcher::Regex(r"\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b".to_string()),
)
.with_status(status_code)
.with_header("Location", redirect_to)
.with_body(body)
.create_async()
.await;
let url = Url::parse(self.url().as_str()).unwrap();
let bridge = Bridge::builder().with_redirect_policy(policy).build(url);
(mock, bridge)
}
}