use apollo_compiler::parser::Parser;
use apollo_compiler::Schema;
#[test]
fn it_fails_validation_with_duplicate_operation_fields() {
let input = r#"
type Query implements NamedEntity {
imgSize: Int
name: String
image: URL
results: [Int]
}
interface NamedEntity {
name: String
image: URL
results: [Int]
name: String
}
scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
"#;
let errors = Schema::parse_and_validate(input, "schema.graphql")
.unwrap_err()
.errors
.to_string();
assert!(
errors
.contains("duplicate definitions for the `name` field of interface type `NamedEntity`"),
"{errors}"
);
}
#[test]
fn it_fails_validation_with_duplicate_interface_definitions() {
let input = r#"
type Query implements NamedEntity {
imgSize: Int
name: String
image: URL
results: [Int]
}
interface NamedEntity {
name: String
image: URL
results: [Int]
}
interface NamedEntity {
name: String
image: URL
results: [Int]
}
scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
"#;
let errors = Schema::parse_and_validate(input, "schema.graphql")
.unwrap_err()
.errors
.to_string();
assert!(
errors.contains("the type `NamedEntity` is defined multiple times"),
"{errors}"
);
}
#[test]
fn it_fails_validation_with_recursive_interface_definition() {
let input = r#"
type Query implements NamedEntity {
imgSize: Int
name: String
image: URL
results: [Int]
}
interface NamedEntity implements NamedEntity {
name: String
image: URL
results: [Int]
}
scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
"#;
let errors = Schema::parse_and_validate(input, "schema.graphql")
.unwrap_err()
.errors
.to_string();
assert!(
errors.contains("interface NamedEntity cannot implement itself"),
"{errors}"
);
}
#[test]
fn it_fails_validation_with_undefined_interface_definition() {
let input = r#"
interface NamedEntity implements NewEntity {
name: String
image: URL
results: [Int]
}
scalar URL @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
"#;
let errors = Schema::parse_and_validate(input, "schema.graphql")
.unwrap_err()
.errors
.to_string();
assert!(
errors.contains("cannot find type `NewEntity` in this document"),
"{errors}"
);
}
#[test]
fn it_fails_validation_with_missing_transitive_interface() {
let input = r#"
type Query implements Node {
id: ID!
}
interface Node {
id: ID!
}
interface Resource implements Node {
id: ID!
width: Int
}
interface Image implements Resource & Node {
id: ID!
thumbnail: String
}
"#;
let errors = Schema::parse_and_validate(input, "schema.graphql")
.unwrap_err()
.errors
.to_string();
assert!(
errors
.contains("type `Image` does not satisfy interface `Resource`: missing field `width`"),
"{errors}"
);
}
#[test]
fn it_generates_diagnostics_for_non_output_field_types() {
let input = r#"
query mainPage {
name {
width
}
}
type Query {
name: mainInterface
}
interface mainInterface {
width: Int
img: Url
relationship: Person
entity: NamedEntity
depth: Number
result: SearchResult
permissions: Auth
coordinates: Point2D
main: mainPage
}
type Person {
name: String
age: Int
}
type Photo {
size: Int
type: String
}
interface NamedEntity {
name: String
}
enum Number {
INT
FLOAT
}
union SearchResult = Photo | Person
directive @Auth(username: String!) repeatable on OBJECT | INTERFACE
input Point2D {
x: Float
y: Float
}
scalar Url @specifiedBy(url: "https://tools.ietf.org/html/rfc3986")
"#;
let errors = Parser::new()
.parse_mixed_validate(input, "doc.graphql")
.unwrap_err()
.to_string();
assert!(
errors.contains("`coordinates` field must return an output type"),
"{errors}"
);
}