Skip to main content

quorum_public/tests/
mod.rs

1mod common;
2mod functional;
3mod robust;
4
5use colored::*;
6use futures::future::BoxFuture;
7use quorum_core::startup;
8use std::time::Duration;
9
10// 1. Define Type Aliases to dramatically simplify the code
11type FunctionalTestFn = fn() -> BoxFuture<'static, Result<TestResult, String>>;
12type RobustnessTestFn = fn() -> BoxFuture<'static, Result<RobustnessTestResult, String>>;
13
14pub struct TestResult {
15    pub endpoint_time: Duration,
16}
17
18pub struct RobustnessTestResult {
19    pub endpoint_time: Duration,
20}
21
22pub async fn run_all_tests() {
23    println!("\n{}", "Running Tests...".yellow().bold());
24
25    run_functional_tests().await;
26    run_robust_tests().await;
27}
28
29async fn run_functional_tests() {
30    println!("\n{}", "Running Functional Tests...".cyan().bold());
31
32    let tests: Vec<(&str, FunctionalTestFn)> = vec![
33        ("Auth signup with email + password test", || {
34            Box::pin(functional::auth_tests::test_signup_email())
35        }),
36        ("Auth signup with username + password test", || {
37            Box::pin(functional::auth_tests::test_signup_username())
38        }),
39        ("Auth login with email test", || {
40            Box::pin(functional::auth_tests::test_login_email())
41        }),
42        ("Auth login with username test", || {
43            Box::pin(functional::auth_tests::test_login_username())
44        }),
45        ("Auth refresh token test", || {
46            Box::pin(functional::auth_tests::test_refresh_token())
47        }),
48        ("Auth logout test", || {
49            Box::pin(functional::auth_tests::test_logout())
50        }),
51        ("Auth delete user account with email test", || {
52            Box::pin(functional::auth_tests::test_delete_user_account_email())
53        }),
54        ("Auth delete user account with username test", || {
55            Box::pin(functional::auth_tests::test_delete_user_account_username())
56        }),
57        ("Auth update user profile test", || {
58            Box::pin(functional::auth_tests::test_update_user_profile())
59        }),
60    ];
61
62    run_test_suite(&tests).await;
63}
64
65async fn run_robust_tests() {
66    println!("\n{}", "Running Robustness Tests...".magenta().bold());
67
68    let tests: Vec<(&str, RobustnessTestFn)> = vec![
69        ("Signup with short username", || {
70            Box::pin(robust::auth_tests::test_signup_short_username())
71        }),
72        ("Signup with long username", || {
73            Box::pin(robust::auth_tests::test_signup_long_username())
74        }),
75        ("Signup with empty password", || {
76            Box::pin(robust::auth_tests::test_signup_empty_password())
77        }),
78        ("Signup with short password", || {
79            Box::pin(robust::auth_tests::test_signup_short_password())
80        }),
81        ("Signup with long password", || {
82            Box::pin(robust::auth_tests::test_signup_long_password())
83        }),
84        ("Signup with invalid email", || {
85            Box::pin(robust::auth_tests::test_signup_invalid_email())
86        }),
87        ("Signup with duplicate username", || {
88            Box::pin(robust::auth_tests::test_signup_duplicate_username())
89        }),
90        ("Login with wrong password", || {
91            Box::pin(robust::auth_tests::test_login_wrong_password())
92        }),
93        ("Login with nonexistent user", || {
94            Box::pin(robust::auth_tests::test_login_nonexistent_user())
95        }),
96        ("Login with empty username", || {
97            Box::pin(robust::auth_tests::test_login_empty_username())
98        }),
99        ("Refresh with invalid token", || {
100            Box::pin(robust::auth_tests::test_refresh_invalid_token())
101        }),
102        ("Refresh with empty token", || {
103            Box::pin(robust::auth_tests::test_refresh_empty_token())
104        }),
105        ("Delete with wrong password", || {
106            Box::pin(robust::auth_tests::test_delete_wrong_password())
107        }),
108        ("Get user data with wrong password", || {
109            Box::pin(robust::auth_tests::test_get_user_data_wrong_password())
110        }),
111        ("Logout with invalid token", || {
112            Box::pin(robust::auth_tests::test_logout_invalid_token())
113        }),
114        ("Updating profile username with an empty field", || {
115            Box::pin(robust::auth_tests::test_update_profile_empty_username())
116        }),
117    ];
118
119    run_robustness_suite(&tests).await;
120}
121
122async fn run_test_suite(tests: &[(&str, FunctionalTestFn)]) {
123    let mut failed_tests = Vec::new();
124
125    for (i, (test_name, test_fn)) in tests.iter().enumerate() {
126        let timer = startup::create_timer();
127        let is_last = i == tests.len() - 1;
128
129        match test_fn().await {
130            Ok(result) => {
131                if is_last {
132                    startup::print_final_step(test_name, true, result.endpoint_time);
133                } else {
134                    startup::print_step(test_name, true, result.endpoint_time);
135                }
136            }
137            Err(e) => {
138                let elapsed = startup::elapsed(timer);
139                if is_last {
140                    startup::print_final_step(test_name, false, elapsed);
141                } else {
142                    startup::print_step(test_name, false, elapsed);
143                }
144                failed_tests.push((test_name.to_string(), e));
145            }
146        }
147    }
148
149    if !failed_tests.is_empty() {
150        println!(
151            "\n{}",
152            format!("{} test(s) failed:", failed_tests.len())
153                .red()
154                .bold()
155        );
156        for (name, error) in &failed_tests {
157            println!("{}", format!("  ✗ {}", name).red());
158            let error_lines: Vec<&str> = error.lines().collect();
159            for (idx, line) in error_lines.iter().enumerate() {
160                if idx == error_lines.len() - 1 {
161                    println!("    {} {}", "└─".red(), line.dimmed());
162                } else {
163                    println!("    {} {}", "├─".red(), line.dimmed());
164                }
165            }
166        }
167    }
168}
169
170// Cleaned up function signature
171async fn run_robustness_suite(tests: &[(&str, RobustnessTestFn)]) {
172    let mut issue_tests = Vec::new();
173
174    for (i, (test_name, test_fn)) in tests.iter().enumerate() {
175        let timer = startup::create_timer();
176        let is_last = i == tests.len() - 1;
177
178        match test_fn().await {
179            Ok(result) => {
180                if is_last {
181                    startup::print_final_step(test_name, true, result.endpoint_time);
182                } else {
183                    startup::print_step(test_name, true, result.endpoint_time);
184                }
185            }
186            Err(e) => {
187                let elapsed = startup::elapsed(timer);
188                if is_last {
189                    startup::print_final_step(test_name, false, elapsed);
190                } else {
191                    startup::print_step(test_name, false, elapsed);
192                }
193                issue_tests.push((test_name.to_string(), e));
194            }
195        }
196    }
197
198    if !issue_tests.is_empty() {
199        println!(
200            "\n{}",
201            format!("{} test(s) with unexpected behavior:", issue_tests.len())
202                .yellow()
203                .bold()
204        );
205        for (name, error) in &issue_tests {
206            println!("{}", format!("  ⚠ {}", name).yellow());
207            let error_lines: Vec<&str> = error.lines().collect();
208            for (idx, line) in error_lines.iter().enumerate() {
209                if idx == error_lines.len() - 1 {
210                    println!("    {} {}", "└─".yellow(), line.dimmed());
211                } else {
212                    println!("    {} {}", "├─".yellow(), line.dimmed());
213                }
214            }
215        }
216    }
217}