#![allow(dead_code)]
use std::collections::HashMap;
use serde_json::Value;
#[derive(Debug, Clone)]
pub struct TestResult {
pub test_name: String,
pub success: bool,
pub details: String,
}
impl TestResult {
pub fn success(test_name: impl Into<String>, details: impl Into<String>) -> Self {
Self { test_name: test_name.into(), success: true, details: details.into() }
}
pub fn failure(test_name: impl Into<String>, details: impl Into<String>) -> Self {
Self { test_name: test_name.into(), success: false, details: details.into() }
}
}
#[derive(Debug, Clone)]
pub struct ApiResponse {
pub status_code: u16,
pub body: String,
}
impl ApiResponse {
pub fn is_success(&self) -> bool {
(200..300).contains(&self.status_code)
}
pub fn json_value(&self) -> Result<Value, serde_json::Error> {
serde_json::from_str(&self.body)
}
}
pub struct ApiTest {
entity_name: String,
base_url: String,
client: reqwest::Client,
}
impl ApiTest {
pub fn new(entity_name: &str, base_url: &str) -> Self {
Self {
entity_name: entity_name.to_string(),
base_url: base_url.trim_end_matches('/').to_string(),
client: reqwest::Client::new(),
}
}
fn url(&self, path: &str) -> String {
format!("{}{}", self.base_url, path)
}
async fn send(
&self,
req: reqwest::RequestBuilder,
headers: Option<HashMap<String, String>>,
) -> Result<ApiResponse, reqwest::Error> {
let mut req = req;
if let Some(hs) = headers {
for (k, v) in hs {
req = req.header(k, v);
}
}
let resp = req.send().await?;
let status_code = resp.status().as_u16();
let body = resp.text().await.unwrap_or_default();
Ok(ApiResponse { status_code, body })
}
pub async fn get(&self, path: &str, headers: Option<HashMap<String, String>>) -> Result<ApiResponse, reqwest::Error> {
self.send(self.client.get(self.url(path)), headers).await
}
pub async fn post(&self, path: &str, body: &Value, headers: Option<HashMap<String, String>>) -> Result<ApiResponse, reqwest::Error> {
self.send(self.client.post(self.url(path)).json(body), headers).await
}
pub async fn put(&self, path: &str, body: &Value, headers: Option<HashMap<String, String>>) -> Result<ApiResponse, reqwest::Error> {
self.send(self.client.put(self.url(path)).json(body), headers).await
}
pub async fn delete(&self, path: &str, headers: Option<HashMap<String, String>>) -> Result<ApiResponse, reqwest::Error> {
self.send(self.client.delete(self.url(path)), headers).await
}
pub fn create_result(&self, test_name: &str, response: &ApiResponse, expected_status: u16, success_msg: &str) -> TestResult {
if response.status_code == expected_status {
TestResult::success(test_name, success_msg)
} else {
let snippet: String = response.body.chars().take(200).collect();
TestResult::failure(
test_name,
format!(
"[{}] expected HTTP {}, got {} (body: {})",
self.entity_name, expected_status, response.status_code, snippet
),
)
}
}
}