async-graphql/src/validation/rules/fragments_on_composite_types.rs
sunli dc7c8d5280 Merge branch 'parser'
Implement a new GraphQL query parser and remove the dependency on graphql-parser.
2020-05-09 17:55:04 +08:00

170 lines
3.7 KiB
Rust

use crate::parser::ast::{FragmentDefinition, InlineFragment, TypeCondition};
use crate::validation::visitor::{Visitor, VisitorContext};
use crate::Spanned;
#[derive(Default)]
pub struct FragmentsOnCompositeTypes;
impl<'a> Visitor<'a> for FragmentsOnCompositeTypes {
fn enter_fragment_definition(
&mut self,
ctx: &mut VisitorContext<'a>,
fragment_definition: &'a Spanned<FragmentDefinition>,
) {
if let Some(current_type) = ctx.current_type() {
if !current_type.is_composite() {
let TypeCondition::On(name) = &fragment_definition.type_condition.node;
ctx.report_error(
vec![fragment_definition.position()],
format!(
"Fragment \"{}\" cannot condition non composite type \"{}\"",
fragment_definition.name, name
),
);
}
}
}
fn enter_inline_fragment(
&mut self,
ctx: &mut VisitorContext<'a>,
inline_fragment: &'a Spanned<InlineFragment>,
) {
if let Some(current_type) = ctx.current_type() {
if !current_type.is_composite() {
ctx.report_error(
vec![inline_fragment.position()],
format!(
"Fragment cannot condition non composite type \"{}\"",
current_type.name()
),
);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::validation::test_harness::{expect_fails_rule, expect_passes_rule};
pub fn factory<'a>() -> FragmentsOnCompositeTypes {
FragmentsOnCompositeTypes
}
#[test]
fn on_object() {
expect_passes_rule(
factory,
r#"
fragment validFragment on Dog {
barks
}
"#,
);
}
#[test]
fn on_interface() {
expect_passes_rule(
factory,
r#"
fragment validFragment on Pet {
name
}
"#,
);
}
#[test]
fn on_object_inline() {
expect_passes_rule(
factory,
r#"
fragment validFragment on Pet {
... on Dog {
barks
}
}
"#,
);
}
#[test]
fn on_inline_without_type_cond() {
expect_passes_rule(
factory,
r#"
fragment validFragment on Pet {
... {
name
}
}
"#,
);
}
#[test]
fn on_union() {
expect_passes_rule(
factory,
r#"
fragment validFragment on CatOrDog {
__typename
}
"#,
);
}
#[test]
fn not_on_scalar() {
expect_fails_rule(
factory,
r#"
fragment scalarFragment on Boolean {
bad
}
"#,
);
}
#[test]
fn not_on_enum() {
expect_fails_rule(
factory,
r#"
fragment scalarFragment on FurColor {
bad
}
"#,
);
}
#[test]
fn not_on_input_object() {
expect_fails_rule(
factory,
r#"
fragment inputFragment on ComplexInput {
stringField
}
"#,
);
}
#[test]
fn not_on_scalar_inline() {
expect_fails_rule(
factory,
r#"
fragment invalidFragment on Pet {
... on String {
barks
}
}
"#,
);
}
}