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

170 lines
3.7 KiB
Rust
Raw Normal View History

use crate::parser::ast::{FragmentDefinition, InlineFragment, TypeCondition};
2020-03-24 10:54:22 +00:00
use crate::validation::visitor::{Visitor, VisitorContext};
use crate::Spanned;
2020-03-09 04:08:50 +00:00
#[derive(Default)]
pub struct FragmentsOnCompositeTypes;
impl<'a> Visitor<'a> for FragmentsOnCompositeTypes {
fn enter_fragment_definition(
&mut self,
2020-03-22 08:45:59 +00:00
ctx: &mut VisitorContext<'a>,
fragment_definition: &'a Spanned<FragmentDefinition>,
2020-03-09 04:08:50 +00:00
) {
2020-04-05 08:00:26 +00:00
if let Some(current_type) = ctx.current_type() {
if !current_type.is_composite() {
let TypeCondition::On(name) = &fragment_definition.type_condition.node;
2020-04-05 08:00:26 +00:00
ctx.report_error(
vec![fragment_definition.position()],
2020-04-05 08:00:26 +00:00
format!(
"Fragment \"{}\" cannot condition non composite type \"{}\"",
fragment_definition.name, name
),
);
}
2020-03-09 04:08:50 +00:00
}
}
fn enter_inline_fragment(
&mut self,
2020-03-22 08:45:59 +00:00
ctx: &mut VisitorContext<'a>,
inline_fragment: &'a Spanned<InlineFragment>,
2020-03-09 04:08:50 +00:00
) {
2020-04-05 08:00:26 +00:00
if let Some(current_type) = ctx.current_type() {
if !current_type.is_composite() {
ctx.report_error(
vec![inline_fragment.position()],
2020-04-05 08:00:26 +00:00
format!(
"Fragment cannot condition non composite type \"{}\"",
current_type.name()
),
);
}
2020-03-09 04:08:50 +00:00
}
}
}
2020-04-05 08:00:26 +00:00
#[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
}
}
"#,
);
}
}