Skip to content

Commit b673f5b

Browse files
committed
Validate scalar values passed as variables
Related to #49 - prevents panics in later stages of execution
1 parent 4d8c361 commit b673f5b

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

src/executor_tests/variables.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ graphql_object!(TestType: () |&self| {
108108
field input_with_defaults(arg: InputWithDefaults) -> String {
109109
format!("a: {:?}", arg.a)
110110
}
111+
112+
field integer_input(value: i64) -> String {
113+
format!("value: {}", value)
114+
}
115+
116+
field float_input(value: f64) -> String {
117+
format!("value: {}", value)
118+
}
111119
});
112120

113121
fn run_variable_query<F>(query: &str, vars: Variables, f: F)
@@ -945,3 +953,126 @@ fn input_object_with_default_values() {
945953
Some(&Value::string(r#"a: 2"#)));
946954
});
947955
}
956+
957+
958+
mod integers {
959+
use super::*;
960+
961+
#[test]
962+
fn positive_and_negative_should_work() {
963+
run_variable_query(
964+
r#"query q($var: Int!) { integerInput(value: $var) }"#,
965+
vec![
966+
("var".to_owned(), InputValue::int(1)),
967+
].into_iter().collect(),
968+
|result| {
969+
assert_eq!(
970+
result.get("integerInput"),
971+
Some(&Value::string(r#"value: 1"#)));
972+
});
973+
974+
run_variable_query(
975+
r#"query q($var: Int!) { integerInput(value: $var) }"#,
976+
vec![
977+
("var".to_owned(), InputValue::int(-1)),
978+
].into_iter().collect(),
979+
|result| {
980+
assert_eq!(
981+
result.get("integerInput"),
982+
Some(&Value::string(r#"value: -1"#)));
983+
});
984+
}
985+
986+
#[test]
987+
fn does_not_coerce_from_float() {
988+
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
989+
990+
let query = r#"query q($var: Int!) { integerInput(value: $var) }"#;
991+
let vars = vec![
992+
("var".to_owned(), InputValue::float(10.0)),
993+
].into_iter().collect();
994+
995+
let error = ::execute(query, None, &schema, &vars, &())
996+
.unwrap_err();
997+
998+
assert_eq!(error, ValidationError(vec![
999+
RuleError::new(
1000+
r#"Variable "$var" got invalid value. Expected "Int"."#,
1001+
&[SourcePosition::new(8, 0, 8)],
1002+
),
1003+
]));
1004+
}
1005+
1006+
#[test]
1007+
fn does_not_coerce_from_string() {
1008+
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
1009+
1010+
let query = r#"query q($var: Int!) { integerInput(value: $var) }"#;
1011+
let vars = vec![
1012+
("var".to_owned(), InputValue::string("10")),
1013+
].into_iter().collect();
1014+
1015+
let error = ::execute(query, None, &schema, &vars, &())
1016+
.unwrap_err();
1017+
1018+
assert_eq!(error, ValidationError(vec![
1019+
RuleError::new(
1020+
r#"Variable "$var" got invalid value. Expected "Int"."#,
1021+
&[SourcePosition::new(8, 0, 8)],
1022+
),
1023+
]));
1024+
}
1025+
}
1026+
1027+
1028+
mod floats {
1029+
use super::*;
1030+
1031+
#[test]
1032+
fn float_values_should_work() {
1033+
run_variable_query(
1034+
r#"query q($var: Float!) { floatInput(value: $var) }"#,
1035+
vec![
1036+
("var".to_owned(), InputValue::float(10.0)),
1037+
].into_iter().collect(),
1038+
|result| {
1039+
assert_eq!(
1040+
result.get("floatInput"),
1041+
Some(&Value::string(r#"value: 10"#)));
1042+
});
1043+
}
1044+
1045+
#[test]
1046+
fn coercion_from_integers_should_work() {
1047+
run_variable_query(
1048+
r#"query q($var: Float!) { floatInput(value: $var) }"#,
1049+
vec![
1050+
("var".to_owned(), InputValue::int(-1)),
1051+
].into_iter().collect(),
1052+
|result| {
1053+
assert_eq!(
1054+
result.get("floatInput"),
1055+
Some(&Value::string(r#"value: -1"#)));
1056+
});
1057+
}
1058+
1059+
#[test]
1060+
fn does_not_coerce_from_string() {
1061+
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
1062+
1063+
let query = r#"query q($var: Float!) { floatInput(value: $var) }"#;
1064+
let vars = vec![
1065+
("var".to_owned(), InputValue::string("10")),
1066+
].into_iter().collect();
1067+
1068+
let error = ::execute(query, None, &schema, &vars, &())
1069+
.unwrap_err();
1070+
1071+
assert_eq!(error, ValidationError(vec![
1072+
RuleError::new(
1073+
r#"Variable "$var" got invalid value. Expected "Float"."#,
1074+
&[SourcePosition::new(8, 0, 8)],
1075+
),
1076+
]));
1077+
}
1078+
}

src/validation/input_value.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,17 @@ fn unify_scalar<'a>(
133133
errors: &mut Vec<RuleError>,
134134
path: &Path<'a>,
135135
) {
136+
if !(meta.try_parse_fn)(value) {
137+
push_unification_error(
138+
errors,
139+
var_name,
140+
var_pos,
141+
path,
142+
&format!(r#"Expected "{}""#, meta.name),
143+
);
144+
return;
145+
}
146+
136147
match *value {
137148
InputValue::List(_) =>
138149
push_unification_error(

0 commit comments

Comments
 (0)