async-graphql/src/validation/rules/default_values_of_correct_type.rs
2022-01-24 14:32:30 +01:00

151 lines
4.0 KiB
Rust

use async_graphql_parser::types::BaseType;
use crate::context::QueryPathNode;
use crate::parser::types::VariableDefinition;
use crate::validation::utils::is_valid_input_value;
use crate::validation::visitor::{Visitor, VisitorContext};
use crate::{Positioned, QueryPathSegment};
pub struct DefaultValuesOfCorrectType;
impl<'a> Visitor<'a> for DefaultValuesOfCorrectType {
fn enter_variable_definition(
&mut self,
ctx: &mut VisitorContext<'a>,
variable_definition: &'a Positioned<VariableDefinition>,
) {
if let BaseType::Named(vtype_name) = &variable_definition.node.var_type.node.base {
if !ctx.registry.types.contains_key(vtype_name.as_str()) {
ctx.report_error(
vec![variable_definition.pos],
format!(r#"Unknown type "{}""#, vtype_name),
);
return;
}
}
if let Some(value) = &variable_definition.node.default_value {
if !variable_definition.node.var_type.node.nullable {
ctx.report_error(vec![variable_definition.pos],format!(
"Argument \"{}\" has type \"{}\" and is not nullable, so it can't have a default value",
variable_definition.node.name, variable_definition.node.var_type,
));
} else if let Some(reason) = is_valid_input_value(
ctx.registry,
&variable_definition.node.var_type.to_string(),
&value.node,
QueryPathNode {
parent: None,
segment: QueryPathSegment::Name(&variable_definition.node.name.node),
},
) {
ctx.report_error(
vec![variable_definition.pos],
format!("Invalid default value for argument: {}", reason),
)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
pub fn factory() -> DefaultValuesOfCorrectType {
DefaultValuesOfCorrectType
}
#[test]
fn variables_with_no_default_values() {
expect_passes_rule!(
factory,
r#"
query NullableValues($a: Int, $b: String, $c: ComplexInput) {
dog { name }
}
"#,
);
}
#[test]
fn required_variables_without_default_values() {
expect_passes_rule!(
factory,
r#"
query RequiredValues($a: Int!, $b: String!) {
dog { name }
}
"#,
);
}
#[test]
fn variables_with_valid_default_values() {
expect_passes_rule!(
factory,
r#"
query WithDefaultValues(
$a: Int = 1,
$b: String = "ok",
$c: ComplexInput = { requiredField: true, intField: 3 }
) {
dog { name }
}
"#,
);
}
#[test]
fn no_required_variables_with_default_values() {
expect_fails_rule!(
factory,
r#"
query UnreachableDefaultValues($a: Int! = 3, $b: String! = "default") {
dog { name }
}
"#,
);
}
#[test]
fn variables_with_invalid_default_values() {
expect_fails_rule!(
factory,
r#"
query InvalidDefaultValues(
$a: Int = "one",
$b: String = 4,
$c: ComplexInput = "notverycomplex"
) {
dog { name }
}
"#,
);
}
#[test]
fn complex_variables_missing_required_field() {
expect_fails_rule!(
factory,
r#"
query MissingRequiredField($a: ComplexInput = {intField: 3}) {
dog { name }
}
"#,
);
}
#[test]
fn list_variables_with_invalid_item() {
expect_fails_rule!(
factory,
r#"
query InvalidItem($a: [String] = ["one", 2]) {
dog { name }
}
"#,
);
}
}