From e0c6b0317183b2a264a3040f8b989bebb46e7b21 Mon Sep 17 00:00:00 2001
From: Magnus Hallin <mhallin@fastmail.com>
Date: Sun, 19 Feb 2017 10:29:37 +0100
Subject: [PATCH] Add more input value null value tests

These correspond to the table in "3.1.6 Input Objects" in the GraphQL
specification.
---
 src/executor_tests/variables.rs | 143 ++++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)

diff --git a/src/executor_tests/variables.rs b/src/executor_tests/variables.rs
index a1baab7c..bff812ab 100644
--- a/src/executor_tests/variables.rs
+++ b/src/executor_tests/variables.rs
@@ -49,6 +49,14 @@ graphql_input_object!(
     }
 );
 
+graphql_input_object!(
+    #[derive(Debug)]
+    struct ExampleInputObject {
+        a: Option<String>,
+        b: i64,
+    }
+);
+
 graphql_object!(TestType: () |&self| {
     field field_with_object_input(input: Option<TestInputObject>) -> String {
         format!("{:?}", input)
@@ -85,6 +93,10 @@ graphql_object!(TestType: () |&self| {
     field nn_list_nn(input: Vec<String>) -> String {
         format!("{:?}", input)
     }
+
+    field example_input(arg: ExampleInputObject) -> String {
+        format!("a: {:?}, b: {:?}", arg.a, arg.b)
+    }
 });
 
 fn run_variable_query<F>(query: &str, vars: Variables, f: F)
@@ -748,3 +760,134 @@ fn default_argument_when_nullable_variable_set_to_null() {
                 Some(&Value::string(r#""Hello World""#)));
         });
 }
+
+#[test]
+fn nullable_input_object_arguments_successful_without_variables() {
+    run_query(
+        r#"{ exampleInput(arg: {a: "abc", b: 123}) }"#,
+        |result| {
+            assert_eq!(
+                result.get("exampleInput"),
+                Some(&Value::string(r#"a: Some("abc"), b: 123"#)));
+        });
+
+    run_query(
+        r#"{ exampleInput(arg: {a: null, b: 1}) }"#,
+        |result| {
+            assert_eq!(
+                result.get("exampleInput"),
+                Some(&Value::string(r#"a: None, b: 1"#)));
+        });
+}
+
+#[test]
+fn nullable_input_object_arguments_successful_with_variables() {
+    run_variable_query(
+        r#"query q($var: Int!) { exampleInput(arg: {b: $var}) }"#,
+        vec![
+            ("var".to_owned(), InputValue::int(123)),
+        ].into_iter().collect(),
+        |result| {
+            assert_eq!(
+                result.get("exampleInput"),
+                Some(&Value::string(r#"a: None, b: 123"#)));
+        });
+
+    run_variable_query(
+        r#"query q($var: String) { exampleInput(arg: {a: $var, b: 1}) }"#,
+        vec![
+            ("var".to_owned(), InputValue::null()),
+        ].into_iter().collect(),
+        |result| {
+            assert_eq!(
+                result.get("exampleInput"),
+                Some(&Value::string(r#"a: None, b: 1"#)));
+        });
+
+    run_variable_query(
+        r#"query q($var: String) { exampleInput(arg: {a: $var, b: 1}) }"#,
+        vec![
+        ].into_iter().collect(),
+        |result| {
+            assert_eq!(
+                result.get("exampleInput"),
+                Some(&Value::string(r#"a: None, b: 1"#)));
+        });
+}
+
+#[test]
+fn does_not_allow_missing_required_field() {
+    let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
+
+    let query = r#"{ exampleInput(arg: {a: "abc"}) }"#;
+    let vars = vec![
+    ].into_iter().collect();
+
+    let error = ::execute(query, None, &schema, &vars, &())
+        .unwrap_err();
+
+    assert_eq!(error, ValidationError(vec![
+        RuleError::new(
+            r#"Invalid value for argument "arg", expected type "ExampleInputObject!""#,
+            &[SourcePosition::new(20, 0, 20)],
+        ),
+    ]));
+}
+
+#[test]
+fn does_not_allow_null_in_required_field() {
+    let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
+
+    let query = r#"{ exampleInput(arg: {a: "abc", b: null}) }"#;
+    let vars = vec![
+    ].into_iter().collect();
+
+    let error = ::execute(query, None, &schema, &vars, &())
+        .unwrap_err();
+
+    assert_eq!(error, ValidationError(vec![
+        RuleError::new(
+            r#"Invalid value for argument "arg", expected type "ExampleInputObject!""#,
+            &[SourcePosition::new(20, 0, 20)],
+        ),
+    ]));
+}
+
+#[test]
+fn does_not_allow_missing_variable_for_required_field() {
+    let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
+
+    let query = r#"query q($var: Int!) { exampleInput(arg: {b: $var}) }"#;
+    let vars = vec![
+    ].into_iter().collect();
+
+    let error = ::execute(query, None, &schema, &vars, &())
+        .unwrap_err();
+
+    assert_eq!(error, ValidationError(vec![
+        RuleError::new(
+            r#"Variable "$var" of required type "Int!" was not provided."#,
+            &[SourcePosition::new(8, 0, 8)],
+        ),
+    ]));
+}
+
+#[test]
+fn does_not_allow_null_variable_for_required_field() {
+    let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
+
+    let query = r#"query q($var: Int!) { exampleInput(arg: {b: $var}) }"#;
+    let vars = vec![
+        ("var".to_owned(), InputValue::null()),
+    ].into_iter().collect();
+
+    let error = ::execute(query, None, &schema, &vars, &())
+        .unwrap_err();
+
+    assert_eq!(error, ValidationError(vec![
+        RuleError::new(
+            r#"Variable "$var" of required type "Int!" was not provided."#,
+            &[SourcePosition::new(8, 0, 8)],
+        ),
+    ]));
+}