Skip to content

Commit 478c7b7

Browse files
committed
Add enum input value tests and improve validation
1 parent b3a750f commit 478c7b7

File tree

3 files changed

+158
-1
lines changed

3 files changed

+158
-1
lines changed

src/executor_tests/enums.rs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
use std::collections::HashMap;
2+
3+
use value::Value;
4+
use ast::InputValue;
5+
use schema::model::RootNode;
6+
use ::GraphQLError::ValidationError;
7+
use validation::RuleError;
8+
use parser::SourcePosition;
9+
10+
#[derive(Debug)]
11+
enum Color { Red, Green, Blue }
12+
struct TestType;
13+
14+
graphql_enum!(Color {
15+
Color::Red => "RED",
16+
Color::Green => "GREEN",
17+
Color::Blue => "BLUE",
18+
});
19+
20+
graphql_object!(TestType: () |&self| {
21+
field to_string(color: Color) -> String {
22+
format!("Color::{:?}", color)
23+
}
24+
25+
field a_color() -> Color {
26+
Color::Red
27+
}
28+
});
29+
30+
fn run_variable_query<F>(query: &str, vars: HashMap<String, InputValue>, f: F)
31+
where F: Fn(&HashMap<String, Value>) -> ()
32+
{
33+
let schema = RootNode::new(TestType, ());
34+
35+
let (result, errs) = ::execute(query, None, &schema, &vars, &())
36+
.expect("Execution failed");
37+
38+
assert_eq!(errs, []);
39+
40+
println!("Result: {:?}", result);
41+
42+
let obj = result.as_object_value().expect("Result is not an object");
43+
44+
f(obj);
45+
}
46+
47+
fn run_query<F>(query: &str, f: F)
48+
where F: Fn(&HashMap<String, Value>) -> ()
49+
{
50+
run_variable_query(query, HashMap::new(), f);
51+
}
52+
53+
#[test]
54+
fn accepts_enum_literal() {
55+
run_query(
56+
"{ toString(color: RED) }",
57+
|result| {
58+
assert_eq!(
59+
result.get("toString"),
60+
Some(&Value::string("Color::Red")));
61+
});
62+
}
63+
64+
#[test]
65+
fn serializes_as_output() {
66+
run_query(
67+
"{ aColor }",
68+
|result| {
69+
assert_eq!(
70+
result.get("aColor"),
71+
Some(&Value::string("RED")));
72+
});
73+
}
74+
75+
#[test]
76+
fn does_not_accept_string_literals() {
77+
let schema = RootNode::new(TestType, ());
78+
79+
let query = r#"{ toString(color: "RED") }"#;
80+
let vars = vec![
81+
].into_iter().collect();
82+
83+
let error = ::execute(query, None, &schema, &vars, &())
84+
.unwrap_err();
85+
86+
assert_eq!(error, ValidationError(vec![
87+
RuleError::new(
88+
r#"Invalid value for argument "color", expected type "Color!""#,
89+
&[SourcePosition::new(18, 0, 18)],
90+
),
91+
]));
92+
}
93+
94+
#[test]
95+
fn accepts_strings_in_variables() {
96+
run_variable_query(
97+
"{ toString(color: RED) }",
98+
vec![
99+
("color".to_owned(), InputValue::string("RED")),
100+
].into_iter().collect(),
101+
|result| {
102+
assert_eq!(
103+
result.get("toString"),
104+
Some(&Value::string("Color::Red")));
105+
});
106+
}
107+
108+
#[test]
109+
fn does_not_accept_incorrect_enum_name_in_variables() {
110+
let schema = RootNode::new(TestType, ());
111+
112+
let query = r#"query q($color: Color!) { toString(color: $color) }"#;
113+
let vars = vec![
114+
("color".to_owned(), InputValue::string("BLURPLE")),
115+
].into_iter().collect();
116+
117+
let error = ::execute(query, None, &schema, &vars, &())
118+
.unwrap_err();
119+
120+
assert_eq!(error, ValidationError(vec![
121+
RuleError::new(
122+
r#"Variable "$color" got invalid value. Invalid value for enum "Color"."#,
123+
&[SourcePosition::new(8, 0, 8)],
124+
),
125+
]));
126+
}
127+
128+
#[test]
129+
fn does_not_accept_incorrect_type_in_variables() {
130+
let schema = RootNode::new(TestType, ());
131+
132+
let query = r#"query q($color: Color!) { toString(color: $color) }"#;
133+
let vars = vec![
134+
("color".to_owned(), InputValue::int(123)),
135+
].into_iter().collect();
136+
137+
let error = ::execute(query, None, &schema, &vars, &())
138+
.unwrap_err();
139+
140+
assert_eq!(error, ValidationError(vec![
141+
RuleError::new(
142+
r#"Variable "$color" got invalid value. Expected "Color", found not a string or enum."#,
143+
&[SourcePosition::new(8, 0, 8)],
144+
),
145+
]));
146+
}

src/executor_tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
mod introspection;
22
mod variables;
3+
mod enums;

src/validation/input_value.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,17 @@ fn unify_enum<'a>(
162162
path: &Path<'a>,
163163
) {
164164
match value {
165-
&InputValue::String(_) | &InputValue::Enum(_) => (),
165+
&InputValue::String(ref name) | &InputValue::Enum(ref name) => {
166+
if !meta.values.iter().any(|ev| &ev.name == name) {
167+
push_unification_error(
168+
errors,
169+
var_name,
170+
var_pos,
171+
path,
172+
&format!(r#"Invalid value for enum "{}""#, meta.name),
173+
)
174+
}
175+
}
166176
_ => push_unification_error(
167177
errors,
168178
var_name,

0 commit comments

Comments
 (0)