use crate::ast::{Definition, Document, Selection, SelectionSet};
use crate::types::{BuiltinScalars, FieldType, GraphQLType, ObjectType, Schema};
use crate::validation::{SpecRule, ValidationRule};
use super::SpecValidator;
fn make_schema() -> Schema {
let mut schema = Schema::new();
let query_type = ObjectType::new("Query".to_string())
.with_field(
"hello".to_string(),
FieldType::new(
"hello".to_string(),
GraphQLType::Scalar(BuiltinScalars::string()),
),
)
.with_field(
"world".to_string(),
FieldType::new(
"world".to_string(),
GraphQLType::Scalar(BuiltinScalars::string()),
),
);
schema.add_type(GraphQLType::Object(query_type));
schema.set_query_type("Query".to_string());
schema
}
fn validate(schema: &Schema, query: &str) -> Vec<crate::validation::ValidationError> {
let doc = crate::parser::parse_document(query).expect("parse failed");
SpecValidator::new(schema).validate(&doc)
}
#[test]
fn test_executable_definitions_valid() {
let schema = make_schema();
let errors = validate(&schema, "{ hello }");
assert!(errors.is_empty(), "unexpected errors: {:?}", errors);
}
#[test]
fn test_unique_operation_names_valid() {
let schema = make_schema();
let errors = validate(&schema, "query Foo { hello } query Bar { hello }");
let unique_errors: Vec<_> = errors
.iter()
.filter(|e| e.rule == ValidationRule::Spec(SpecRule::UniqueOperationNames))
.collect();
assert!(
unique_errors.is_empty(),
"unexpected errors: {:?}",
unique_errors
);
}
#[test]
fn test_unique_operation_names_invalid() {
let schema = make_schema();
let errors = validate(&schema, "query Foo { hello } query Foo { world }");
assert!(
errors
.iter()
.any(|e| e.rule == ValidationRule::Spec(SpecRule::UniqueOperationNames)),
"expected UniqueOperationNames error, got: {:?}",
errors
);
}
#[test]
fn test_lone_anonymous_operation_valid() {
let schema = make_schema();
let errors = validate(&schema, "{ hello }");
let lone_errors: Vec<_> = errors
.iter()
.filter(|e| e.rule == ValidationRule::Spec(SpecRule::LoneAnonymousOperation))
.collect();
assert!(
lone_errors.is_empty(),
"unexpected errors: {:?}",
lone_errors
);
}
#[test]
fn test_lone_anonymous_operation_invalid() {
let schema = make_schema();
let errors = validate(&schema, "{ hello } query Foo { world }");
assert!(
errors
.iter()
.any(|e| e.rule == ValidationRule::Spec(SpecRule::LoneAnonymousOperation)),
"expected LoneAnonymousOperation error, got: {:?}",
errors
);
}
#[test]
fn test_unique_fragment_names_valid() {
let schema = make_schema();
let errors = validate(&schema, "fragment A on Query { hello } query Q { ...A }");
let frag_errors: Vec<_> = errors
.iter()
.filter(|e| e.rule == ValidationRule::Spec(SpecRule::UniqueFragmentNames))
.collect();
assert!(
frag_errors.is_empty(),
"unexpected errors: {:?}",
frag_errors
);
}
#[test]
fn test_no_fragment_cycles_valid() {
let schema = make_schema();
let errors = validate(&schema, "fragment A on Query { hello } query Q { ...A }");
let cycle_errors: Vec<_> = errors
.iter()
.filter(|e| e.rule == ValidationRule::Spec(SpecRule::NoFragmentCycles))
.collect();
assert!(
cycle_errors.is_empty(),
"unexpected cycle errors: {:?}",
cycle_errors
);
}
#[test]
fn test_no_fragment_cycles_invalid() {
let schema = make_schema();
let errors = validate(
&schema,
"fragment A on Query { ...B } fragment B on Query { ...A } query Q { ...A }",
);
assert!(
errors
.iter()
.any(|e| e.rule == ValidationRule::Spec(SpecRule::NoFragmentCycles)),
"expected NoFragmentCycles error, got: {:?}",
errors
);
}
#[test]
fn test_no_unused_fragments_valid() {
let schema = make_schema();
let errors = validate(&schema, "fragment A on Query { hello } query Q { ...A }");
let unused_errors: Vec<_> = errors
.iter()
.filter(|e| e.rule == ValidationRule::Spec(SpecRule::NoUnusedFragments))
.collect();
assert!(
unused_errors.is_empty(),
"unexpected errors: {:?}",
unused_errors
);
}
#[test]
fn test_no_unused_fragments_invalid() {
let schema = make_schema();
let errors = validate(&schema, "fragment A on Query { hello } query Q { world }");
assert!(
errors
.iter()
.any(|e| e.rule == ValidationRule::Spec(SpecRule::NoUnusedFragments)),
"expected NoUnusedFragments error, got: {:?}",
errors
);
}
#[test]
fn test_unique_variable_names_invalid() {
let schema = make_schema();
let doc = Document {
definitions: vec![Definition::Operation(crate::ast::OperationDefinition {
operation_type: crate::ast::OperationType::Query,
name: Some("Q".to_string()),
variable_definitions: vec![
crate::ast::VariableDefinition {
variable: crate::ast::Variable {
name: "x".to_string(),
},
type_: crate::ast::Type::NamedType("String".to_string()),
default_value: None,
directives: vec![],
},
crate::ast::VariableDefinition {
variable: crate::ast::Variable {
name: "x".to_string(),
},
type_: crate::ast::Type::NamedType("String".to_string()),
default_value: None,
directives: vec![],
},
],
directives: vec![],
selection_set: SelectionSet {
selections: vec![Selection::Field(crate::ast::Field {
alias: None,
name: "hello".to_string(),
arguments: vec![],
directives: vec![],
selection_set: None,
})],
},
})],
};
let errors = SpecValidator::new(&schema).validate(&doc);
assert!(
errors
.iter()
.any(|e| e.rule == ValidationRule::Spec(SpecRule::UniqueVariableNames)),
"expected UniqueVariableNames error, got: {:?}",
errors
);
}
#[test]
fn test_known_fragment_names_invalid() {
let schema = make_schema();
let doc = Document {
definitions: vec![Definition::Operation(crate::ast::OperationDefinition {
operation_type: crate::ast::OperationType::Query,
name: None,
variable_definitions: vec![],
directives: vec![],
selection_set: SelectionSet {
selections: vec![Selection::FragmentSpread(crate::ast::FragmentSpread {
fragment_name: "Undefined".to_string(),
directives: vec![],
})],
},
})],
};
let errors = SpecValidator::new(&schema).validate(&doc);
assert!(
errors
.iter()
.any(|e| e.rule == ValidationRule::Spec(SpecRule::KnownFragmentNames)),
"expected KnownFragmentNames error, got: {:?}",
errors
);
}
#[test]
fn test_overlapping_fields_conflict() {
let schema = make_schema();
let doc = Document {
definitions: vec![Definition::Operation(crate::ast::OperationDefinition {
operation_type: crate::ast::OperationType::Query,
name: None,
variable_definitions: vec![],
directives: vec![],
selection_set: SelectionSet {
selections: vec![
Selection::Field(crate::ast::Field {
alias: Some("x".to_string()),
name: "hello".to_string(),
arguments: vec![],
directives: vec![],
selection_set: None,
}),
Selection::Field(crate::ast::Field {
alias: Some("x".to_string()),
name: "world".to_string(),
arguments: vec![],
directives: vec![],
selection_set: None,
}),
],
},
})],
};
let errors = SpecValidator::new(&schema).validate(&doc);
assert!(
errors
.iter()
.any(|e| e.rule == ValidationRule::Spec(SpecRule::OverlappingFieldsCanBeMerged)),
"expected OverlappingFieldsCanBeMerged error, got: {:?}",
errors
);
}
#[test]
fn test_spec_validator_new() {
let schema = make_schema();
let _validator = SpecValidator::new(&schema);
}