use qubit_common::StringArgument;
use regex::Regex;
#[test]
fn non_blank() {
let result = "hello".require_non_blank("s");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "hello");
assert!(" ".require_non_blank("s").is_err());
let s = String::from("world");
let result2 = s.require_non_blank("s");
assert!(result2.is_ok());
assert_eq!(result2.unwrap(), "world");
let err = "".require_non_blank("empty");
assert!(err.is_err());
let err_msg = err.unwrap_err();
assert!(err_msg.to_string().contains("empty"));
let err2 = " \t ".require_non_blank("whitespace");
assert!(err2.is_err());
let empty_string = String::from("");
assert!(empty_string.require_non_blank("s").is_err());
}
#[test]
fn length_checks_and_range() {
let r1 = "abc".require_length_be("s", 3);
assert!(r1.is_ok());
assert_eq!(r1.unwrap(), "abc");
let err1 = "abc".require_length_be("s", 2);
assert!(err1.is_err());
let err_msg1 = err1.unwrap_err();
assert!(err_msg1.to_string().contains("s"));
let s = String::from("test");
let err1b = s.require_length_be("s", 5);
assert!(err1b.is_err());
let r2 = "abc".require_length_at_least("s", 3);
assert!(r2.is_ok());
assert_eq!(r2.unwrap(), "abc");
let err2 = "ab".require_length_at_least("s", 3);
assert!(err2.is_err());
let err_msg2 = err2.unwrap_err();
assert!(err_msg2.to_string().contains("at least"));
let s2 = String::from("x");
let err2b = s2.require_length_at_least("s", 5);
assert!(err2b.is_err());
let r3 = "abc".require_length_at_most("s", 3);
assert!(r3.is_ok());
assert_eq!(r3.unwrap(), "abc");
let err3 = "abcd".require_length_at_most("s", 3);
assert!(err3.is_err());
let err_msg3 = err3.unwrap_err();
assert!(err_msg3.to_string().contains("at most"));
let s3 = String::from("toolong");
let err3b = s3.require_length_at_most("s", 3);
assert!(err3b.is_err());
let r4 = "abcd".require_length_in_range("s", 3, 5);
assert!(r4.is_ok());
assert_eq!(r4.unwrap(), "abcd");
let err4a = "ab".require_length_in_range("s", 3, 5);
assert!(err4a.is_err());
let err4b = "abcdef".require_length_in_range("s", 3, 5);
assert!(err4b.is_err());
let err_msg4b = err4b.unwrap_err();
assert!(err_msg4b.to_string().contains("range"));
let s4 = String::from("verylongstring");
let err4c = s4.require_length_in_range("s", 1, 5);
assert!(err4c.is_err());
}
#[test]
fn regex_match_and_not_match() {
let email_re = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
let r1 = "user@example.com".require_match("email", &email_re);
assert!(r1.is_ok());
assert_eq!(r1.unwrap(), "user@example.com");
let err1 = "bad@com".require_match("email", &email_re);
assert!(err1.is_err());
let err_msg1 = err1.unwrap_err();
assert!(err_msg1.to_string().contains("email"));
assert!(err_msg1.to_string().contains("match"));
let s = String::from("invalid");
let err1b = s.require_match("email", &email_re);
assert!(err1b.is_err());
let digits = Regex::new(r"^\d+$").unwrap();
let r2 = "abc".require_not_match("id", &digits);
assert!(r2.is_ok());
assert_eq!(r2.unwrap(), "abc");
let err2 = "123".require_not_match("id", &digits);
assert!(err2.is_err());
let err_msg2 = err2.unwrap_err();
assert!(err_msg2.to_string().contains("id"));
assert!(err_msg2.to_string().contains("cannot match"));
let s2 = String::from("456");
let err2b = s2.require_not_match("id", &digits);
assert!(err2b.is_err());
}
#[test]
fn multibyte_strings_len_is_bytes() {
let han = "汉"; assert!(han.require_length_be("c", 3).is_ok());
assert!(han.require_length_be("c", 1).is_err());
let emoji = "😀"; assert!(emoji.require_length_be("e", 4).is_ok());
assert!(emoji.require_length_in_range("e", 4, 4).is_ok());
}
#[test]
fn test_empty_string() {
assert!("".require_non_blank("empty").is_err());
assert!("".require_length_be("empty", 0).is_ok());
assert!("".require_length_at_least("empty", 0).is_ok());
assert!("".require_length_at_most("empty", 0).is_ok());
assert!("".require_length_at_most("empty", 10).is_ok());
}
#[test]
fn test_whitespace_only() {
assert!(" ".require_non_blank("spaces").is_err());
assert!("\t".require_non_blank("tab").is_err());
assert!("\n".require_non_blank("newline").is_err());
assert!(" \t\n ".require_non_blank("mixed").is_err());
}
#[test]
fn test_string_type() {
let s = String::from("hello");
assert!(s.require_non_blank("string").is_ok());
assert!(s.require_length_be("string", 5).is_ok());
assert!(s.require_length_at_least("string", 3).is_ok());
assert!(s.require_length_at_most("string", 10).is_ok());
assert!(s.require_length_in_range("string", 3, 10).is_ok());
}
#[test]
fn test_regex_edge_cases() {
let any = Regex::new(r".*").unwrap();
assert!("anything".require_match("any", &any).is_ok());
assert!("".require_match("empty", &any).is_ok());
let none = Regex::new(r"^$").unwrap();
assert!("".require_match("empty", &none).is_ok());
assert!("x".require_match("not_empty", &none).is_err());
assert!("abc".require_not_match("text", &none).is_ok());
assert!("".require_not_match("empty", &none).is_err());
}
#[test]
fn test_length_boundary() {
let text = "12345";
assert!(text.require_length_be("text", 5).is_ok());
assert!(text.require_length_at_least("text", 5).is_ok());
assert!(text.require_length_at_most("text", 5).is_ok());
assert!(text.require_length_in_range("text", 5, 5).is_ok());
assert!(text.require_length_be("text", 6).is_err());
assert!(text.require_length_at_most("text", 4).is_err());
assert!(text.require_length_at_least("text", 6).is_err());
}
#[test]
fn test_chaining() {
let username = "alice";
let result = username
.require_non_blank("username")
.and_then(|u| u.require_length_at_least("username", 3))
.and_then(|u| u.require_length_at_most("username", 20));
assert!(result.is_ok());
let short = "ab";
let result = short
.require_non_blank("username")
.and_then(|u| u.require_length_at_least("username", 3));
assert!(result.is_err());
}
#[test]
fn test_special_characters() {
let special = "hello@world#123";
assert!(special.require_non_blank("special").is_ok());
assert!(special.require_length_be("special", 15).is_ok());
let pattern = Regex::new(r"[a-z@#0-9]+").unwrap();
assert!(special.require_match("special", &pattern).is_ok());
}
#[test]
fn test_very_long_string() {
let long = "a".repeat(1000);
assert!(long.require_non_blank("long").is_ok());
assert!(long.require_length_be("long", 1000).is_ok());
assert!(long.require_length_at_least("long", 500).is_ok());
assert!(long.require_length_at_most("long", 2000).is_ok());
assert!(long.require_length_in_range("long", 500, 2000).is_ok());
}
#[test]
fn test_all_success_branches_for_str() {
let text = "hello";
assert!(text.require_non_blank("text").is_ok());
assert_eq!(text.require_non_blank("text").unwrap(), "hello");
assert!(text.require_length_be("text", 5).is_ok());
assert_eq!(text.require_length_be("text", 5).unwrap(), "hello");
assert!(text.require_length_at_least("text", 5).is_ok());
assert_eq!(text.require_length_at_least("text", 5).unwrap(), "hello");
assert!(text.require_length_at_least("text", 3).is_ok());
assert!(text.require_length_at_most("text", 5).is_ok());
assert_eq!(text.require_length_at_most("text", 5).unwrap(), "hello");
assert!(text.require_length_at_most("text", 10).is_ok());
assert!(text.require_length_in_range("text", 3, 7).is_ok());
assert_eq!(text.require_length_in_range("text", 3, 7).unwrap(), "hello");
assert!(text.require_length_in_range("text", 5, 5).is_ok());
use regex::Regex;
let pattern = Regex::new(r"^[a-z]+$").unwrap();
assert!(text.require_match("text", &pattern).is_ok());
assert_eq!(text.require_match("text", &pattern).unwrap(), "hello");
let digit_pattern = Regex::new(r"\d").unwrap();
assert!(text.require_not_match("text", &digit_pattern).is_ok());
assert_eq!(
text.require_not_match("text", &digit_pattern).unwrap(),
"hello"
);
}
#[test]
fn test_all_success_branches_for_string() {
let text = String::from("world");
assert!(text.require_non_blank("text").is_ok());
assert_eq!(text.require_non_blank("text").unwrap(), "world");
assert!(text.require_length_be("text", 5).is_ok());
assert_eq!(text.require_length_be("text", 5).unwrap(), "world");
assert!(text.require_length_at_least("text", 5).is_ok());
assert_eq!(text.require_length_at_least("text", 5).unwrap(), "world");
assert!(text.require_length_at_least("text", 3).is_ok());
assert!(text.require_length_at_most("text", 5).is_ok());
assert_eq!(text.require_length_at_most("text", 5).unwrap(), "world");
assert!(text.require_length_at_most("text", 10).is_ok());
assert!(text.require_length_in_range("text", 3, 7).is_ok());
assert_eq!(text.require_length_in_range("text", 3, 7).unwrap(), "world");
assert!(text.require_length_in_range("text", 5, 5).is_ok());
use regex::Regex;
let pattern = Regex::new(r"^[a-z]+$").unwrap();
assert!(text.require_match("text", &pattern).is_ok());
assert_eq!(text.require_match("text", &pattern).unwrap(), "world");
let digit_pattern = Regex::new(r"\d").unwrap();
assert!(text.require_not_match("text", &digit_pattern).is_ok());
assert_eq!(
text.require_not_match("text", &digit_pattern).unwrap(),
"world"
);
}
#[test]
fn test_length_in_range_min_boundary() {
let text = "abc";
assert!(text.require_length_in_range("text", 3, 10).is_ok());
assert!(text.require_length_in_range("text", 4, 10).is_err());
}
#[test]
fn test_length_in_range_max_boundary() {
let text = "abcde";
assert!(text.require_length_in_range("text", 1, 5).is_ok());
assert!(text.require_length_in_range("text", 1, 4).is_err());
let text2 = String::from("abcdef");
assert!(text2.require_length_in_range("text", 1, 5).is_err());
}
#[test]
fn test_length_in_range_both_boundaries() {
let text = "abc";
let result = text.require_length_in_range("text", 5, 10);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("must be in"));
let text2 = "abcdefghijk";
let result2 = text2.require_length_in_range("text", 1, 5);
assert!(result2.is_err());
let text3 = String::from("ab");
assert!(text3.require_length_in_range("text", 5, 10).is_err());
let text4 = String::from("abcdefghijk");
assert!(text4.require_length_in_range("text", 1, 5).is_err());
}