async-graphql/src/validation/rules/known_type_names.rs

94 lines
2.5 KiB
Rust
Raw Normal View History

use crate::parser::ast::{FragmentDefinition, InlineFragment, TypeCondition, VariableDefinition};
2020-03-09 10:05:52 +00:00
use crate::registry::TypeName;
2020-03-24 10:54:22 +00:00
use crate::validation::visitor::{Visitor, VisitorContext};
2020-05-10 02:59:51 +00:00
use crate::{Pos, Positioned};
2020-03-09 10:05:52 +00:00
#[derive(Default)]
pub struct KnownTypeNames;
impl<'a> Visitor<'a> for KnownTypeNames {
fn enter_fragment_definition(
&mut self,
2020-03-22 08:45:59 +00:00
ctx: &mut VisitorContext<'a>,
2020-05-10 02:59:51 +00:00
fragment_definition: &'a Positioned<FragmentDefinition>,
2020-03-09 10:05:52 +00:00
) {
let TypeCondition::On(name) = &fragment_definition.type_condition.node;
validate_type(ctx, name.node, fragment_definition.position());
2020-03-09 10:05:52 +00:00
}
fn enter_variable_definition(
&mut self,
2020-03-22 08:45:59 +00:00
ctx: &mut VisitorContext<'a>,
2020-05-10 02:59:51 +00:00
variable_definition: &'a Positioned<VariableDefinition>,
2020-03-09 10:05:52 +00:00
) {
validate_type(
ctx,
2020-04-06 10:30:38 +00:00
TypeName::concrete_typename(&variable_definition.var_type.to_string()),
variable_definition.position(),
2020-03-09 10:05:52 +00:00
);
}
fn enter_inline_fragment(
&mut self,
2020-03-22 08:45:59 +00:00
ctx: &mut VisitorContext<'a>,
2020-05-10 02:59:51 +00:00
inline_fragment: &'a Positioned<InlineFragment>,
2020-03-09 10:05:52 +00:00
) {
if let Some(TypeCondition::On(name)) =
inline_fragment.type_condition.as_ref().map(|c| &c.node)
{
validate_type(ctx, name.node, inline_fragment.position());
2020-03-09 10:05:52 +00:00
}
}
}
2020-03-22 08:45:59 +00:00
fn validate_type(ctx: &mut VisitorContext<'_>, type_name: &str, pos: Pos) {
2020-03-09 10:05:52 +00:00
if ctx.registry.types.get(type_name).is_none() {
ctx.report_error(vec![pos], format!(r#"Unknown type "{}""#, type_name));
}
}
2020-04-05 08:00:26 +00:00
#[cfg(test)]
mod tests {
use super::*;
use crate::validation::test_harness::{expect_fails_rule, expect_passes_rule};
pub fn factory() -> KnownTypeNames {
KnownTypeNames::default()
}
#[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
}
"#,
);
}
}