1use std::collections::HashMap;
38
39use crate::request::{Body, HttpVersion, Method, Request};
40use crate::response::{Response, ResponseBody, StatusCode};
41
42#[derive(Debug, Clone)]
64pub struct RequestFactory {
65 method: Method,
66 path: String,
67 query: Option<String>,
68 version: HttpVersion,
69 headers: Vec<(String, Vec<u8>)>,
70 body: Option<Vec<u8>>,
71}
72
73impl RequestFactory {
74 #[must_use]
76 pub fn new(method: Method, path: impl Into<String>) -> Self {
77 Self {
78 method,
79 path: path.into(),
80 query: None,
81 version: HttpVersion::Http11,
82 headers: Vec::new(),
83 body: None,
84 }
85 }
86
87 #[must_use]
89 pub fn get(path: impl Into<String>) -> Self {
90 Self::new(Method::Get, path)
91 }
92
93 #[must_use]
95 pub fn post(path: impl Into<String>) -> Self {
96 Self::new(Method::Post, path)
97 }
98
99 #[must_use]
101 pub fn put(path: impl Into<String>) -> Self {
102 Self::new(Method::Put, path)
103 }
104
105 #[must_use]
107 pub fn delete(path: impl Into<String>) -> Self {
108 Self::new(Method::Delete, path)
109 }
110
111 #[must_use]
113 pub fn patch(path: impl Into<String>) -> Self {
114 Self::new(Method::Patch, path)
115 }
116
117 #[must_use]
119 pub fn options(path: impl Into<String>) -> Self {
120 Self::new(Method::Options, path)
121 }
122
123 #[must_use]
125 pub fn head(path: impl Into<String>) -> Self {
126 Self::new(Method::Head, path)
127 }
128
129 #[must_use]
131 pub fn query(mut self, query: impl Into<String>) -> Self {
132 self.query = Some(query.into());
133 self
134 }
135
136 #[must_use]
138 pub fn query_params<I, K, V>(mut self, params: I) -> Self
139 where
140 I: IntoIterator<Item = (K, V)>,
141 K: AsRef<str>,
142 V: AsRef<str>,
143 {
144 let query: String = params
145 .into_iter()
146 .map(|(k, v)| format!("{}={}", k.as_ref(), v.as_ref()))
147 .collect::<Vec<_>>()
148 .join("&");
149 self.query = Some(query);
150 self
151 }
152
153 #[must_use]
155 pub fn version(mut self, version: HttpVersion) -> Self {
156 self.version = version;
157 self
158 }
159
160 #[must_use]
162 pub fn header(mut self, name: impl Into<String>, value: impl Into<Vec<u8>>) -> Self {
163 self.headers.push((name.into(), value.into()));
164 self
165 }
166
167 #[must_use]
169 pub fn content_type(self, content_type: impl AsRef<str>) -> Self {
170 self.header("Content-Type", content_type.as_ref().as_bytes().to_vec())
171 }
172
173 #[must_use]
175 pub fn accept(self, accept: impl AsRef<str>) -> Self {
176 self.header("Accept", accept.as_ref().as_bytes().to_vec())
177 }
178
179 #[must_use]
181 pub fn bearer_token(self, token: impl AsRef<str>) -> Self {
182 self.header(
183 "Authorization",
184 format!("Bearer {}", token.as_ref()).into_bytes(),
185 )
186 }
187
188 #[must_use]
190 pub fn basic_auth(self, username: impl AsRef<str>, password: impl AsRef<str>) -> Self {
191 use std::io::Write;
192 let mut encoded = Vec::new();
193 let _ = write!(
194 &mut encoded,
195 "Basic {}",
196 base64_encode(&format!("{}:{}", username.as_ref(), password.as_ref()))
197 );
198 self.header("Authorization", encoded)
199 }
200
201 #[must_use]
203 pub fn api_key(self, key: impl AsRef<str>) -> Self {
204 self.header("X-API-Key", key.as_ref().as_bytes().to_vec())
205 }
206
207 #[must_use]
209 pub fn body(mut self, body: impl Into<Vec<u8>>) -> Self {
210 self.body = Some(body.into());
211 self
212 }
213
214 #[must_use]
216 pub fn json<T: serde::Serialize>(self, value: &T) -> Self {
217 let json = serde_json::to_vec(value).unwrap_or_default();
218 self.content_type("application/json").body(json)
219 }
220
221 #[must_use]
223 pub fn form<I, K, V>(self, fields: I) -> Self
224 where
225 I: IntoIterator<Item = (K, V)>,
226 K: AsRef<str>,
227 V: AsRef<str>,
228 {
229 let body: String = fields
230 .into_iter()
231 .map(|(k, v)| {
232 format!(
233 "{}={}",
234 urlencoding_simple(k.as_ref()),
235 urlencoding_simple(v.as_ref())
236 )
237 })
238 .collect::<Vec<_>>()
239 .join("&");
240 self.content_type("application/x-www-form-urlencoded")
241 .body(body.into_bytes())
242 }
243
244 #[must_use]
246 pub fn text(self, text: impl AsRef<str>) -> Self {
247 self.content_type("text/plain")
248 .body(text.as_ref().as_bytes().to_vec())
249 }
250
251 #[must_use]
253 pub fn build(self) -> Request {
254 let mut req = Request::with_version(self.method, self.path, self.version);
255 req.set_query(self.query);
256
257 for (name, value) in self.headers {
258 req.headers_mut().insert(name, value);
259 }
260
261 if let Some(body) = self.body {
262 if !body.is_empty() {
263 req.headers_mut()
264 .insert("Content-Length", body.len().to_string().into_bytes());
265 }
266 req.set_body(Body::Bytes(body));
267 }
268
269 req
270 }
271}
272
273#[derive(Debug, Clone)]
298pub struct ResponseFactory {
299 status: StatusCode,
300 headers: Vec<(String, Vec<u8>)>,
301 body: Option<Vec<u8>>,
302}
303
304impl ResponseFactory {
305 #[must_use]
307 pub fn new(status: StatusCode) -> Self {
308 Self {
309 status,
310 headers: Vec::new(),
311 body: None,
312 }
313 }
314
315 #[must_use]
317 pub fn ok() -> Self {
318 Self::new(StatusCode::OK)
319 }
320
321 #[must_use]
323 pub fn created() -> Self {
324 Self::new(StatusCode::CREATED)
325 }
326
327 #[must_use]
329 pub fn no_content() -> Self {
330 Self::new(StatusCode::NO_CONTENT)
331 }
332
333 #[must_use]
335 pub fn moved_permanently(location: impl AsRef<str>) -> Self {
336 Self::new(StatusCode::MOVED_PERMANENTLY)
337 .header("Location", location.as_ref().as_bytes().to_vec())
338 }
339
340 #[must_use]
342 pub fn found(location: impl AsRef<str>) -> Self {
343 Self::new(StatusCode::FOUND).header("Location", location.as_ref().as_bytes().to_vec())
344 }
345
346 #[must_use]
348 pub fn bad_request() -> Self {
349 Self::new(StatusCode::BAD_REQUEST)
350 }
351
352 #[must_use]
354 pub fn unauthorized() -> Self {
355 Self::new(StatusCode::UNAUTHORIZED)
356 }
357
358 #[must_use]
360 pub fn forbidden() -> Self {
361 Self::new(StatusCode::FORBIDDEN)
362 }
363
364 #[must_use]
366 pub fn not_found() -> Self {
367 Self::new(StatusCode::NOT_FOUND)
368 }
369
370 #[must_use]
372 pub fn unprocessable_entity() -> Self {
373 Self::new(StatusCode::UNPROCESSABLE_ENTITY)
374 }
375
376 #[must_use]
378 pub fn internal_server_error() -> Self {
379 Self::new(StatusCode::INTERNAL_SERVER_ERROR)
380 }
381
382 #[must_use]
384 pub fn status(mut self, status: StatusCode) -> Self {
385 self.status = status;
386 self
387 }
388
389 #[must_use]
391 pub fn header(mut self, name: impl Into<String>, value: impl Into<Vec<u8>>) -> Self {
392 self.headers.push((name.into(), value.into()));
393 self
394 }
395
396 #[must_use]
398 pub fn content_type(self, content_type: impl AsRef<str>) -> Self {
399 self.header("Content-Type", content_type.as_ref().as_bytes().to_vec())
400 }
401
402 #[must_use]
404 pub fn body(mut self, body: impl Into<Vec<u8>>) -> Self {
405 self.body = Some(body.into());
406 self
407 }
408
409 #[must_use]
411 pub fn json<T: serde::Serialize>(self, value: &T) -> Self {
412 let json = serde_json::to_vec(value).unwrap_or_default();
413 self.content_type("application/json").body(json)
414 }
415
416 #[must_use]
418 pub fn text(self, text: impl AsRef<str>) -> Self {
419 self.content_type("text/plain")
420 .body(text.as_ref().as_bytes().to_vec())
421 }
422
423 #[must_use]
425 pub fn html(self, html: impl AsRef<str>) -> Self {
426 self.content_type("text/html")
427 .body(html.as_ref().as_bytes().to_vec())
428 }
429
430 #[must_use]
432 pub fn build(self) -> Response {
433 let mut resp = Response::with_status(self.status);
434
435 for (name, value) in self.headers {
436 resp = resp.header(name, value);
437 }
438
439 if let Some(body) = self.body {
440 resp = resp.body(ResponseBody::Bytes(body));
441 }
442
443 resp
444 }
445}
446
447pub struct AuthFactory;
471
472impl AuthFactory {
473 #[must_use]
475 pub fn bearer_token() -> String {
476 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U".to_string()
478 }
479
480 #[must_use]
482 pub fn api_key() -> String {
483 "sk_test_abcdefghijklmnopqrstuvwxyz123456".to_string()
484 }
485
486 #[must_use]
488 pub fn session_id() -> String {
489 "sess_abcdef123456789012345678901234567890".to_string()
490 }
491
492 #[must_use]
494 pub fn refresh_token() -> String {
495 "rt_abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGH".to_string()
496 }
497
498 #[must_use]
500 pub fn jwt_token() -> JwtFactory {
501 JwtFactory::new()
502 }
503
504 #[must_use]
506 pub fn basic_credentials() -> (String, String) {
507 ("testuser".to_string(), "testpass123".to_string())
508 }
509
510 #[must_use]
512 pub fn oauth_code() -> String {
513 "authcode_abcdefghijklmnopqrstuvwxyz123456".to_string()
514 }
515}
516
517#[derive(Debug, Clone, Default)]
519pub struct JwtFactory {
520 sub: Option<String>,
521 iat: Option<u64>,
522 exp: Option<u64>,
523 iss: Option<String>,
524 aud: Option<String>,
525 custom: HashMap<String, String>,
526}
527
528impl JwtFactory {
529 #[must_use]
531 pub fn new() -> Self {
532 Self::default()
533 }
534
535 #[must_use]
537 #[allow(clippy::should_implement_trait)]
538 pub fn sub(mut self, sub: impl Into<String>) -> Self {
539 self.sub = Some(sub.into());
540 self
541 }
542
543 #[must_use]
545 pub fn iat(mut self, iat: u64) -> Self {
546 self.iat = Some(iat);
547 self
548 }
549
550 #[must_use]
552 pub fn exp(mut self, exp: u64) -> Self {
553 self.exp = Some(exp);
554 self
555 }
556
557 #[must_use]
559 pub fn iss(mut self, iss: impl Into<String>) -> Self {
560 self.iss = Some(iss.into());
561 self
562 }
563
564 #[must_use]
566 pub fn aud(mut self, aud: impl Into<String>) -> Self {
567 self.aud = Some(aud.into());
568 self
569 }
570
571 #[must_use]
573 pub fn claim(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
574 self.custom.insert(key.into(), value.into());
575 self
576 }
577
578 #[must_use]
582 pub fn build(self) -> String {
583 let mut claims = serde_json::Map::new();
585
586 if let Some(sub) = self.sub {
587 claims.insert("sub".into(), serde_json::Value::String(sub));
588 }
589 if let Some(iat) = self.iat {
590 claims.insert("iat".into(), serde_json::Value::Number(iat.into()));
591 }
592 if let Some(exp) = self.exp {
593 claims.insert("exp".into(), serde_json::Value::Number(exp.into()));
594 }
595 if let Some(iss) = self.iss {
596 claims.insert("iss".into(), serde_json::Value::String(iss));
597 }
598 if let Some(aud) = self.aud {
599 claims.insert("aud".into(), serde_json::Value::String(aud));
600 }
601 for (k, v) in self.custom {
602 claims.insert(k, serde_json::Value::String(v));
603 }
604
605 let header = base64_encode(r#"{"alg":"HS256","typ":"JWT"}"#);
606 let payload = base64_encode(&serde_json::to_string(&claims).unwrap_or_default());
607 let signature = "test_signature_not_valid";
608
609 format!("{header}.{payload}.{signature}")
610 }
611}
612
613pub struct JsonFactory;
640
641impl JsonFactory {
642 #[must_use]
644 pub fn object() -> JsonObjectFactory {
645 JsonObjectFactory::new()
646 }
647
648 #[must_use]
650 pub fn array() -> JsonArrayFactory {
651 JsonArrayFactory::new()
652 }
653
654 #[must_use]
656 pub fn malformed() -> Vec<u8> {
657 b"{\"key\": \"value\"".to_vec()
658 }
659
660 #[must_use]
662 pub fn trailing_comma() -> Vec<u8> {
663 b"{\"key\": \"value\",}".to_vec()
664 }
665
666 #[must_use]
668 pub fn single_quotes() -> Vec<u8> {
669 b"{'key': 'value'}".to_vec()
670 }
671
672 #[must_use]
674 pub fn unquoted_keys() -> Vec<u8> {
675 b"{key: \"value\"}".to_vec()
676 }
677
678 #[must_use]
680 pub fn empty_object() -> Vec<u8> {
681 b"{}".to_vec()
682 }
683
684 #[must_use]
686 pub fn empty_array() -> Vec<u8> {
687 b"[]".to_vec()
688 }
689
690 #[must_use]
692 pub fn null() -> Vec<u8> {
693 b"null".to_vec()
694 }
695}
696
697#[derive(Debug, Clone, Default)]
699pub struct JsonObjectFactory {
700 fields: Vec<(String, serde_json::Value)>,
701}
702
703impl JsonObjectFactory {
704 #[must_use]
706 pub fn new() -> Self {
707 Self::default()
708 }
709
710 #[must_use]
712 pub fn string(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
713 self.fields
714 .push((key.into(), serde_json::Value::String(value.into())));
715 self
716 }
717
718 #[must_use]
720 pub fn number(mut self, key: impl Into<String>, value: i64) -> Self {
721 self.fields
722 .push((key.into(), serde_json::Value::Number(value.into())));
723 self
724 }
725
726 #[must_use]
728 pub fn float(mut self, key: impl Into<String>, value: f64) -> Self {
729 if let Some(n) = serde_json::Number::from_f64(value) {
730 self.fields.push((key.into(), serde_json::Value::Number(n)));
731 }
732 self
733 }
734
735 #[must_use]
737 pub fn bool(mut self, key: impl Into<String>, value: bool) -> Self {
738 self.fields
739 .push((key.into(), serde_json::Value::Bool(value)));
740 self
741 }
742
743 #[must_use]
745 pub fn null(mut self, key: impl Into<String>) -> Self {
746 self.fields.push((key.into(), serde_json::Value::Null));
747 self
748 }
749
750 #[must_use]
752 pub fn object(mut self, key: impl Into<String>, factory: JsonObjectFactory) -> Self {
753 let map: serde_json::Map<String, serde_json::Value> = factory.fields.into_iter().collect();
754 self.fields
755 .push((key.into(), serde_json::Value::Object(map)));
756 self
757 }
758
759 #[must_use]
761 pub fn array(mut self, key: impl Into<String>, factory: JsonArrayFactory) -> Self {
762 self.fields
763 .push((key.into(), serde_json::Value::Array(factory.items)));
764 self
765 }
766
767 #[must_use]
769 pub fn build(self) -> Vec<u8> {
770 let map: serde_json::Map<String, serde_json::Value> = self.fields.into_iter().collect();
771 serde_json::to_vec(&map).unwrap_or_default()
772 }
773
774 #[must_use]
776 pub fn build_value(self) -> serde_json::Value {
777 let map: serde_json::Map<String, serde_json::Value> = self.fields.into_iter().collect();
778 serde_json::Value::Object(map)
779 }
780}
781
782#[derive(Debug, Clone, Default)]
784pub struct JsonArrayFactory {
785 items: Vec<serde_json::Value>,
786}
787
788impl JsonArrayFactory {
789 #[must_use]
791 pub fn new() -> Self {
792 Self::default()
793 }
794
795 #[must_use]
797 pub fn push_string(mut self, value: impl Into<String>) -> Self {
798 self.items.push(serde_json::Value::String(value.into()));
799 self
800 }
801
802 #[must_use]
804 pub fn push_number(mut self, value: i64) -> Self {
805 self.items.push(serde_json::Value::Number(value.into()));
806 self
807 }
808
809 #[must_use]
811 pub fn push_bool(mut self, value: bool) -> Self {
812 self.items.push(serde_json::Value::Bool(value));
813 self
814 }
815
816 #[must_use]
818 pub fn push_null(mut self) -> Self {
819 self.items.push(serde_json::Value::Null);
820 self
821 }
822
823 #[must_use]
825 pub fn push_object(mut self, factory: JsonObjectFactory) -> Self {
826 self.items.push(factory.build_value());
827 self
828 }
829
830 #[must_use]
832 pub fn build(self) -> Vec<u8> {
833 serde_json::to_vec(&self.items).unwrap_or_default()
834 }
835}
836
837#[derive(Debug, Clone, Default)]
854pub struct UserFactory {
855 id: Option<i64>,
856 email: Option<String>,
857 name: Option<String>,
858 role: Option<String>,
859 active: Option<bool>,
860}
861
862impl UserFactory {
863 #[must_use]
865 pub fn new() -> Self {
866 Self::default()
867 }
868
869 #[must_use]
871 pub fn id(mut self, id: i64) -> Self {
872 self.id = Some(id);
873 self
874 }
875
876 #[must_use]
878 pub fn email(mut self, email: impl Into<String>) -> Self {
879 self.email = Some(email.into());
880 self
881 }
882
883 #[must_use]
885 pub fn name(mut self, name: impl Into<String>) -> Self {
886 self.name = Some(name.into());
887 self
888 }
889
890 #[must_use]
892 pub fn role(mut self, role: impl Into<String>) -> Self {
893 self.role = Some(role.into());
894 self
895 }
896
897 #[must_use]
899 pub fn active(mut self, active: bool) -> Self {
900 self.active = Some(active);
901 self
902 }
903
904 #[must_use]
906 pub fn admin() -> Self {
907 Self::new()
908 .id(1)
909 .email("admin@example.com")
910 .name("Admin User")
911 .role("admin")
912 .active(true)
913 }
914
915 #[must_use]
917 pub fn regular() -> Self {
918 Self::new()
919 .id(2)
920 .email("user@example.com")
921 .name("Regular User")
922 .role("user")
923 .active(true)
924 }
925
926 #[must_use]
928 pub fn inactive() -> Self {
929 Self::new()
930 .id(3)
931 .email("inactive@example.com")
932 .name("Inactive User")
933 .role("user")
934 .active(false)
935 }
936
937 #[must_use]
939 pub fn build(self) -> Vec<u8> {
940 let mut map = serde_json::Map::new();
941
942 if let Some(id) = self.id {
943 map.insert("id".into(), serde_json::Value::Number(id.into()));
944 }
945 if let Some(email) = self.email {
946 map.insert("email".into(), serde_json::Value::String(email));
947 }
948 if let Some(name) = self.name {
949 map.insert("name".into(), serde_json::Value::String(name));
950 }
951 if let Some(role) = self.role {
952 map.insert("role".into(), serde_json::Value::String(role));
953 }
954 if let Some(active) = self.active {
955 map.insert("active".into(), serde_json::Value::Bool(active));
956 }
957
958 serde_json::to_vec(&map).unwrap_or_default()
959 }
960
961 #[must_use]
963 pub fn build_value(self) -> serde_json::Value {
964 serde_json::from_slice(&self.build()).unwrap_or(serde_json::Value::Null)
965 }
966}
967
968pub struct CommonFixtures;
974
975impl CommonFixtures {
976 pub const TEST_EMAIL: &'static str = "test@example.com";
978
979 pub const TEST_PHONE: &'static str = "+1234567890";
981
982 pub const TEST_URL: &'static str = "https://example.com";
984
985 pub const TEST_UUID: &'static str = "550e8400-e29b-41d4-a716-446655440000";
987
988 pub const TEST_DATE: &'static str = "2025-01-15";
990
991 pub const TEST_DATETIME: &'static str = "2025-01-15T10:30:00Z";
993
994 pub const TEST_IPV4: &'static str = "192.168.1.1";
996
997 pub const TEST_IPV6: &'static str = "::1";
999}
1000
1001fn base64_encode(input: &str) -> String {
1007 const ALPHABET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1008
1009 let bytes = input.as_bytes();
1010 let mut result = String::new();
1011
1012 for chunk in bytes.chunks(3) {
1013 let b = match chunk.len() {
1014 1 => [chunk[0], 0, 0],
1015 2 => [chunk[0], chunk[1], 0],
1016 _ => [chunk[0], chunk[1], chunk[2]],
1017 };
1018
1019 let n = (u32::from(b[0]) << 16) | (u32::from(b[1]) << 8) | u32::from(b[2]);
1020
1021 result.push(ALPHABET[((n >> 18) & 63) as usize] as char);
1022 result.push(ALPHABET[((n >> 12) & 63) as usize] as char);
1023
1024 if chunk.len() > 1 {
1025 result.push(ALPHABET[((n >> 6) & 63) as usize] as char);
1026 } else {
1027 result.push('=');
1028 }
1029
1030 if chunk.len() > 2 {
1031 result.push(ALPHABET[(n & 63) as usize] as char);
1032 } else {
1033 result.push('=');
1034 }
1035 }
1036
1037 result
1038}
1039
1040fn urlencoding_simple(s: &str) -> String {
1042 let mut result = String::with_capacity(s.len() * 3);
1043 for c in s.chars() {
1044 match c {
1045 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' | '.' | '~' => result.push(c),
1046 ' ' => result.push('+'),
1047 _ => {
1048 for byte in c.to_string().as_bytes() {
1049 result.push_str(&format!("%{byte:02X}"));
1050 }
1051 }
1052 }
1053 }
1054 result
1055}
1056
1057#[cfg(test)]
1058mod tests {
1059 use super::*;
1060
1061 #[test]
1062 fn test_request_factory_get() {
1063 let req = RequestFactory::get("/users").build();
1064 assert_eq!(req.method(), Method::Get);
1065 assert_eq!(req.path(), "/users");
1066 }
1067
1068 #[test]
1069 fn test_request_factory_post_json() {
1070 let data = serde_json::json!({"name": "Alice"});
1071 let req = RequestFactory::post("/users").json(&data).build();
1072
1073 assert_eq!(req.method(), Method::Post);
1074 assert!(req.headers().get("content-type").is_some());
1075 }
1076
1077 #[test]
1078 fn test_request_factory_with_auth() {
1079 let req = RequestFactory::get("/protected")
1080 .bearer_token("token123")
1081 .build();
1082
1083 let auth = req.headers().get("authorization").unwrap();
1084 assert!(std::str::from_utf8(auth).unwrap().starts_with("Bearer "));
1085 }
1086
1087 #[test]
1088 fn test_request_factory_query_params() {
1089 let req = RequestFactory::get("/search")
1090 .query_params([("q", "rust"), ("limit", "10")])
1091 .build();
1092
1093 assert_eq!(req.query(), Some("q=rust&limit=10"));
1094 }
1095
1096 #[test]
1097 fn test_response_factory_ok() {
1098 let resp = ResponseFactory::ok().build();
1099 assert_eq!(resp.status(), StatusCode::OK);
1100 }
1101
1102 #[test]
1103 fn test_response_factory_not_found_json() {
1104 let body = serde_json::json!({"error": "Not found"});
1105 let resp = ResponseFactory::not_found().json(&body).build();
1106
1107 assert_eq!(resp.status(), StatusCode::NOT_FOUND);
1108 }
1109
1110 #[test]
1111 fn test_auth_factory_tokens() {
1112 let bearer = AuthFactory::bearer_token();
1113 assert!(!bearer.is_empty());
1114
1115 let api_key = AuthFactory::api_key();
1116 assert!(api_key.starts_with("sk_test_"));
1117
1118 let session = AuthFactory::session_id();
1119 assert!(session.starts_with("sess_"));
1120 }
1121
1122 #[test]
1123 fn test_jwt_factory() {
1124 let token = JwtFactory::new().sub("user123").iss("test-issuer").build();
1125
1126 let parts: Vec<_> = token.split('.').collect();
1127 assert_eq!(parts.len(), 3);
1128 }
1129
1130 #[test]
1131 fn test_json_factory_object() {
1132 let json = JsonFactory::object()
1133 .string("name", "Alice")
1134 .number("age", 30)
1135 .bool("active", true)
1136 .build();
1137
1138 let parsed: serde_json::Value = serde_json::from_slice(&json).unwrap();
1139 assert_eq!(parsed["name"], "Alice");
1140 assert_eq!(parsed["age"], 30);
1141 assert_eq!(parsed["active"], true);
1142 }
1143
1144 #[test]
1145 fn test_json_factory_array() {
1146 let json = JsonArrayFactory::new()
1147 .push_number(1)
1148 .push_number(2)
1149 .push_number(3)
1150 .build();
1151
1152 let parsed: Vec<i64> = serde_json::from_slice(&json).unwrap();
1153 assert_eq!(parsed, vec![1, 2, 3]);
1154 }
1155
1156 #[test]
1157 fn test_json_factory_malformed() {
1158 let malformed = JsonFactory::malformed();
1159 assert!(serde_json::from_slice::<serde_json::Value>(&malformed).is_err());
1160 }
1161
1162 #[test]
1163 fn test_user_factory() {
1164 let user = UserFactory::admin().build();
1165 let parsed: serde_json::Value = serde_json::from_slice(&user).unwrap();
1166
1167 assert_eq!(parsed["role"], "admin");
1168 assert_eq!(parsed["active"], true);
1169 }
1170
1171 #[test]
1172 fn test_common_fixtures() {
1173 assert!(CommonFixtures::TEST_EMAIL.contains('@'));
1174 assert!(CommonFixtures::TEST_UUID.contains('-'));
1175 }
1176
1177 #[test]
1178 fn test_base64_encode() {
1179 assert_eq!(base64_encode("hello"), "aGVsbG8=");
1180 assert_eq!(base64_encode("a"), "YQ==");
1181 }
1182}