juniper 0.9.1

GraphQL server library
Documentation
use ast::{Fragment, InlineFragment, VariableDefinition};
use validation::{ValidatorContext, Visitor};
use parser::{SourcePosition, Spanning};

pub struct KnownTypeNames {}

pub fn factory() -> KnownTypeNames {
    KnownTypeNames {}
}

impl<'a> Visitor<'a> for KnownTypeNames {
    fn enter_inline_fragment(
        &mut self,
        ctx: &mut ValidatorContext<'a>,
        fragment: &'a Spanning<InlineFragment>,
    ) {
        if let Some(ref type_cond) = fragment.item.type_condition {
            validate_type(ctx, type_cond.item, &type_cond.start);
        }
    }

    fn enter_fragment_definition(
        &mut self,
        ctx: &mut ValidatorContext<'a>,
        fragment: &'a Spanning<Fragment>,
    ) {
        let type_cond = &fragment.item.type_condition;
        validate_type(ctx, type_cond.item, &type_cond.start);
    }

    fn enter_variable_definition(
        &mut self,
        ctx: &mut ValidatorContext<'a>,
        &(_, ref var_def): &'a (Spanning<&'a str>, VariableDefinition),
    ) {
        let type_name = var_def.var_type.item.innermost_name();
        validate_type(ctx, type_name, &var_def.var_type.start);
    }
}

fn validate_type<'a>(ctx: &mut ValidatorContext<'a>, type_name: &str, location: &SourcePosition) {
    if ctx.schema.type_by_name(type_name).is_none() {
        ctx.report_error(&error_message(type_name), &[location.clone()]);
    }
}

fn error_message(type_name: &str) -> String {
    format!(r#"Unknown type "{}""#, type_name)
}

#[cfg(test)]
mod tests {
    use super::{error_message, factory};

    use parser::SourcePosition;
    use validation::{expect_fails_rule, expect_passes_rule, RuleError};

    #[test]
    fn known_type_names_are_valid() {
        expect_passes_rule(
            factory,
            r#"
          query Foo($var: String, $required: [String!]!) {
            user(id: 4) {
              pets { ... on Pet { name }, ...PetFields, ... { name } }
            }
          }
          fragment PetFields on Pet {
            name
          }
        "#,
        );
    }

    #[test]
    fn unknown_type_names_are_invalid() {
        expect_fails_rule(
            factory,
            r#"
          query Foo($var: JumbledUpLetters) {
            user(id: 4) {
              name
              pets { ... on Badger { name }, ...PetFields }
            }
          }
          fragment PetFields on Peettt {
            name
          }
        "#,
            &[
                RuleError::new(
                    &error_message("JumbledUpLetters"),
                    &[SourcePosition::new(27, 1, 26)],
                ),
                RuleError::new(&error_message("Badger"), &[SourcePosition::new(120, 4, 28)]),
                RuleError::new(&error_message("Peettt"), &[SourcePosition::new(210, 7, 32)]),
            ],
        );
    }
}