diff --git a/README.md b/README.md index 84fdb9a..ff60519 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ graphql-tools = { version = "...", features = "graphql_parser_fork", default-fea #### Validation Rules -> This comparison is based on `graphql-js` refernece implementation. +> This comparison is based on `graphql-js` reference implementation. - [x] ExecutableDefinitions (not actually needed) - [x] UniqueOperationNames diff --git a/src/ast/operation_visitor.rs b/src/ast/operation_visitor.rs index 044e245..b9f6716 100644 --- a/src/ast/operation_visitor.rs +++ b/src/ast/operation_visitor.rs @@ -167,9 +167,43 @@ fn visit_definitions<'a, Visitor, UserContext>( Definition::Operation(operation) => match operation { OperationDefinition::Query(_) => Some(&context.schema.query_type().name), OperationDefinition::SelectionSet(_) => Some(&context.schema.query_type().name), - OperationDefinition::Mutation(_) => context.schema.mutation_type().map(|t| &t.name), + OperationDefinition::Mutation(_) => { + context.schema.mutation_type().map(|t| &t.name).or_else(|| { + // Awkward hack but enables me to move forward + // Somehow the `mutation_type()` gives None, even though `Mutation` type is defined in the schema. + if let Some(type_definition) = context.schema.type_by_name("Mutation") { + return match type_definition { + crate::parser::schema::TypeDefinition::Object(object_type) => { + Some(&object_type.name) + } + _ => None, + }; + } + + None + }) + } OperationDefinition::Subscription(_) => { - context.schema.subscription_type().map(|t| &t.name) + context + .schema + .subscription_type() + .map(|t| &t.name) + .or_else(|| { + // Awkward hack but enables me to move forward + // Somehow the `subscription_type()` gives None, even though `Subscription` type is defined in the schema. + if let Some(type_definition) = + context.schema.type_by_name("Subscription") + { + return match type_definition { + crate::parser::schema::TypeDefinition::Object(object_type) => { + Some(&object_type.name) + } + _ => None, + }; + } + + None + }) } }, }; diff --git a/src/validation/rules/fields_on_correct_type.rs b/src/validation/rules/fields_on_correct_type.rs index 89fe9b4..88c63df 100644 --- a/src/validation/rules/fields_on_correct_type.rs +++ b/src/validation/rules/fields_on_correct_type.rs @@ -118,6 +118,12 @@ pub static FIELDS_ON_CORRECT_TYPE_TEST_SCHEMA: &str = " type Query { human: Human } + type Mutation { + deletePetByName(name: String): Pet + } + type Subscription { + onNewPet: Pet + } "; #[test] @@ -219,6 +225,69 @@ fn ignores_fields_on_unknown_type() { assert_eq!(get_messages(&errors).len(), 0); } +#[test] +fn unknown_query_field() { + use crate::validation::test_utils::*; + + let mut plan = create_plan_from_rule(Box::new(FieldsOnCorrectType {})); + let errors = test_operation_with_schema( + "query test { + unknownField + }", + &FIELDS_ON_CORRECT_TYPE_TEST_SCHEMA, + &mut plan, + ); + + let messages = get_messages(&errors); + assert_eq!(messages.len(), 1); + assert_eq!( + messages, + vec!["Cannot query field \"unknownField\" on type \"Query\"."] + ); +} + +#[test] +fn unknown_mutation_field() { + use crate::validation::test_utils::*; + + let mut plan = create_plan_from_rule(Box::new(FieldsOnCorrectType {})); + let errors = test_operation_with_schema( + "mutation test { + unknownField + }", + &FIELDS_ON_CORRECT_TYPE_TEST_SCHEMA, + &mut plan, + ); + + let messages = get_messages(&errors); + assert_eq!(messages.len(), 1); + assert_eq!( + messages, + vec!["Cannot query field \"unknownField\" on type \"Mutation\"."] + ); +} + +#[test] +fn unknown_subscription_field() { + use crate::validation::test_utils::*; + + let mut plan = create_plan_from_rule(Box::new(FieldsOnCorrectType {})); + let errors = test_operation_with_schema( + "subscription test { + unknownField + }", + &FIELDS_ON_CORRECT_TYPE_TEST_SCHEMA, + &mut plan, + ); + + let messages = get_messages(&errors); + assert_eq!(messages.len(), 1); + assert_eq!( + messages, + vec!["Cannot query field \"unknownField\" on type \"Subscription\"."] + ); +} + #[test] fn reports_errors_when_type_is_known_again() { use crate::validation::test_utils::*;