async_graphql/validation/rules/
default_values_of_correct_type.rs1use async_graphql_parser::types::BaseType;
2
3use crate::{
4 Positioned, QueryPathSegment,
5 context::QueryPathNode,
6 parser::types::VariableDefinition,
7 validation::{
8 utils::is_valid_input_value,
9 visitor::{Visitor, VisitorContext},
10 },
11};
12
13pub struct DefaultValuesOfCorrectType;
14
15impl<'a> Visitor<'a> for DefaultValuesOfCorrectType {
16 fn enter_variable_definition(
17 &mut self,
18 ctx: &mut VisitorContext<'a>,
19 variable_definition: &'a Positioned<VariableDefinition>,
20 ) {
21 if let BaseType::Named(vtype_name) = &variable_definition.node.var_type.node.base
22 && !ctx.registry.types.contains_key(vtype_name.as_str())
23 {
24 ctx.report_error(
25 vec![variable_definition.pos],
26 format!(r#"Unknown type "{}""#, vtype_name),
27 );
28 return;
29 }
30
31 if let Some(value) = &variable_definition.node.default_value
32 && let Some(reason) = is_valid_input_value(
33 ctx.registry,
34 &variable_definition.node.var_type.to_string(),
35 &value.node,
36 QueryPathNode {
37 parent: None,
38 segment: QueryPathSegment::Name(&variable_definition.node.name.node),
39 },
40 )
41 {
42 ctx.report_error(
43 vec![variable_definition.pos],
44 format!("Invalid default value for argument: {}", reason),
45 )
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 pub fn factory() -> DefaultValuesOfCorrectType {
55 DefaultValuesOfCorrectType
56 }
57
58 #[test]
59 fn variables_with_no_default_values() {
60 expect_passes_rule!(
61 factory,
62 r#"
63 query NullableValues($a: Int, $b: String, $c: ComplexInput) {
64 dog { name }
65 }
66 "#,
67 );
68 }
69
70 #[test]
71 fn required_variables_without_default_values() {
72 expect_passes_rule!(
73 factory,
74 r#"
75 query RequiredValues($a: Int!, $b: String!) {
76 dog { name }
77 }
78 "#,
79 );
80 }
81
82 #[test]
83 fn variables_with_valid_default_values() {
84 expect_passes_rule!(
85 factory,
86 r#"
87 query WithDefaultValues(
88 $a: Int = 1,
89 $b: String = "ok",
90 $c: ComplexInput = { requiredField: true, intField: 3 }
91 ) {
92 dog { name }
93 }
94 "#,
95 );
96 }
97
98 #[test]
99 fn required_variables_with_default_values() {
100 expect_passes_rule!(
101 factory,
102 r#"
103 query UnreachableDefaultValues($a: Int! = 3, $b: String! = "default") {
104 dog { name }
105 }
106 "#,
107 );
108 }
109
110 #[test]
111 fn variables_with_invalid_default_values() {
112 expect_fails_rule!(
113 factory,
114 r#"
115 query InvalidDefaultValues(
116 $a: Int = "one",
117 $b: String = 4,
118 $c: ComplexInput = "notverycomplex"
119 ) {
120 dog { name }
121 }
122 "#,
123 );
124 }
125
126 #[test]
127 fn complex_variables_missing_required_field() {
128 expect_fails_rule!(
129 factory,
130 r#"
131 query MissingRequiredField($a: ComplexInput = {intField: 3}) {
132 dog { name }
133 }
134 "#,
135 );
136 }
137
138 #[test]
139 fn list_variables_with_invalid_item() {
140 expect_fails_rule!(
141 factory,
142 r#"
143 query InvalidItem($a: [String] = ["one", 2]) {
144 dog { name }
145 }
146 "#,
147 );
148 }
149}