diff options
| author | Vincent Prouillet | 2017-07-19 16:30:01 +0900 |
|---|---|---|
| committer | GitHub | 2017-07-19 16:30:01 +0900 |
| commit | 2ab1a0fa0fe8fe9ccc025cbd7228e6b8201b1f1f (patch) | |
| tree | e71b13aea39c61b19e8aec09468a8e5c4a291e16 /validator_derive/tests | |
| parent | 69e35d6cc905b9d7a894af7e486237e376fae939 (diff) | |
| parent | b31fd25cc5cec96ccee737ba1313c6e9f702f32a (diff) | |
| download | validator-2ab1a0fa0fe8fe9ccc025cbd7228e6b8201b1f1f.tar.bz2 | |
Merge pull request #27 from Keats/revamp
Complete refactor
Diffstat (limited to 'validator_derive/tests')
| -rw-r--r-- | validator_derive/tests/compile-fail/length/wrong_type.rs | 2 | ||||
| -rw-r--r-- | validator_derive/tests/compile-fail/must_match/field_doesnt_exist.rs | 2 | ||||
| -rw-r--r-- | validator_derive/tests/compile-fail/must_match/field_type_doesnt_match.rs | 2 | ||||
| -rw-r--r-- | validator_derive/tests/compile-fail/range/wrong_type.rs | 2 | ||||
| -rw-r--r-- | validator_derive/tests/complex.rs | 155 | ||||
| -rw-r--r-- | validator_derive/tests/contains.rs | 77 | ||||
| -rw-r--r-- | validator_derive/tests/custom.rs | 66 | ||||
| -rw-r--r-- | validator_derive/tests/email.rs | 77 | ||||
| -rw-r--r-- | validator_derive/tests/length.rs | 78 | ||||
| -rw-r--r-- | validator_derive/tests/must_match.rs | 87 | ||||
| -rw-r--r-- | validator_derive/tests/range.rs | 78 | ||||
| -rw-r--r-- | validator_derive/tests/regex.rs | 84 | ||||
| -rw-r--r-- | validator_derive/tests/run-pass/custom.rs | 6 | ||||
| -rw-r--r-- | validator_derive/tests/run-pass/schema.rs | 11 | ||||
| -rw-r--r-- | validator_derive/tests/schema.rs | 99 | ||||
| -rw-r--r-- | validator_derive/tests/test_derive.rs | 357 | ||||
| -rw-r--r-- | validator_derive/tests/url.rs | 77 |
17 files changed, 891 insertions, 369 deletions
diff --git a/validator_derive/tests/compile-fail/length/wrong_type.rs b/validator_derive/tests/compile-fail/length/wrong_type.rs index 365675f..a9d53d4 100644 --- a/validator_derive/tests/compile-fail/length/wrong_type.rs +++ b/validator_derive/tests/compile-fail/length/wrong_type.rs @@ -4,7 +4,7 @@ use validator::Validate; #[derive(Validate)] //~^ ERROR: proc-macro derive panicked -//~^^ HELP: Invalid attribute #[validate] on field `s`: Validator `length` can only be used on types `String`, `&str` or `Vec` but found `usize` +//~^^ HELP: Validator `length` can only be used on types `String`, `&str` or `Vec` but found `usize` struct Test { #[validate(length())] s: usize, diff --git a/validator_derive/tests/compile-fail/must_match/field_doesnt_exist.rs b/validator_derive/tests/compile-fail/must_match/field_doesnt_exist.rs index f3a2347..1ba5319 100644 --- a/validator_derive/tests/compile-fail/must_match/field_doesnt_exist.rs +++ b/validator_derive/tests/compile-fail/must_match/field_doesnt_exist.rs @@ -4,7 +4,7 @@ use validator::Validate; #[derive(Validate)] //~^ ERROR: proc-macro derive panicked -//~^^ HELP: Invalid attribute #[validate] on field `password`: invalid argument for `must_match` validator: field doesn't exist in struct +//~^^ HELP: Invalid argument for `must_match` validator of field `password`: the other field doesn't exist in struct struct Test { #[validate(must_match = "password2")] password: String, diff --git a/validator_derive/tests/compile-fail/must_match/field_type_doesnt_match.rs b/validator_derive/tests/compile-fail/must_match/field_type_doesnt_match.rs index b04a732..580495a 100644 --- a/validator_derive/tests/compile-fail/must_match/field_type_doesnt_match.rs +++ b/validator_derive/tests/compile-fail/must_match/field_type_doesnt_match.rs @@ -4,7 +4,7 @@ use validator::Validate; #[derive(Validate)] //~^ ERROR: proc-macro derive panicked -//~^^ HELP: Invalid attribute #[validate] on field `password`: invalid argument for `must_match` validator: types of field can't match +//~^^ HELP: Invalid argument for `must_match` validator of field `password`: types of field can't match struct Test { #[validate(must_match = "password2")] password: String, diff --git a/validator_derive/tests/compile-fail/range/wrong_type.rs b/validator_derive/tests/compile-fail/range/wrong_type.rs index 239a93d..f6a0a43 100644 --- a/validator_derive/tests/compile-fail/range/wrong_type.rs +++ b/validator_derive/tests/compile-fail/range/wrong_type.rs @@ -6,7 +6,7 @@ use validator::Validate; #[derive(Validate)] //~^ ERROR: proc-macro derive panicked -//~^^ HELP: Invalid attribute #[validate] on field `s`: Validator `range` can only be used on number types but found `String` +//~^^ HELP: Validator `range` can only be used on number types but found `String` struct Test { #[validate(range(min = 10.0, max = 12.0))] s: String, diff --git a/validator_derive/tests/complex.rs b/validator_derive/tests/complex.rs new file mode 100644 index 0000000..db5f1bf --- /dev/null +++ b/validator_derive/tests/complex.rs @@ -0,0 +1,155 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; +#[macro_use] +extern crate serde_derive; +extern crate serde_json; +extern crate regex; +#[macro_use] +extern crate lazy_static; + +use regex::Regex; +use validator::{Validate, ValidationError}; + + +fn validate_unique_username(username: &str) -> Result<(), ValidationError> { + if username == "xXxShad0wxXx" { + return Err(ValidationError::new("terrible_username")); + } + + Ok(()) +} + +fn validate_signup(data: &SignupData) -> Result<(), ValidationError> { + if data.mail.ends_with("gmail.com") && data.age == 18 { + return Err(ValidationError::new("stupid_rule")); + } + + Ok(()) +} + +#[derive(Debug, Validate, Deserialize)] +#[validate(schema(function = "validate_signup", skip_on_field_errors = "false"))] +struct SignupData { + #[validate(email)] + mail: String, + #[validate(url)] + site: String, + #[validate(length(min = "1"), custom = "validate_unique_username")] + #[serde(rename = "firstName")] + first_name: String, + #[validate(range(min = "18", max = "20"))] + age: u32, +} + + +#[test] +fn is_fine_with_many_valid_validations() { + let signup = SignupData { + mail: "bob@bob.com".to_string(), + site: "http://hello.com".to_string(), + first_name: "Bob".to_string(), + age: 18, + }; + + assert!(signup.validate().is_ok()); +} + +#[test] +fn failed_validation_points_to_original_field_name() { + let signup = SignupData { + mail: "bob@bob.com".to_string(), + site: "http://hello.com".to_string(), + first_name: "".to_string(), + age: 18, + }; + let res = signup.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("firstName")); + assert_eq!(errs["firstName"].len(), 1); + assert_eq!(errs["firstName"][0].code, "length"); +} + +#[test] +fn test_can_validate_option_fields_with_lifetime() { + lazy_static! { + static ref RE2: Regex = Regex::new(r"[a-z]{2}").unwrap(); + } + + #[derive(Debug, Validate)] + struct PutStruct<'a> { + #[validate(length(min = "1", max = "10"))] + name: Option<&'a str>, + #[validate(range(min = "1", max = "10"))] + range: Option<usize>, + #[validate(email)] + email: Option<&'a str>, + #[validate(url)] + url: Option<&'a str>, + #[validate(contains = "@")] + text: Option<&'a str>, + #[validate(regex = "RE2")] + re: Option<&'a str>, + #[validate(custom = "check_str")] + custom: Option<&'a str>, + } + + fn check_str(_: &str) -> Result<(), ValidationError> { + Ok(()) + } + + let s = PutStruct { + name: Some("al"), + range: Some(2), + email: Some("hi@gmail.com"), + url: Some("http://google.com"), + text: Some("@someone"), + re: Some("hi"), + custom: Some("hey"), + }; + assert!(s.validate().is_ok()); +} + +#[test] +fn test_can_validate_option_fields_without_lifetime() { + lazy_static! { + static ref RE2: Regex = Regex::new(r"[a-z]{2}").unwrap(); + } + + #[derive(Debug, Validate)] + struct PutStruct { + #[validate(length(min = "1", max = "10"))] + name: Option<String>, + #[validate(length(min = "1", max = "10"))] + ids: Option<Vec<usize>>, + #[validate(range(min = "1", max = "10"))] + range: Option<usize>, + #[validate(email)] + email: Option<String>, + #[validate(url)] + url: Option<String>, + #[validate(contains = "@")] + text: Option<String>, + #[validate(regex = "RE2")] + re: Option<String>, + #[validate(custom = "check_str")] + custom: Option<String>, + } + + fn check_str(_: &str) -> Result<(), ValidationError> { + Ok(()) + } + + let s = PutStruct { + name: Some("al".to_string()), + ids: Some(vec![1, 2, 3]), + range: Some(2), + email: Some("hi@gmail.com".to_string()), + url: Some("http://google.com".to_string()), + text: Some("@someone".to_string()), + re: Some("hi".to_string()), + custom: Some("hey".to_string()), + }; + assert!(s.validate().is_ok()); +} diff --git a/validator_derive/tests/contains.rs b/validator_derive/tests/contains.rs new file mode 100644 index 0000000..847de0f --- /dev/null +++ b/validator_derive/tests/contains.rs @@ -0,0 +1,77 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; + +#[test] +fn can_validate_contains_ok() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(contains = "he")] + val: String, + } + + let s = TestStruct { + val: "hello".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn value_not_containing_needle_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(contains = "he")] + val: String, + } + + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "contains"); + assert_eq!(errs["val"][0].params["value"], ""); + assert_eq!(errs["val"][0].params["needle"], "he"); +} + +#[test] +fn can_specify_code_for_contains() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(contains(pattern = "he", code = "oops"))] + val: String, + } + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); +} + +#[test] +fn can_specify_message_for_contains() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(contains(pattern = "he", message = "oops"))] + val: String, + } + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/custom.rs b/validator_derive/tests/custom.rs new file mode 100644 index 0000000..0cac75f --- /dev/null +++ b/validator_derive/tests/custom.rs @@ -0,0 +1,66 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::{Validate, ValidationError}; + +fn valid_custom_fn(_: &str) -> Result<(), ValidationError> { + Ok(()) +} + +fn invalid_custom_fn(_: &str) -> Result<(), ValidationError> { + Err(ValidationError::new("meh")) +} + +#[test] +fn can_validate_custom_fn_ok() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(custom = "valid_custom_fn")] + val: String, + } + + let s = TestStruct { + val: "hello".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn can_fail_custom_fn_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(custom = "invalid_custom_fn")] + val: String, + } + + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "meh"); + assert_eq!(errs["val"][0].params["value"], ""); +} + +#[test] +fn can_specify_message_for_custom_fn() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(custom(function = "invalid_custom_fn", message = "oops"))] + val: String, + } + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/email.rs b/validator_derive/tests/email.rs new file mode 100644 index 0000000..fc05bf9 --- /dev/null +++ b/validator_derive/tests/email.rs @@ -0,0 +1,77 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; + + +#[test] +fn can_validate_valid_email() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(email)] + val: String, + } + + let s = TestStruct { + val: "bob@bob.com".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn bad_email_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(email)] + val: String, + } + + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "email"); + assert_eq!(errs["val"][0].params["value"], "bob"); +} + +#[test] +fn can_specify_code_for_email() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(email(code = "oops"))] + val: String, + } + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); +} + +#[test] +fn can_specify_message_for_email() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(email(message = "oops"))] + val: String, + } + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/length.rs b/validator_derive/tests/length.rs new file mode 100644 index 0000000..892cf74 --- /dev/null +++ b/validator_derive/tests/length.rs @@ -0,0 +1,78 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; + +#[test] +fn can_validate_length_ok() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(length(min = "5", max = "10"))] + val: String, + } + + let s = TestStruct { + val: "hello".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn value_out_of_length_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(length(min = "5", max = "10"))] + val: String, + } + + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "length"); + assert_eq!(errs["val"][0].params["value"], ""); + assert_eq!(errs["val"][0].params["min"], 5); + assert_eq!(errs["val"][0].params["max"], 10); +} + +#[test] +fn can_specify_code_for_length() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(length(min = "5", max = "10", code = "oops"))] + val: String, + } + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); +} + +#[test] +fn can_specify_message_for_length() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(length(min = "5", max = "10", message = "oops"))] + val: String, + } + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/must_match.rs b/validator_derive/tests/must_match.rs new file mode 100644 index 0000000..038616a --- /dev/null +++ b/validator_derive/tests/must_match.rs @@ -0,0 +1,87 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; + + +#[test] +fn can_validate_valid_must_match() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(must_match = "val2")] + val: String, + val2: String, + } + + let s = TestStruct { + val: "bob".to_string(), + val2: "bob".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn not_matching_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(must_match = "val2")] + val: String, + val2: String, + } + + let s = TestStruct { + val: "bob".to_string(), + val2: "bobby".to_string(), + }; + + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "must_match"); + assert_eq!(errs["val"][0].params["value"], "bob"); + assert_eq!(errs["val"][0].params["other"], "bobby"); +} + +#[test] +fn can_specify_code_for_must_match() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(must_match(other = "val2", code = "oops"))] + val: String, + val2: String, + } + let s = TestStruct { + val: "bob".to_string(), + val2: "bobb".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); +} + +#[test] +fn can_specify_message_for_must_match() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(must_match(other = "val2", message = "oops"))] + val: String, + val2: String, + } + let s = TestStruct { + val: "bob".to_string(), + val2: "bobb".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/range.rs b/validator_derive/tests/range.rs new file mode 100644 index 0000000..2ecd678 --- /dev/null +++ b/validator_derive/tests/range.rs @@ -0,0 +1,78 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; + +#[test] +fn can_validate_range_ok() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(range(min = "5", max = "10"))] + val: usize, + } + + let s = TestStruct { + val: 6, + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn value_out_of_range_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(range(min = "5", max = "10"))] + val: usize, + } + + let s = TestStruct { + val: 11, + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "range"); +} + +#[test] +fn can_specify_code_for_range() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(range(min = "5", max = "10", code = "oops"))] + val: usize, + } + let s = TestStruct { + val: 11, + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); + assert_eq!(errs["val"][0].params["value"], 11); + assert_eq!(errs["val"][0].params["min"], 5f64); + assert_eq!(errs["val"][0].params["max"], 10f64); +} + +#[test] +fn can_specify_message_for_range() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(range(min = "5", max = "10", message = "oops"))] + val: usize, + } + let s = TestStruct { + val: 1, + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/regex.rs b/validator_derive/tests/regex.rs new file mode 100644 index 0000000..58f8f69 --- /dev/null +++ b/validator_derive/tests/regex.rs @@ -0,0 +1,84 @@ +extern crate regex; +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; +use regex::Regex; + +lazy_static! { + static ref RE2: Regex = Regex::new(r"^[a-z]{2}$").unwrap(); +} + +#[test] +fn can_validate_valid_regex() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(regex = "RE2")] + val: String, + } + + let s = TestStruct { + val: "aa".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn bad_value_for_regex_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(regex = "RE2")] + val: String, + } + + let s = TestStruct { + val: "2".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "regex"); + assert_eq!(errs["val"][0].params["value"], "2"); +} + +#[test] +fn can_specify_code_for_regex() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(regex(path = "RE2", code = "oops"))] + val: String, + } + let s = TestStruct { + val: "2".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); +} + +#[test] +fn can_specify_message_for_regex() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(regex(path = "RE2", message = "oops"))] + val: String, + } + let s = TestStruct { + val: "2".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} diff --git a/validator_derive/tests/run-pass/custom.rs b/validator_derive/tests/run-pass/custom.rs index 642b2d2..3a2a396 100644 --- a/validator_derive/tests/run-pass/custom.rs +++ b/validator_derive/tests/run-pass/custom.rs @@ -2,7 +2,7 @@ #[macro_use] extern crate validator_derive; extern crate validator; -use validator::Validate; +use validator::{Validate, ValidationError}; #[derive(Validate)] struct Test { @@ -10,8 +10,8 @@ struct Test { s: String, } -fn validate_something(s: &str) -> Option<String> { - Some(s.to_string()) +fn validate_something(s: &str) -> Result<(), ValidationError> { + Ok(()) } fn main() {} diff --git a/validator_derive/tests/run-pass/schema.rs b/validator_derive/tests/run-pass/schema.rs index 788d1e2..e219698 100644 --- a/validator_derive/tests/run-pass/schema.rs +++ b/validator_derive/tests/run-pass/schema.rs @@ -2,7 +2,7 @@ #[macro_use] extern crate validator_derive; extern crate validator; -use validator::Validate; +use validator::{Validate, ValidationError}; #[derive(Validate)] #[validate(schema(function = "hey"))] @@ -10,8 +10,8 @@ struct Test { s: String, } -fn hey(_: &Test) -> Option<(String, String)> { - None +fn hey(_: &Test) -> Result<(), ValidationError> { + Ok(()) } #[derive(Validate)] @@ -20,8 +20,9 @@ struct Test2 { s: String, } -fn hey2(_: &Test2) -> Option<(String, String)> { - None +fn hey2(_: &Test2) -> Result<(), ValidationError> { + Ok(()) } + fn main() {} diff --git a/validator_derive/tests/schema.rs b/validator_derive/tests/schema.rs new file mode 100644 index 0000000..6b3ae4f --- /dev/null +++ b/validator_derive/tests/schema.rs @@ -0,0 +1,99 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::{Validate, ValidationError}; + + +#[test] +fn can_validate_schema_fn_ok() { + fn valid_schema_fn(_: &TestStruct) -> Result<(), ValidationError> { + Ok(()) +} + + #[derive(Debug, Validate)] + #[validate(schema(function = "valid_schema_fn"))] + struct TestStruct { + val: String, + } + + let s = TestStruct { + val: "hello".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn can_fail_schema_fn_validation() { + fn invalid_schema_fn(_: &TestStruct) -> Result<(), ValidationError> { + Err(ValidationError::new("meh")) + } + + #[derive(Debug, Validate)] + #[validate(schema(function = "invalid_schema_fn"))] + struct TestStruct { + val: String, + } + + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("__all__")); + assert_eq!(errs["__all__"].len(), 1); + assert_eq!(errs["__all__"][0].code, "meh"); +} + +#[test] +fn can_specify_message_for_schema_fn() { + fn invalid_schema_fn(_: &TestStruct) -> Result<(), ValidationError> { + Err(ValidationError::new("meh")) + } + + #[derive(Debug, Validate)] + #[validate(schema(function = "invalid_schema_fn", message = "oops"))] + struct TestStruct { + val: String, + } + let s = TestStruct { + val: String::new(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("__all__")); + assert_eq!(errs["__all__"].len(), 1); + assert_eq!(errs["__all__"][0].clone().message.unwrap(), "oops"); +} + +#[test] +fn can_choose_to_run_schema_validation_even_after_field_errors() { + fn invalid_schema_fn(_: &TestStruct) -> Result<(), ValidationError> { + Err(ValidationError::new("meh")) + } + #[derive(Debug, Validate)] + #[validate(schema(function = "invalid_schema_fn", skip_on_field_errors = "false"))] + struct TestStruct { + val: String, + #[validate(range(min = "1", max = "10"))] + num: usize, + } + + let s = TestStruct { + val: "hello".to_string(), + num: 0, + }; + + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("__all__")); + assert_eq!(errs["__all__"].len(), 1); + assert_eq!(errs["__all__"][0].clone().code, "meh"); + assert!(errs.contains_key("num")); + assert_eq!(errs["num"].len(), 1); + assert_eq!(errs["num"][0].clone().code, "range"); +} diff --git a/validator_derive/tests/test_derive.rs b/validator_derive/tests/test_derive.rs deleted file mode 100644 index 24c408a..0000000 --- a/validator_derive/tests/test_derive.rs +++ /dev/null @@ -1,357 +0,0 @@ -#[macro_use] extern crate validator_derive; -extern crate validator; -#[macro_use] extern crate serde_derive; -extern crate serde_json; -extern crate regex; -#[macro_use] extern crate lazy_static; - -use validator::Validate; -use regex::Regex; - - -#[derive(Debug, Validate, Deserialize)] -#[validate(schema(function = "validate_signup", skip_on_field_errors = "false"))] -struct SignupData { - #[validate(email)] - mail: String, - #[validate(url)] - site: String, - #[validate(length(min = "1"), custom = "validate_unique_username")] - #[serde(rename = "firstName")] - first_name: String, - #[validate(range(min = "18", max = "20"))] - age: u32, -} - -#[derive(Debug, Validate)] -struct PasswordData { - #[validate(must_match = "password2")] - password: String, - password2: String, -} - - -fn validate_unique_username(username: &str) -> Option<String> { - if username == "xXxShad0wxXx" { - return Some("terrible_username".to_string()); - } - - None -} - -fn validate_signup(data: &SignupData) -> Option<(String, String)> { - if data.mail.ends_with("gmail.com") && data.age == 18 { - return Some(("all".to_string(), "stupid_rule".to_string())); - } - - None -} - -#[derive(Debug, Validate, Deserialize)] -#[validate(schema(function = "validate_signup2", skip_on_field_errors = "false"))] -struct SignupData2 { - #[validate(email)] - mail: String, - #[validate(range(min = "18", max = "20"))] - age: u32, -} - -#[derive(Debug, Validate, Deserialize)] -#[validate(schema(function = "validate_signup3"))] -struct SignupData3 { - #[validate(email, contains = "bob")] - mail: String, - #[validate(range(min = "18", max = "20"))] - age: u32, -} - -fn validate_signup2(data: &SignupData2) -> Option<(String, String)> { - if data.mail.starts_with("bob") && data.age == 18 { - return Some(("mail".to_string(), "stupid_rule".to_string())); - } - - None -} - -fn validate_signup3(_: &SignupData3) -> Option<(String, String)> { - Some(("mail".to_string(), "stupid_rule".to_string())) -} - -#[test] -fn test_can_validate_ok() { - let signup = SignupData { - mail: "bob@bob.com".to_string(), - site: "http://hello.com".to_string(), - first_name: "Bob".to_string(), - age: 18, - }; - - assert!(signup.validate().is_ok()); -} - -#[test] -fn test_bad_email_fails_validation() { - let signup = SignupData { - mail: "bob".to_string(), - site: "http://hello.com".to_string(), - first_name: "Bob".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("mail")); - assert_eq!(errs["mail"], vec!["email".to_string()]); -} - -#[test] -fn test_bad_url_fails_validation() { - let signup = SignupData { - mail: "bob@bob.com".to_string(), - site: "//hello.com".to_string(), - first_name: "Bob".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("site")); - assert_eq!(errs["site"], vec!["url".to_string()]); -} - -#[test] -fn test_bad_length_fails_validation_and_points_to_original_name() { - let signup = SignupData { - mail: "bob@bob.com".to_string(), - site: "http://hello.com".to_string(), - first_name: "".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("firstName")); - assert_eq!(errs["firstName"], vec!["length".to_string()]); -} - - -#[test] -fn test_bad_range_fails_validation() { - let signup = SignupData { - mail: "bob@bob.com".to_string(), - site: "https://hello.com".to_string(), - first_name: "Bob".to_string(), - age: 1, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("age")); - assert_eq!(errs["age"], vec!["range".to_string()]); -} - -#[test] -fn test_can_have_multiple_errors() { - let signup = SignupData { - mail: "bob@bob.com".to_string(), - site: "https://hello.com".to_string(), - first_name: "".to_string(), - age: 1, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("age")); - assert!(errs.contains_key("firstName")); - assert_eq!(errs["age"], vec!["range".to_string()]); - assert_eq!(errs["firstName"], vec!["length".to_string()]); -} - -#[test] -fn test_custom_validation_error() { - let signup = SignupData { - mail: "bob@bob.com".to_string(), - site: "https://hello.com".to_string(), - first_name: "xXxShad0wxXx".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("firstName")); - assert_eq!(errs["firstName"], vec!["terrible_username".to_string()]); -} - -#[test] -fn test_must_match_can_work() { - let data = PasswordData { - password: "passw0rd".to_string(), - password2: "passw0rd".to_string(), - }; - assert!(data.validate().is_ok()) -} - - -#[test] -fn test_must_match_can_fail() { - let data = PasswordData { - password: "passw0rd".to_string(), - password2: "password".to_string(), - }; - assert!(data.validate().is_err()) -} - -#[test] -fn test_can_fail_struct_validation_new_key() { - let signup = SignupData { - mail: "bob@gmail.com".to_string(), - site: "https://hello.com".to_string(), - first_name: "xXxShad0wxXx".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("all")); - assert_eq!(errs["all"], vec!["stupid_rule".to_string()]); -} - -#[test] -fn test_can_fail_struct_validation_existing_key() { - let signup = SignupData2 { - mail: "bob".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("mail")); - assert_eq!(errs["mail"], vec!["email".to_string(), "stupid_rule".to_string()]); -} - -#[test] -fn test_skip_struct_validation_by_default_if_errors() { - let signup = SignupData3 { - mail: "bob".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("mail")); - assert_eq!(errs["mail"], vec!["email".to_string()]); -} - -#[test] -fn test_can_fail_contains_validation() { - let signup = SignupData3 { - mail: "bo@gmail.com".to_string(), - age: 18, - }; - let res = signup.validate(); - assert!(res.is_err()); - let errs = res.unwrap_err().inner(); - assert!(errs.contains_key("mail")); - assert_eq!(errs["mail"], vec!["contains".to_string()]); -} - -#[test] -fn test_can_check_regex_validator() { - lazy_static! { - static ref RE: Regex = Regex::new(r"[a-z]{2}").unwrap(); - } - - #[derive(Debug, Validate)] - struct RegexStruct { - #[validate(regex = "RE")] - name: String, - } - let s = RegexStruct {name: "al".to_string()}; - assert!(s.validate().is_ok()); - let s2 = RegexStruct {name: "AL".to_string()}; - assert!(s2.validate().is_err()); -} - - -#[test] -fn test_can_validate_option_fields_with_lifetime() { - lazy_static! { - static ref RE2: Regex = Regex::new(r"[a-z]{2}").unwrap(); - } - - #[derive(Debug, Validate)] - struct PutStruct<'a> { - #[validate(length(min = "1", max = "10"))] - name: Option<&'a str>, - #[validate(range(min = "1", max = "10"))] - range: Option<usize>, - #[validate(email)] - email: Option<&'a str>, - #[validate(url)] - url: Option<&'a str>, - #[validate(contains = "@")] - text: Option<&'a str>, - #[validate(regex = "RE2")] - re: Option<&'a str>, - #[validate(custom = "check_str")] - custom: Option<&'a str>, - } - - fn check_str(_: &str) -> Option<String> { - None - } - - let s = PutStruct { - name: Some("al"), - range: Some(2), - email: Some("hi@gmail.com"), - url: Some("http://google.com"), - text: Some("@someone"), - re: Some("hi"), - custom: Some("hey"), - }; - assert!(s.validate().is_ok()); -} - -#[test] -fn test_can_validate_option_fields_without_lifetime() { - lazy_static! { - static ref RE2: Regex = Regex::new(r"[a-z]{2}").unwrap(); - } - - #[derive(Debug, Validate)] - struct PutStruct { - #[validate(length(min = "1", max = "10"))] - name: Option<String>, - #[validate(length(min = "1", max = "10"))] - ids: Option<Vec<usize>>, - #[validate(range(min = "1", max = "10"))] - range: Option<usize>, - #[validate(email)] - email: Option<String>, - #[validate(url)] - url: Option<String>, - #[validate(contains = "@")] - text: Option<String>, - #[validate(regex = "RE2")] - re: Option<String>, - #[validate(custom = "check_str")] - custom: Option<String>, - } - - fn check_str(_: &str) -> Option<String> { - None - } - - let s = PutStruct { - name: Some("al".to_string()), - ids: Some(vec![1, 2, 3]), - range: Some(2), - email: Some("hi@gmail.com".to_string()), - url: Some("http://google.com".to_string()), - text: Some("@someone".to_string()), - re: Some("hi".to_string()), - custom: Some("hey".to_string()), - }; - assert!(s.validate().is_ok()); -} diff --git a/validator_derive/tests/url.rs b/validator_derive/tests/url.rs new file mode 100644 index 0000000..1182086 --- /dev/null +++ b/validator_derive/tests/url.rs @@ -0,0 +1,77 @@ +#[macro_use] +extern crate validator_derive; +extern crate validator; + +use validator::Validate; + + +#[test] +fn can_validate_url_ok() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(url)] + val: String, + } + + let s = TestStruct { + val: "https://google.com".to_string(), + }; + + assert!(s.validate().is_ok()); +} + +#[test] +fn bad_url_fails_validation() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(url)] + val: String, + } + + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "url"); +} + +#[test] +fn can_specify_code_for_url() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(url(code = "oops"))] + val: String, + } + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].code, "oops"); + assert_eq!(errs["val"][0].params["value"], "bob"); +} + +#[test] +fn can_specify_message_for_url() { + #[derive(Debug, Validate)] + struct TestStruct { + #[validate(url(message = "oops"))] + val: String, + } + let s = TestStruct { + val: "bob".to_string(), + }; + let res = s.validate(); + assert!(res.is_err()); + let errs = res.unwrap_err().inner(); + assert!(errs.contains_key("val")); + assert_eq!(errs["val"].len(), 1); + assert_eq!(errs["val"][0].clone().message.unwrap(), "oops"); +} |
