use serde_json::Value;
use valico::json_dsl;
use valico::json_dsl::errors;
use valico::json_schema;
use valico::json_schema::errors as schema_errors;
use self::helpers::{
assert_error, assert_error_with_scope, assert_str_eq, assert_str_eq_with_scope,
};
mod helpers;
#[test]
fn is_process_empty_builder() {
let params = json_dsl::Builder::build(|_params| {});
assert_str_eq(¶ms, r#"{"a":1}"#, r#"{"a":1}"#);
}
#[test]
fn is_process_simple_require() {
let params = json_dsl::Builder::build(|params| {
params.req_defined("a");
});
assert_str_eq(¶ms, r#"{"a":1}"#, r#"{"a":1}"#);
assert_error::<errors::Required>(¶ms, r#"{}"#, "/a");
}
#[test]
fn is_process_i64_require() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::i64());
});
assert_str_eq(¶ms, r#"{"a":"1"}"#, r#"{"a":1}"#);
assert_str_eq(¶ms, r#"{"a": 1.112}"#, r#"{"a":1}"#);
assert_error::<errors::WrongType>(¶ms, r#"{"a": "not-int"}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a": {"a": 1}}"#, "/a");
}
#[test]
fn is_process_string_require() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::string());
});
assert_str_eq(¶ms, r#"{"a":"1"}"#, r#"{"a":"1"}"#);
assert_str_eq(¶ms, r#"{"a":1}"#, r#"{"a":"1"}"#);
assert_str_eq(¶ms, r#"{"a":1.112}"#, r#"{"a":"1.112"}"#);
assert_error::<errors::WrongType>(¶ms, r#"{"a": {}}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a": null}"#, "/a");
}
#[test]
fn is_process_boolean_require() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::boolean());
});
assert_str_eq(¶ms, r#"{"a":true}"#, r#"{"a":true}"#);
assert_str_eq(¶ms, r#"{"a":false}"#, r#"{"a":false}"#);
assert_str_eq(¶ms, r#"{"a":"true"}"#, r#"{"a":true}"#);
assert_str_eq(¶ms, r#"{"a":"false"}"#, r#"{"a":false}"#);
assert_error::<errors::WrongType>(¶ms, r#"{"a": null}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a": 1}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a": "not-bool"}"#, "/a");
}
#[test]
fn is_process_simple_array_require() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::array());
});
assert_str_eq(¶ms, r#"{"a":[1,"2",[3]]}"#, r#"{"a":[1,"2",[3]]}"#);
assert_error::<errors::WrongType>(¶ms, r#"{"a": {}}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a": "test"}"#, "/a");
}
#[test]
fn is_process_typed_array_require() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::array_of(json_dsl::string()));
});
assert_str_eq(¶ms, r#"{"a":[1,"2",3.1]}"#, r#"{"a":["1","2","3.1"]}"#);
assert_error::<errors::WrongType>(¶ms, r#"{"a": {}}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a": [1,2,{}]}"#, "/a/2");
}
#[test]
fn is_process_array_with_nested_require() {
let params = json_dsl::Builder::build(|params| {
params.req_nested("a", json_dsl::array(), |params| {
params.req_typed("b", json_dsl::string());
params.req_typed("c", json_dsl::array_of(json_dsl::u64()))
});
});
assert_str_eq(
¶ms,
r#"{"a":[{"b":1,"c":["1"]}]}"#,
r#"{"a":[{"b":"1","c":[1]}]}"#,
);
assert_error::<errors::WrongType>(¶ms, r#"{"a":[{"b":{},"c":["1"]}]}"#, "/a/0/b");
assert_error::<errors::WrongType>(¶ms, r#"{"a":[{"b":1,"c":[{}]}]}"#, "/a/0/c/0");
}
#[test]
fn it_process_encoded_array() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::encoded_array(","));
});
assert_str_eq(¶ms, r#"{"a":"a,b,c"}"#, r#"{"a":["a","b","c"]}"#);
}
#[test]
fn it_process_encoded_array_of_type() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::encoded_array_of(",", json_dsl::u64()));
});
assert_str_eq(¶ms, r#"{"a":"1,2,3"}"#, r#"{"a":[1,2,3]}"#);
}
#[test]
fn is_process_object_require() {
let params = json_dsl::Builder::build(|params| {
params.req_typed("a", json_dsl::object());
});
assert_str_eq(¶ms, r#"{"a":{}}"#, r#"{"a":{}}"#);
assert_error::<errors::WrongType>(¶ms, r#"{"a":[]}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a":""}"#, "/a");
}
#[test]
fn is_process_object_with_nested_require() {
let params = json_dsl::Builder::build(|params| {
params.req_nested("a", json_dsl::object(), |params| {
params.req_typed("b", json_dsl::f64());
params.req_typed("c", json_dsl::array_of(json_dsl::string()));
});
});
assert_str_eq(
¶ms,
r#"{"a":{"b":"1.22","c":[1.112,""]}}"#,
r#"{"a":{"b":1.22,"c":["1.112",""]}}"#,
);
assert_error::<errors::WrongType>(¶ms, r#"{"a":{"b":"not-f64"},"c":[1.112,""]}"#, "/a/b");
assert_error::<errors::WrongType>(¶ms, r#"{"a":{"b":"1.22","c":[1.112,{}]}}"#, "/a/c/1");
}
#[test]
fn is_process_require_allows_null() {
let params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::string());
})
});
assert_error::<errors::WrongType>(¶ms, r#"{"a":null}"#, "/a");
let params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::string());
a.allow_null();
})
});
assert_str_eq(¶ms, r#"{"a":null}"#, r#"{"a":null}"#);
}
#[test]
fn is_validates_allow_values() {
let params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::string());
a.allow_values(&["allowed1".to_string(), "allowed2".to_string()])
})
});
assert_str_eq(¶ms, r#"{"a":"allowed1"}"#, r#"{"a":"allowed1"}"#);
assert_str_eq(¶ms, r#"{"a":"allowed2"}"#, r#"{"a":"allowed2"}"#);
assert_error::<errors::WrongValue>(¶ms, r#"{"a":"not in allowed"}"#, "/a");
}
#[test]
fn is_validates_reject_values() {
let params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::string());
a.reject_values(&["rejected1".to_string(), "rejected2".to_string()])
})
});
assert_str_eq(¶ms, r#"{"a":"some"}"#, r#"{"a":"some"}"#);
assert_error::<errors::WrongValue>(¶ms, r#"{"a":"rejected1"}"#, "/a");
assert_error::<errors::WrongValue>(¶ms, r#"{"a":"rejected2"}"#, "/a");
}
#[test]
fn is_validates_with_function_validator() {
let params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::u64());
a.validate_with(|val: &Value, path: &str| {
if *val == json!(2) {
Ok(())
} else {
Err(vec![Box::new(errors::WrongType {
path: path.to_string(),
detail: "Value is not exactly 2".to_string(),
})])
}
});
})
});
assert_str_eq(¶ms, r#"{"a":"2"}"#, r#"{"a":2}"#);
assert_error::<errors::WrongType>(¶ms, r#"{"a":3}"#, "/a");
assert_error::<errors::WrongType>(¶ms, r#"{"a":"3"}"#, "/a");
}
#[test]
#[allow(clippy::trivial_regex)]
fn is_validates_with_regex() {
let params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::string());
a.regex(regex::Regex::new("^test$").unwrap());
})
});
assert_str_eq(¶ms, r#"{"a":"test"}"#, r#"{"a":"test"}"#);
assert_error::<errors::WrongValue>(¶ms, r#"{"a":"2"}"#, "/a");
assert_error::<errors::WrongValue>(¶ms, r#"{"a":"test "}"#, "/a");
let params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::array());
a.regex(regex::Regex::new("^test$").unwrap());
})
});
assert_error::<errors::WrongType>(¶ms, r#"{"a":[]}"#, "/a");
}
#[test]
fn is_validates_opt() {
let params = json_dsl::Builder::build(|params| {
params.req_defined("a");
params.opt_typed("b", json_dsl::u64());
});
assert_str_eq(¶ms, r#"{"a":"test"}"#, r#"{"a":"test"}"#);
assert_str_eq(¶ms, r#"{"a":"test","b":"1"}"#, r#"{"a":"test","b":1}"#);
}
#[test]
fn is_validates_opt_with_default() {
let params = json_dsl::Builder::build(|params| {
params.opt("a", |a| {
a.default("default".to_string());
});
});
assert_str_eq(¶ms, r#"{"a":"test"}"#, r#"{"a":"test"}"#);
assert_str_eq(¶ms, r#"{}"#, r#"{"a":"default"}"#);
}
#[test]
fn is_validates_mutually_exclusive() {
let params = json_dsl::Builder::build(|params| {
params.opt_defined("a");
params.opt_defined("b");
params.mutually_exclusive(&["a", "b"])
});
assert_str_eq(¶ms, r#"{"a":1}"#, r#"{"a":1}"#);
assert_str_eq(¶ms, r#"{"b":1}"#, r#"{"b":1}"#);
assert_str_eq(¶ms, r#"{}"#, r#"{}"#);
assert_error::<errors::MutuallyExclusive>(¶ms, r#"{"a":1,"b":1}"#, "/");
}
#[test]
fn is_validates_exactly_one_of() {
let params = json_dsl::Builder::build(|params| {
params.opt_defined("a");
params.opt_defined("b");
params.exactly_one_of(&["a", "b"])
});
assert_str_eq(¶ms, r#"{"a":1}"#, r#"{"a":1}"#);
assert_str_eq(¶ms, r#"{"b":1}"#, r#"{"b":1}"#);
assert_error::<errors::ExactlyOne>(¶ms, r#"{}"#, "/");
assert_error::<errors::ExactlyOne>(¶ms, r#"{"a":1,"b":1}"#, "/");
}
#[test]
fn is_validates_at_least_one_of() {
let params = json_dsl::Builder::build(|params| {
params.opt_defined("a");
params.opt_defined("b");
params.at_least_one_of(&["a", "b"])
});
assert_str_eq(¶ms, r#"{"a":1}"#, r#"{"a":1}"#);
assert_str_eq(¶ms, r#"{"b":1}"#, r#"{"b":1}"#);
assert_str_eq(¶ms, r#"{"a":1,"b":1}"#, r#"{"a":1,"b":1}"#);
assert_error::<errors::AtLeastOne>(¶ms, r#"{}"#, "/");
}
#[test]
fn is_validates_with_function() {
let params = json_dsl::Builder::build(|params| {
params.opt_defined("a");
params.opt_defined("b");
params.validate_with(|_: &Value, path: &str| {
Err(vec![Box::new(errors::WrongType {
path: path.to_string(),
detail: "You shall not pass!".to_string(),
})])
});
});
assert_error::<errors::WrongType>(¶ms, r#"{}"#, "/");
}
#[test]
fn it_validates_with_schema() {
let mut params = json_dsl::Builder::build(|params| {
params.opt_typed("a", json_dsl::u64());
params.opt_typed("b", json_dsl::u64());
params.schema(|schema| {
schema.max_properties(2);
})
});
let mut scope = json_schema::Scope::new();
params.build_schemes(&mut scope).unwrap();
assert_str_eq_with_scope(
¶ms,
Some(&scope),
r#"{"a":1, "b": 1}"#,
r#"{"a":1,"b":1}"#,
);
assert_error_with_scope::<schema_errors::MaxProperties>(
¶ms,
Some(&scope),
r#"{"a":1, "b": 1, "c": 1}"#,
"/",
);
}
#[test]
fn it_validates_params_with_schema() {
let mut params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.schema(|schema| {
schema.integer();
schema.maximum(10f64);
})
});
});
let mut scope = json_schema::Scope::new();
params.build_schemes(&mut scope).unwrap();
assert_str_eq_with_scope(¶ms, Some(&scope), r#"{"a":1}"#, r#"{"a":1}"#);
assert_error_with_scope::<schema_errors::Maximum>(¶ms, Some(&scope), r#"{"a":11}"#, "/a");
assert_error_with_scope::<schema_errors::WrongType>(
¶ms,
Some(&scope),
r#"{"a":"test"}"#,
"/a",
);
}
#[test]
fn it_validates_params_with_schema_and_coercion() {
let mut params = json_dsl::Builder::build(|params| {
params.req("a", |a| {
a.coerce(json_dsl::u64());
a.schema(|schema| {
schema.maximum(10f64);
})
});
});
let mut scope = json_schema::Scope::new();
params.build_schemes(&mut scope).unwrap();
assert_str_eq_with_scope(¶ms, Some(&scope), r#"{"a":1}"#, r#"{"a":1}"#);
assert_str_eq_with_scope(¶ms, Some(&scope), r#"{"a":"10"}"#, r#"{"a":10}"#);
assert_error_with_scope::<schema_errors::Maximum>(¶ms, Some(&scope), r#"{"a":"11"}"#, "/a");
assert_error_with_scope::<errors::WrongType>(¶ms, Some(&scope), r#"{"a":"test"}"#, "/a");
}