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

97 lines
2.5 KiB
Rust
Raw Normal View History

use crate::parser::types::{FragmentDefinition, InlineFragment, TypeCondition, VariableDefinition};
use crate::registry::MetaTypeName;
2020-03-24 10:54:22 +00:00
use crate::validation::visitor::{Visitor, VisitorContext};
use crate::{Name, 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>,
_name: &'a Name,
2020-05-10 02:59:51 +00:00
fragment_definition: &'a Positioned<FragmentDefinition>,
2020-03-09 10:05:52 +00:00
) {
2020-09-06 05:38:31 +00:00
let TypeCondition { on: name } = &fragment_definition.node.type_condition.node;
validate_type(ctx, &name.node, fragment_definition.pos);
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-09-06 05:38:31 +00:00
MetaTypeName::concrete_typename(&variable_definition.node.var_type.to_string()),
variable_definition.pos,
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
) {
2020-09-06 06:16:36 +00:00
if let Some(TypeCondition { on: name }) = inline_fragment
.node
.type_condition
.as_ref()
.map(|c| &c.node)
{
2020-09-06 05:38:31 +00:00
validate_type(ctx, &name.node, inline_fragment.pos);
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::*;
pub fn factory() -> KnownTypeNames {
KnownTypeNames::default()
}
#[test]
fn known_type_names_are_valid() {
2020-05-29 09:29:15 +00:00
expect_passes_rule!(
2020-04-05 08:00:26 +00:00
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() {
2020-05-29 09:29:15 +00:00
expect_fails_rule!(
2020-04-05 08:00:26 +00:00
factory,
r#"
query Foo($var: JumbledUpLetters) {
user(id: 4) {
name
pets { ... on Badger { name }, ...PetFields }
}
}
fragment PetFields on Peettt {
name
}
"#,
);
}
}