Validate scalar values passed as variables

Related to #49 - prevents panics in later stages of execution
This commit is contained in:
Magnus Hallin 2017-06-15 10:36:07 +02:00
parent 4d8c3611d2
commit b673f5bd1f
2 changed files with 142 additions and 0 deletions

View file

@ -108,6 +108,14 @@ graphql_object!(TestType: () |&self| {
field input_with_defaults(arg: InputWithDefaults) -> String {
format!("a: {:?}", arg.a)
}
field integer_input(value: i64) -> String {
format!("value: {}", value)
}
field float_input(value: f64) -> String {
format!("value: {}", value)
}
});
fn run_variable_query<F>(query: &str, vars: Variables, f: F)
@ -945,3 +953,126 @@ fn input_object_with_default_values() {
Some(&Value::string(r#"a: 2"#)));
});
}
mod integers {
use super::*;
#[test]
fn positive_and_negative_should_work() {
run_variable_query(
r#"query q($var: Int!) { integerInput(value: $var) }"#,
vec![
("var".to_owned(), InputValue::int(1)),
].into_iter().collect(),
|result| {
assert_eq!(
result.get("integerInput"),
Some(&Value::string(r#"value: 1"#)));
});
run_variable_query(
r#"query q($var: Int!) { integerInput(value: $var) }"#,
vec![
("var".to_owned(), InputValue::int(-1)),
].into_iter().collect(),
|result| {
assert_eq!(
result.get("integerInput"),
Some(&Value::string(r#"value: -1"#)));
});
}
#[test]
fn does_not_coerce_from_float() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($var: Int!) { integerInput(value: $var) }"#;
let vars = vec![
("var".to_owned(), InputValue::float(10.0)),
].into_iter().collect();
let error = ::execute(query, None, &schema, &vars, &())
.unwrap_err();
assert_eq!(error, ValidationError(vec![
RuleError::new(
r#"Variable "$var" got invalid value. Expected "Int"."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
}
#[test]
fn does_not_coerce_from_string() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($var: Int!) { integerInput(value: $var) }"#;
let vars = vec![
("var".to_owned(), InputValue::string("10")),
].into_iter().collect();
let error = ::execute(query, None, &schema, &vars, &())
.unwrap_err();
assert_eq!(error, ValidationError(vec![
RuleError::new(
r#"Variable "$var" got invalid value. Expected "Int"."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
}
}
mod floats {
use super::*;
#[test]
fn float_values_should_work() {
run_variable_query(
r#"query q($var: Float!) { floatInput(value: $var) }"#,
vec![
("var".to_owned(), InputValue::float(10.0)),
].into_iter().collect(),
|result| {
assert_eq!(
result.get("floatInput"),
Some(&Value::string(r#"value: 10"#)));
});
}
#[test]
fn coercion_from_integers_should_work() {
run_variable_query(
r#"query q($var: Float!) { floatInput(value: $var) }"#,
vec![
("var".to_owned(), InputValue::int(-1)),
].into_iter().collect(),
|result| {
assert_eq!(
result.get("floatInput"),
Some(&Value::string(r#"value: -1"#)));
});
}
#[test]
fn does_not_coerce_from_string() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($var: Float!) { floatInput(value: $var) }"#;
let vars = vec![
("var".to_owned(), InputValue::string("10")),
].into_iter().collect();
let error = ::execute(query, None, &schema, &vars, &())
.unwrap_err();
assert_eq!(error, ValidationError(vec![
RuleError::new(
r#"Variable "$var" got invalid value. Expected "Float"."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
}
}

View file

@ -133,6 +133,17 @@ fn unify_scalar<'a>(
errors: &mut Vec<RuleError>,
path: &Path<'a>,
) {
if !(meta.try_parse_fn)(value) {
push_unification_error(
errors,
var_name,
var_pos,
path,
&format!(r#"Expected "{}""#, meta.name),
);
return;
}
match *value {
InputValue::List(_) =>
push_unification_error(