async_graphql/validation/rules/
known_type_names.rs1use crate::{
2 Name, Pos, Positioned,
3 parser::types::{FragmentDefinition, InlineFragment, TypeCondition, VariableDefinition},
4 registry::MetaTypeName,
5 validation::visitor::{Visitor, VisitorContext},
6};
7
8#[derive(Default)]
9pub struct KnownTypeNames;
10
11impl<'a> Visitor<'a> for KnownTypeNames {
12 fn enter_fragment_definition(
13 &mut self,
14 ctx: &mut VisitorContext<'a>,
15 _name: &'a Name,
16 fragment_definition: &'a Positioned<FragmentDefinition>,
17 ) {
18 let TypeCondition { on: name } = &fragment_definition.node.type_condition.node;
19 validate_type(ctx, &name.node, fragment_definition.pos);
20 }
21
22 fn enter_variable_definition(
23 &mut self,
24 ctx: &mut VisitorContext<'a>,
25 variable_definition: &'a Positioned<VariableDefinition>,
26 ) {
27 validate_type(
28 ctx,
29 MetaTypeName::concrete_typename(&variable_definition.node.var_type.to_string()),
30 variable_definition.pos,
31 );
32 }
33
34 fn enter_inline_fragment(
35 &mut self,
36 ctx: &mut VisitorContext<'a>,
37 inline_fragment: &'a Positioned<InlineFragment>,
38 ) {
39 if let Some(TypeCondition { on: name }) = inline_fragment
40 .node
41 .type_condition
42 .as_ref()
43 .map(|c| &c.node)
44 {
45 validate_type(ctx, &name.node, inline_fragment.pos);
46 }
47 }
48}
49
50fn validate_type(ctx: &mut VisitorContext<'_>, type_name: &str, pos: Pos) {
51 if !ctx.registry.types.contains_key(type_name) {
52 ctx.report_error(vec![pos], format!(r#"Unknown type "{}""#, type_name));
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 pub fn factory() -> KnownTypeNames {
61 KnownTypeNames
62 }
63
64 #[test]
65 fn known_type_names_are_valid() {
66 expect_passes_rule!(
67 factory,
68 r#"
69 query Foo($var: String, $required: [String!]!) {
70 user(id: 4) {
71 pets { ... on Pet { name }, ...PetFields, ... { name } }
72 }
73 }
74 fragment PetFields on Pet {
75 name
76 }
77 "#,
78 );
79 }
80
81 #[test]
82 fn unknown_type_names_are_invalid() {
83 expect_fails_rule!(
84 factory,
85 r#"
86 query Foo($var: JumbledUpLetters) {
87 user(id: 4) {
88 name
89 pets { ... on Badger { name }, ...PetFields }
90 }
91 }
92 fragment PetFields on Peettt {
93 name
94 }
95 "#,
96 );
97 }
98}