aboutsummaryrefslogtreecommitdiffstats
path: root/validator_derive/tests
diff options
context:
space:
mode:
authorVincent Prouillet2017-07-19 16:30:01 +0900
committerGitHub2017-07-19 16:30:01 +0900
commit2ab1a0fa0fe8fe9ccc025cbd7228e6b8201b1f1f (patch)
treee71b13aea39c61b19e8aec09468a8e5c4a291e16 /validator_derive/tests
parent69e35d6cc905b9d7a894af7e486237e376fae939 (diff)
parentb31fd25cc5cec96ccee737ba1313c6e9f702f32a (diff)
downloadvalidator-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.rs2
-rw-r--r--validator_derive/tests/compile-fail/must_match/field_doesnt_exist.rs2
-rw-r--r--validator_derive/tests/compile-fail/must_match/field_type_doesnt_match.rs2
-rw-r--r--validator_derive/tests/compile-fail/range/wrong_type.rs2
-rw-r--r--validator_derive/tests/complex.rs155
-rw-r--r--validator_derive/tests/contains.rs77
-rw-r--r--validator_derive/tests/custom.rs66
-rw-r--r--validator_derive/tests/email.rs77
-rw-r--r--validator_derive/tests/length.rs78
-rw-r--r--validator_derive/tests/must_match.rs87
-rw-r--r--validator_derive/tests/range.rs78
-rw-r--r--validator_derive/tests/regex.rs84
-rw-r--r--validator_derive/tests/run-pass/custom.rs6
-rw-r--r--validator_derive/tests/run-pass/schema.rs11
-rw-r--r--validator_derive/tests/schema.rs99
-rw-r--r--validator_derive/tests/test_derive.rs357
-rw-r--r--validator_derive/tests/url.rs77
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");
+}