1pub mod database;
36pub mod client;
37pub mod factories;
38pub mod assertions;
39pub mod auth;
40pub mod performance;
41
42pub use database::{TestDatabase, DatabaseTransaction};
44pub use client::{TestClient, TestResponse};
45pub use factories::{Factory, FactoryBuilder};
46pub use assertions::TestAssertions;
47
48pub mod prelude {
50 pub use crate::{
51 database::{TestDatabase, DatabaseTransaction},
52 client::{TestClient, TestResponse},
53 factories::{Factory, FactoryBuilder},
54 assertions::TestAssertions,
55 utils,
56 };
57
58 pub use serde_json::{json, Value as JsonValue};
60 pub use uuid::Uuid;
61 pub use chrono::{DateTime, Utc};
62
63}
64
65#[derive(thiserror::Error, Debug)]
67pub enum TestError {
68 #[error("Database error: {0}")]
69 Database(#[from] sqlx::Error),
70
71 #[error("Serialization error: {0}")]
72 Serialization(#[from] serde_json::Error),
73
74 #[error("Factory error: {message}")]
75 Factory { message: String },
76
77 #[error("Assertion failed: {message}")]
78 Assertion { message: String },
79
80 #[error("Authentication error: {0}")]
81 Authentication(String),
82
83 #[error("Test setup error: {0}")]
84 Setup(String),
85}
86
87pub type TestResult<T> = Result<T, TestError>;
88
89pub mod utils {
91
92 pub fn random_string(prefix: Option<&str>) -> String {
94 use rand::Rng;
95 let suffix: String = rand::thread_rng()
96 .sample_iter(&rand::distributions::Alphanumeric)
97 .take(8)
98 .map(char::from)
99 .collect();
100
101 match prefix {
102 Some(p) => format!("{}_{}", p, suffix),
103 None => suffix,
104 }
105 }
106
107 pub fn random_email() -> String {
109 format!("test_{}@example.com", random_string(None).to_lowercase())
110 }
111
112 pub fn test_uuid() -> uuid::Uuid {
114 uuid::Uuid::new_v4()
115 }
116
117 pub fn test_timestamp() -> chrono::DateTime<chrono::Utc> {
119 chrono::Utc::now()
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use crate::utils;
126
127 #[test]
128 fn test_random_string_generation() {
129 let s1 = utils::random_string(None);
130 let s2 = utils::random_string(None);
131
132 assert_eq!(s1.len(), 8);
133 assert_ne!(s1, s2);
134 }
135
136 #[test]
137 fn test_random_string_with_prefix() {
138 let s = utils::random_string(Some("test"));
139 assert!(s.starts_with("test_"));
140 assert!(s.len() > 5);
141 }
142
143 #[test]
144 fn test_random_email_format() {
145 let email = utils::random_email();
146 assert!(email.contains("@example.com"));
147 assert!(email.starts_with("test_"));
148 }
149
150 #[test]
151 fn test_uuid_generation() {
152 let uuid1 = utils::test_uuid();
153 let uuid2 = utils::test_uuid();
154 assert_ne!(uuid1, uuid2);
155 }
156}