Repository URL to install this package:
|
Version:
1.8.2 ▾
|
# frozen_string_literal: true
require "spec_helper"
describe GraphQL::Language::DocumentFromSchemaDefinition do
let(:subject) { GraphQL::Language::DocumentFromSchemaDefinition }
describe "#document" do
let(:schema_idl) { <<-GRAPHQL
type QueryType {
foo: Foo
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Site
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: String): Type
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
type Type {
a: String
}
input InputType {
key: String!
answer: Int = 42
}
type MutationType {
a(input: InputType): String
}
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
union Union = Type | QueryType
schema {
query: QueryType
mutation: MutationType
}
GRAPHQL
}
let(:schema) { GraphQL::Schema.from_definition(schema_idl) }
let(:expected_document) { GraphQL.parse(expected_idl) }
describe "when printing and schema respects root name conventions" do
let(:schema_idl) { <<-GRAPHQL
type Query {
foo: Foo
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Site
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: String): Type
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
type Type {
a: String
}
input InputType {
key: String!
answer: Int = 42
}
type Mutation {
a(input: InputType): String
}
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
union Union = Type | Query
schema {
query: Query
mutation: Mutation
}
GRAPHQL
}
let(:expected_idl) { <<-GRAPHQL
type QueryType {
foo: Foo
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Site
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: String): Type
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
type Type {
a: String
}
input InputType {
key: String!
answer: Int = 42
}
type MutationType {
a(input: InputType): String
}
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
union Union = Type | QueryType
GRAPHQL
}
let(:document) {
subject.new(
schema
).document
}
it "returns the IDL without introspection, built ins and schema root" do
assert equivalent_node?(expected_document, document)
end
end
describe "with defaults" do
let(:expected_idl) { <<-GRAPHQL
type QueryType {
foo: Foo
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Site
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: String): Type
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
type Type {
a: String
}
input InputType {
key: String!
answer: Int = 42
}
type MutationType {
a(input: InputType): String
}
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
union Union = Type | QueryType
schema {
query: QueryType
mutation: MutationType
}
GRAPHQL
}
let(:document) {
subject.new(
schema
).document
}
it "returns the IDL without introspection, built ins and schema if it doesnt respect name conventions" do
assert equivalent_node?(expected_document, document)
end
end
describe "with an except filter" do
let(:expected_idl) { <<-GRAPHQL
type QueryType {
foo: Foo
}
type Foo implements Bar {
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): Site
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
input InputType {
key: String!
answer: Int = 42
}
type MutationType {
a(input: InputType): String
}
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
schema {
query: QueryType
mutation: MutationType
}
GRAPHQL
}
let(:document) {
subject.new(
schema,
except: ->(m, _ctx) { m.is_a?(GraphQL::BaseType) && m.name == "Type" }
).document
}
it "returns the IDL minus the filtered members" do
assert equivalent_node?(expected_document, document)
end
end
describe "with an only filter" do
let(:expected_idl) { <<-GRAPHQL
type QueryType {
foo: Foo
}
type Foo implements Bar {
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): Site
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
input InputType {
key: String!
answer: Int = 42
}
type MutationType {
a(input: InputType): String
}
enum Site {
DESKTOP
MOBILE
}
schema {
query: QueryType
mutation: MutationType
}
GRAPHQL
}
let(:document) {
subject.new(
schema,
only: ->(m, _ctx) { !(m.is_a?(GraphQL::ScalarType) && m.name == "CustomScalar") }
).document
}
it "returns the IDL minus the filtered members" do
assert equivalent_node?(expected_document, document)
end
end
describe "when excluding built ins and introspection types" do
let(:expected_idl) { <<-GRAPHQL
type QueryType {
foo: Foo
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Site
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: String): Type
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
type Type {
a: String
}
input InputType {
key: String!
answer: Int = 42
}
type MutationType {
a(input: InputType): String
}
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
union Union = Type | QueryType
schema {
query: QueryType
mutation: MutationType
}
GRAPHQL
}
let(:document) {
subject.new(
schema,
always_include_schema: true
).document
}
it "returns the schema idl besides introspection types and built ins" do
assert equivalent_node?(expected_document, document)
end
end
describe "when printing excluding only introspection types" do
let(:expected_idl) { <<-GRAPHQL
# Represents `true` or `false` values.
scalar Boolean
# Represents textual data as UTF-8 character sequences. This type is most often
# used by GraphQL to represent free-form human-readable text.
scalar String
type QueryType {
foo: Foo
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): CustomScalar
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: String): Type
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
type Type {
a: String
}
input InputType {
key: String!
answer: Int = 42
}
# Represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
scalar Int
type MutationType {
a(input: InputType): String
}
# Represents signed double-precision fractional values as specified by [IEEE
# 754](http://en.wikipedia.org/wiki/IEEE_floating_point).
scalar Float
# Represents a unique identifier that is Base64 obfuscated. It is often used to
# refetch an object or as key for a cache. The ID type appears in a JSON response
# as a String; however, it is not intended to be human-readable. When expected as
# an input type, any string (such as `"VXNlci0xMA=="`) or integer (such as `4`)
# input value will be accepted as an ID.
scalar ID
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
union Union = Type | QueryType
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
# Marks an element of a GraphQL schema as no longer supported.
directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE
schema {
query: QueryType
mutation: MutationType
}
GRAPHQL
}
let(:document) {
subject.new(
schema,
include_built_in_scalars: true,
include_built_in_directives: true,
).document
}
it "returns the the schema IDL including only the built ins and not introspection types" do
assert equivalent_node?(expected_document, document)
end
end
describe "when printing the full schema" do
let(:expected_idl) { <<-GRAPHQL
# Represents `true` or `false` values.
scalar Boolean
# Represents textual data as UTF-8 character sequences. This type is most often
# used by GraphQL to represent free-form human-readable text.
scalar String
# The fundamental unit of any GraphQL Schema is the type. There are many kinds of
# types in GraphQL as represented by the `__TypeKind` enum.
#
# Depending on the kind of a type, certain fields describe information about that
# type. Scalar types provide no information beyond a name and description, while
# Enum types provide their values. Object and Interface types provide the fields
# they describe. Abstract types, Union and Interface, provide the Object types
# possible at runtime. List and NonNull types compose other types.
type __Type {
kind: __TypeKind!
name: String
description: String
fields(includeDeprecated: Boolean = false): [__Field!]
interfaces: [__Type!]
possibleTypes: [__Type!]
enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
inputFields: [__InputValue!]
ofType: __Type
}
# An enum describing what kind of type a given `__Type` is.
enum __TypeKind {
# Indicates this type is a scalar.
SCALAR
# Indicates this type is an object. `fields` and `interfaces` are valid fields.
OBJECT
# Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.
INTERFACE
# Indicates this type is a union. `possibleTypes` is a valid field.
UNION
# Indicates this type is an enum. `enumValues` is a valid field.
ENUM
# Indicates this type is an input object. `inputFields` is a valid field.
INPUT_OBJECT
# Indicates this type is a list. `ofType` is a valid field.
LIST
# Indicates this type is a non-null. `ofType` is a valid field.
NON_NULL
}
# Object and Interface types are described by a list of Fields, each of which has
# a name, potentially a list of arguments, and a return type.
type __Field {
name: String!
description: String
args: [__InputValue!]!
type: __Type!
isDeprecated: Boolean!
deprecationReason: String
}
# Arguments provided to Fields or Directives and the input fields of an
# InputObject are represented as Input Values which describe their type and
# optionally a default value.
type __InputValue {
name: String!
description: String
type: __Type!
# A GraphQL-formatted string representing the default value for this input value.
defaultValue: String
}
# One possible value for a given Enum. Enum values are unique values, not a
# placeholder for a string or numeric value. However an Enum value is returned in
# a JSON response as a string.
type __EnumValue {
name: String!
description: String
isDeprecated: Boolean!
deprecationReason: String
}
type QueryType {
foo: Foo
}
type Foo implements Bar {
one: Type
two(argument: InputType!): Type
three(argument: InputType, other: String): Int
four(argument: String = "string"): String
five(argument: [String] = ["string", "string"]): String
six(argument: String): Type
}
interface Bar {
one: Type
four(argument: String = "string"): String
}
type Type {
a: String
}
input InputType {
key: String!
answer: Int = 42
}
# Represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
scalar Int
type MutationType {
a(input: InputType): String
}
# A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all
# available types and directives on the server, as well as the entry points for
# query, mutation, and subscription operations.
type __Schema {
# A list of all types supported by this server.
types: [__Type!]!
# The type that query operations will be rooted at.
queryType: __Type!
# If this server supports mutation, the type that mutation operations will be rooted at.
mutationType: __Type
# If this server support subscription, the type that subscription operations will be rooted at.
subscriptionType: __Type
# A list of all directives supported by this server.
directives: [__Directive!]!
}
# A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
#
# In some cases, you need to provide options to alter GraphQL's execution behavior
# in ways field arguments will not suffice, such as conditionally including or
# skipping a field. Directives provide this by describing additional information
# to the executor.
type __Directive {
name: String!
description: String
locations: [__DirectiveLocation!]!
args: [__InputValue!]!
onOperation: Boolean!
onFragment: Boolean!
onField: Boolean!
}
# A Directive can be adjacent to many parts of the GraphQL language, a
# __DirectiveLocation describes one such possible adjacencies.
enum __DirectiveLocation {
# Location adjacent to a query operation.
QUERY
# Location adjacent to a mutation operation.
MUTATION
# Location adjacent to a subscription operation.
SUBSCRIPTION
# Location adjacent to a field.
FIELD
# Location adjacent to a fragment definition.
FRAGMENT_DEFINITION
# Location adjacent to a fragment spread.
FRAGMENT_SPREAD
# Location adjacent to an inline fragment.
INLINE_FRAGMENT
# Location adjacent to a schema definition.
SCHEMA
# Location adjacent to a scalar definition.
SCALAR
# Location adjacent to an object type definition.
OBJECT
# Location adjacent to a field definition.
FIELD_DEFINITION
# Location adjacent to an argument definition.
ARGUMENT_DEFINITION
# Location adjacent to an interface definition.
INTERFACE
# Location adjacent to a union definition.
UNION
# Location adjacent to an enum definition.
ENUM
# Location adjacent to an enum value definition.
ENUM_VALUE
# Location adjacent to an input object type definition.
INPUT_OBJECT
# Location adjacent to an input object field definition.
INPUT_FIELD_DEFINITION
}
# Represents signed double-precision fractional values as specified by [IEEE
# 754](http://en.wikipedia.org/wiki/IEEE_floating_point).
scalar Float
# Represents a unique identifier that is Base64 obfuscated. It is often used to
# refetch an object or as key for a cache. The ID type appears in a JSON response
# as a String; however, it is not intended to be human-readable. When expected as
# an input type, any string (such as `"VXNlci0xMA=="`) or integer (such as `4`)
# input value will be accepted as an ID.
scalar ID
# Scalar description
scalar CustomScalar
enum Site {
DESKTOP
MOBILE
}
union Union = Type | QueryType
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
# Marks an element of a GraphQL schema as no longer supported.
directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ENUM_VALUE
schema {
query: QueryType
mutation: MutationType
}
GRAPHQL
}
let(:document) {
subject.new(
schema,
include_introspection_types: true,
include_built_in_directives: true,
include_built_in_scalars: true,
always_include_schema: true,
).document
}
it "returns the full document AST from the given schema including built ins and introspection" do
assert equivalent_node?(expected_document, document)
end
end
end
private
def equivalent_node?(expected, node)
return false unless expected.is_a?(node.class)
if expected.respond_to?(:children) && expected.respond_to?(:scalars)
children_equal = expected.children.all? do |expected_child|
node.children.find { |child| equivalent_node?(expected_child, child) }
end
scalars_equal = expected.children.all? do |expected_child|
node.children.find { |child| equivalent_node?(expected_child, child) }
end
children_equal && scalars_equal
else
expected == node
end
end
end