use apollo_compiler::schema::SchemaBuilder;
use apollo_compiler::Schema;
#[test]
fn find_definitions_with_directive() {
let schema = r#"
type Query { unused: Int }
type ObjectOne @key(field: "id") {
id: ID!
inStock: Boolean!
}
type ObjectTwo @key(field: "name") {
name: String!
address: String!
}
type ObjectThree {
price: Int
}
directive @key(field: String) on OBJECT
"#;
let schema = Schema::parse_and_validate(schema, "schema.graphql").unwrap();
let mut key_definition_names: Vec<&str> = schema
.types
.iter()
.filter(|(_name, def)| def.directives().has("key"))
.map(|(name, _def)| name.as_str())
.collect();
key_definition_names.sort();
assert_eq!(key_definition_names, ["ObjectOne", "ObjectTwo"])
}
#[test]
fn test_schema_reserialize() {
let input = r#"
extend type Query {
withArg(arg: Boolean): String @deprecated,
}
type Query {
int: Int,
}
extend type Query implements Inter
interface Inter {
string: String
}
extend type Query @customDirective
extend type Query {
string: String,
}
directive @customDirective on OBJECT
"#;
let expected = expect_test::expect![[r#"
directive @customDirective on OBJECT
type Query {
int: Int
}
extend type Query @customDirective
extend type Query implements Inter
extend type Query {
withArg(arg: Boolean): String @deprecated
}
extend type Query {
string: String
}
interface Inter {
string: String
}
"#]];
let schema = Schema::parse_and_validate(input, "schema.graphql").unwrap();
expected.assert_eq(&schema.to_string());
}
#[test]
fn is_subtype() {
fn gen_schema_types(schema: &str) -> Schema {
let base_schema = r#"
type Query {
me: String
}
type Foo {
me: String
}
type Bar {
me: String
}
type Baz {
me: String
}
union UnionType2 = Foo | Bar
"#;
Schema::builder()
.parse(SUPERGRAPH_BOILERPLATE, "boilerplate")
.parse(base_schema, "base")
.parse(schema, "schema")
.build()
.unwrap()
}
fn gen_schema_interfaces(schema: &str) -> Schema {
let base_schema = r#"
type Query {
me: String
}
interface Foo {
me: String
}
interface Bar {
me: String
}
interface Baz {
me: String,
}
type ObjectType2 implements Foo & Bar { me: String }
interface InterfaceType2 implements Foo & Bar { me: String }
"#;
Schema::builder()
.parse(SUPERGRAPH_BOILERPLATE, "boilerplate")
.parse(base_schema, "base")
.parse(schema, "schema")
.build()
.unwrap()
}
let schema = gen_schema_types("union UnionType = Foo | Bar | Baz");
assert!(schema.is_subtype("UnionType", "Foo"));
assert!(schema.is_subtype("UnionType", "Bar"));
assert!(schema.is_subtype("UnionType", "Baz"));
assert!(!schema.is_subtype("UnionType", "UnionType"));
assert!(!schema.is_subtype("UnionType", "Query"));
assert!(!schema.is_subtype("UnionType", "NotAType"));
assert!(!schema.is_subtype("NotAType", "Foo"));
assert!(!schema.is_subtype("Foo", "UnionType"));
let schema = gen_schema_interfaces("type ObjectType implements Foo & Bar & Baz { me: String }");
assert!(schema.is_subtype("Foo", "ObjectType"));
assert!(schema.is_subtype("Bar", "ObjectType"));
assert!(schema.is_subtype("Baz", "ObjectType"));
assert!(!schema.is_subtype("Baz", "ObjectType2"));
assert!(!schema.is_subtype("Foo", "Foo"));
assert!(!schema.is_subtype("Foo", "Query"));
assert!(!schema.is_subtype("Foo", "NotAType"));
assert!(!schema.is_subtype("ObjectType", "Foo"));
let schema =
gen_schema_interfaces("interface InterfaceType implements Foo & Bar & Baz { me: String }");
assert!(schema.is_subtype("Foo", "InterfaceType"));
assert!(schema.is_subtype("Bar", "InterfaceType"));
assert!(schema.is_subtype("Baz", "InterfaceType"));
assert!(!schema.is_subtype("Baz", "InterfaceType2"));
assert!(!schema.is_subtype("Foo", "Foo"));
assert!(!schema.is_subtype("Foo", "Query"));
assert!(!schema.is_subtype("Foo", "NotAType"));
assert!(!schema.is_subtype("InterfaceType", "Foo"));
let schema = gen_schema_types("extend union UnionType2 = Baz");
assert!(schema.is_subtype("UnionType2", "Foo"));
assert!(schema.is_subtype("UnionType2", "Bar"));
assert!(schema.is_subtype("UnionType2", "Baz"));
let schema = gen_schema_interfaces("extend type ObjectType2 implements Baz { me2: String }");
assert!(schema.is_subtype("Foo", "ObjectType2"));
assert!(schema.is_subtype("Bar", "ObjectType2"));
assert!(schema.is_subtype("Baz", "ObjectType2"));
let schema =
gen_schema_interfaces("extend interface InterfaceType2 implements Baz { me2: String }");
assert!(schema.is_subtype("Foo", "InterfaceType2"));
assert!(schema.is_subtype("Bar", "InterfaceType2"));
assert!(schema.is_subtype("Baz", "InterfaceType2"));
}
const SUPERGRAPH_BOILERPLATE: &str = r#"
schema
@core(feature: "https://specs.apollo.dev/core/v0.1")
@core(feature: "https://specs.apollo.dev/join/v0.1") {
query: Query
}
directive @core(feature: String!) repeatable on SCHEMA
directive @join__graph(name: String!, url: String!) on ENUM_VALUE
enum join__Graph {
TEST @join__graph(name: "test", url: "http://localhost:4001/graphql")
}
"#;
#[test]
fn test_default_root_op_name_ignored_with_explicit_schema_def() {
let input = r#"
schema {
query: Query
# no mutation here
}
type Query {
viruses: [Virus!]
}
type Virus {
name: String!
knownMutations: [Mutation!]!
}
type Mutation { # happens to use that name but isn't a root operation
name: String!
geneSequence: String!
}
"#;
let schema = Schema::parse_and_validate(input, "schema.graphql").unwrap();
assert!(schema.schema_definition.mutation.is_none())
}
#[test]
fn handles_implicit_root_types() {
let sdl = r#"
extend type Query {
foo: String
}
extend type Mutation {
bar: String
}
"#;
let builder = SchemaBuilder::new().adopt_orphan_extensions();
let schema = builder
.parse(sdl, "schema.graphql")
.build()
.expect("schema parsed successfully");
assert!(schema.schema_definition.query.is_some());
assert!(schema.schema_definition.mutation.is_some());
}