quorum_public/tests/
common.rs1use crate::startup;
2use quorum_core::utility::config::Config;
3use serde_json::json;
4use std::time::Duration;
5
6static CLIENT: std::sync::OnceLock<reqwest::Client> = std::sync::OnceLock::new();
7
8#[allow(clippy::redundant_closure)]
9fn get_client() -> &'static reqwest::Client {
10 CLIENT.get_or_init(|| reqwest::Client::new())
11}
12
13pub async fn make_auth_request(
14 endpoint: &str,
15 payload: &serde_json::Value,
16 expected_status: u16,
17) -> Result<serde_json::Value, String> {
18 let client = get_client();
19 let server_url = Config::get().server_url.clone();
20
21 let response = client
23 .post(format!("{}{}", server_url, endpoint))
24 .json(payload)
25 .send()
26 .await
27 .map_err(|e| format!("Request failed: {}", e))?;
28
29 let status = response.status().as_u16();
30 let body: serde_json::Value = response
31 .json()
32 .await
33 .map_err(|e| format!("Failed to parse response: {}", e))?;
34
35 if status != expected_status {
36 let error_msg = body["message"].as_str().unwrap_or("Unknown error");
37 return Err(format!(
38 "Expected {}, got {} - {}",
39 expected_status, status, error_msg
40 ));
41 }
42
43 if body["success"] != true {
44 return Err(format!("Request failed: {}", body["message"]));
45 }
46
47 Ok(body)
48}
49
50pub async fn make_auth_request_raw(
51 endpoint: &str,
52 payload: &serde_json::Value,
53 expected_status: u16,
54) -> Result<serde_json::Value, String> {
55 let client = get_client();
56 let server_url = Config::get().server_url.clone();
57
58 let response = client
59 .post(format!("{}{}", server_url, endpoint))
60 .json(payload)
61 .send()
62 .await
63 .map_err(|e| format!("Request failed: {}", e))?;
64
65 let status = response.status().as_u16();
66 let body: serde_json::Value = response
67 .json()
68 .await
69 .map_err(|e| format!("Failed to parse response: {}", e))?;
70
71 if status != expected_status {
72 let error_msg = body["message"].as_str().unwrap_or("Unknown error");
73 return Err(format!(
74 "Expected {}, got {} - {}",
75 expected_status, status, error_msg
76 ));
77 }
78
79 Ok(body)
80}
81
82pub fn get_test_username() -> String {
83 use rand::RngExt;
84 use std::time::{SystemTime, UNIX_EPOCH};
85 let timestamp = SystemTime::now()
86 .duration_since(UNIX_EPOCH)
87 .unwrap()
88 .as_millis();
89 let random: u32 = rand::rng().random_range(0..10000);
90 format!("t{}_{}", timestamp % 1000000, random)
91}
92
93pub async fn cleanup_user(username: &str, password: &str, user_id: &str) -> Result<(), String> {
94 make_auth_request(
95 "/auth/delete",
96 &json!({
97 "username_or_email": username,
98 "password": password,
99 "user_id": user_id
100 }),
101 200,
102 )
103 .await?;
104 Ok(())
105}
106
107pub struct TestUserTimings {
108 pub signup: Duration,
109 pub login: Duration,
110}
111
112pub async fn create_test_user(
113 password: &str,
114 email: bool,
115 clean_up: bool,
116) -> Result<(String, String, String, TestUserTimings), String> {
117 let username = get_test_username();
118
119 let signup_timer = startup::create_timer();
120 let mut payload = json!({
121 "username": username,
122 "password": password
123 });
124 if email {
125 payload["email"] = json!(format!("{}@example.com", username));
126 }
127 make_auth_request("/auth/signup", &payload, 201).await?;
128 let signup_time = signup_timer.elapsed();
129
130 let login_timer = startup::create_timer();
131 let login_body = make_auth_request(
132 "/auth/login",
133 &json!({
134 "username_or_email": username,
135 "password": password
136 }),
137 200,
138 )
139 .await?;
140 let login_time = login_timer.elapsed();
141
142 let user_id = login_body["user"]["id"]
143 .as_str()
144 .ok_or("Failed to get user ID")?
145 .to_string();
146
147 if clean_up {
148 let _ = cleanup_user(&username, password, &user_id).await;
149 }
150
151 Ok((
152 username,
153 password.to_string(),
154 user_id,
155 TestUserTimings {
156 signup: signup_time,
157 login: login_time,
158 },
159 ))
160}