-
# frozen_string_literal: true
-
-
1
require_relative './gqli/dsl'
-
1
require_relative './gqli/client'
-
1
require_relative './gqli/introspection'
-
1
require_relative './gqli/version'
-
# frozen_string_literal: true
-
-
1
require_relative './enum_value'
-
-
1
module GQLi
-
# Base class for GraphQL type wrappers
-
1
class Base
-
1
attr_reader :__name, :__depth, :__nodes
-
-
1
def initialize(name = nil, depth = 0, &block)
-
358
@__name = name
-
358
@__depth = depth
-
358
@__nodes = []
-
358
instance_eval(&block) unless block.nil?
-
end
-
-
# Inlines fragment nodes into current node
-
1
def ___(fragment)
-
10
@__nodes += __clone_nodes(fragment)
-
end
-
-
# Adds type match node
-
1
def __on(type_name, &block)
-
3
__node("... on #{type_name}", {}, &block)
-
end
-
-
# Adds children node into current node
-
1
def __node(name, params = {}, &block)
-
144
require_relative './node'
-
144
@__nodes << Node.new(name, params, __depth + 1, &block)
-
end
-
-
# Creates an EnumType value
-
1
def __enum(value)
-
2
EnumValue.new(value)
-
end
-
-
1
protected
-
-
1
def __clone_nodes(node_container)
-
182
require_relative './node'
-
182
__clone(node_container.__nodes).map do |n|
-
172
node = Node.new(n.__name, n.__params, __depth + 1)
-
172
node.instance_variable_set(
-
:@__nodes,
-
node.send(:__clone_nodes, n)
-
)
-
172
node
-
end
-
end
-
-
1
def __clone(obj)
-
182
Marshal.load(Marshal.dump(obj))
-
end
-
-
1
def __params_from_args(args)
-
139
args.empty? ? {} : args[0]
-
end
-
-
1
def method_missing(name, *args, &block)
-
139
__node(name.to_s, __params_from_args(args), &block)
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require 'http'
-
1
require 'json'
-
1
require_relative './response'
-
1
require_relative './introspection'
-
1
require_relative './version'
-
-
1
module GQLi
-
# GraphQL HTTP Client
-
1
class Client
-
1
attr_reader :url, :params, :headers, :validate_query, :schema
-
-
1
def initialize(url, params: {}, headers: {}, validate_query: true)
-
24
@url = url
-
24
@params = params
-
24
@headers = headers
-
24
@validate_query = validate_query
-
-
24
@schema = Introspection.new(self) if validate_query
-
end
-
-
# Executes a query
-
# If validations are enabled, will perform validation check before request.
-
1
def execute(query)
-
4
if validate_query
-
3
validation = schema.validate(query)
-
3
fail validation_error_message(validation) unless validation.valid?
-
end
-
-
3
execute!(query)
-
end
-
-
# Executres a query
-
# Ignores validations
-
1
def execute!(query)
-
26
http_response = HTTP.headers(request_headers).post(@url, params: @params, json: { query: query.to_gql })
-
-
26
fail "Error: #{http_response.reason}\nBody: #{http_response.body}" if http_response.status >= 300
-
-
24
data = JSON.parse(http_response.to_s)['data']
-
-
24
Response.new(data, query)
-
end
-
-
# Validates a query against the schema
-
1
def valid?(query)
-
return true unless validate_query
-
-
schema.valid?(query)
-
end
-
-
1
protected
-
-
1
def validation_error_message(validation)
-
1
<<~ERROR
-
Validation Error: query is invalid - HTTP Request not sent.
-
-
Errors:
-
- #{validation.errors.join("\n - ")}
-
ERROR
-
end
-
-
1
def request_headers
-
{
-
accept: 'application/json',
-
user_agent: "gqli.rb/#{VERSION}; http.rb/#{HTTP::VERSION}"
-
26
}.merge(@headers)
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require_relative './query'
-
1
require_relative './fragment'
-
1
require_relative './enum_value'
-
-
1
module GQLi
-
# GraphQL-like DSL methods
-
1
module DSL
-
# Creates a Query object
-
#
-
# Can be used at a class level
-
1
def self.query(name = nil, &block)
-
32
Query.new(name, &block)
-
end
-
-
# Creates a Fragment object
-
#
-
# Can be used at a class level
-
1
def self.fragment(name, on, &block)
-
3
Fragment.new(name, on, &block)
-
end
-
-
# Creates a EnumValue object
-
#
-
# Can be used at a class level
-
1
def self.enum(value)
-
1
EnumValue.new(value)
-
end
-
-
# Creates a Query object
-
#
-
# Can be used at an instance level
-
1
def query(name = nil, &block)
-
3
Query.new(name, &block)
-
end
-
-
# Creates a Fragment object
-
#
-
# Can be used at an instance level
-
1
def fragment(name, on, &block)
-
4
Fragment.new(name, on, &block)
-
end
-
-
# Creates a EnumValue object
-
#
-
# Can be used at an instance level
-
1
def enum(value)
-
1
EnumValue.new(value)
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module GQLi
-
# Wrapper for Enum values
-
1
class EnumValue
-
1
attr_reader :value
-
-
1
def initialize(value)
-
4
@value = value
-
end
-
-
# Serializes the enum value to string
-
1
def to_s
-
5
value.to_s
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require_relative './base'
-
1
require_relative './node'
-
-
1
module GQLi
-
# Fragment wrapper
-
1
class Fragment < Base
-
1
attr_reader :__on_type
-
-
1
def initialize(name, on, &block)
-
7
super(name, 0, &block)
-
7
@__on_type = on
-
end
-
-
# Serializes to a GraphQL string
-
1
def to_gql
-
2
<<~GQL
-
fragment #{__name} on #{__on_type} {
-
#{__nodes.map(&:to_gql).join("\n")}
-
}
-
GQL
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require_relative './dsl'
-
1
require_relative './validation'
-
-
1
module GQLi
-
# Introspection schema and validator
-
1
class Introspection
-
1
extend DSL
-
-
# Specific type kind introspection fragment
-
1
TypeRef = fragment('TypeRef', '__Type') {
-
1
kind
-
1
name
-
1
ofType {
-
1
kind
-
1
name
-
1
ofType {
-
1
kind
-
1
name
-
1
ofType {
-
1
kind
-
1
name
-
}
-
}
-
}
-
}
-
-
# Input value introspection fragment
-
1
InputValue = fragment('InputValue', '__InputValue') {
-
1
name
-
1
description
-
2
type { ___ TypeRef }
-
1
defaultValue
-
}
-
-
# Type introspection fragment
-
1
FullType = fragment('FullType', '__Type') {
-
1
kind
-
1
name
-
1
description
-
1
fields(includeDeprecated: true) {
-
1
name
-
1
description
-
2
args { ___ InputValue }
-
2
type { ___ TypeRef }
-
1
isDeprecated
-
1
deprecationReason
-
}
-
2
inputFields { ___ InputValue }
-
2
interfaces { ___ TypeRef }
-
1
enumValues(includeDeprecated: true) {
-
1
name
-
1
description
-
1
isDeprecated
-
1
deprecationReason
-
}
-
2
possibleTypes { ___ TypeRef }
-
}
-
-
# Query for fetching the complete schema
-
1
IntrospectionQuery = query {
-
1
__schema {
-
2
queryType { name }
-
2
mutationType { name }
-
2
subscriptionType { name }
-
2
types { ___ FullType }
-
1
directives {
-
1
name
-
1
description
-
2
args { ___ InputValue }
-
1
onOperation
-
1
onFragment
-
1
onField
-
}
-
}
-
}
-
-
1
attr_reader :schema, :query_type, :mutation_type, :subscription_type, :types
-
-
1
def initialize(client)
-
22
@schema = client.execute!(IntrospectionQuery).data.__schema
-
22
@query_type = schema.queryType
-
22
@mutation_type = schema.mutationType
-
22
@subscription_type = schema.subscriptionType
-
22
@types = schema.types
-
end
-
-
# Returns the evaluated validation for a query
-
1
def validate(query)
-
30
Validation.new(self, query)
-
end
-
-
# Returns if the query is valid
-
1
def valid?(query)
-
10
validate(query).valid?
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require_relative './base'
-
-
1
module GQLi
-
# Node wrapper
-
1
class Node < Base
-
1
attr_reader :__params
-
-
1
def initialize(name, params = {}, depth = 1, &block)
-
316
super(name, depth, &block)
-
316
@__params = params
-
end
-
-
# Serializes to a GraphQL string
-
1
def to_gql
-
2489
result = ' ' * __depth + __name
-
2489
result += __params_to_s(__params, true) unless __params.empty?
-
2489
unless __nodes.empty?
-
789
result += " {\n"
-
789
result += __nodes.map(&:to_gql).join("\n")
-
789
result += "\n#{' ' * __depth}}"
-
end
-
-
2489
result
-
end
-
-
1
private
-
-
1
def __directive?(params)
-
55
params.size == 1 && params.keys.first.to_s.start_with?('@')
-
end
-
-
1
def __directive(params)
-
2
params.first.tap do |directive, directive_params|
-
2
return " #{directive}#{__params_to_s(directive_params, true)}"
-
end
-
end
-
-
1
def __params_to_s(params, initial = false)
-
109
case params
-
when ::Hash
-
55
return __directive(params) if __directive?(params)
-
-
53
result = params.map do |k, v|
-
53
"#{k}: #{__params_to_s(v)}"
-
end.join(', ')
-
-
53
return "(#{result})" if initial
-
-
1
"{#{result}}"
-
when ::Array
-
3
"[#{params.map { |p| __params_to_s(p) }.join(', ')}]"
-
when ::String
-
2
"\"#{params}\""
-
else
-
51
params.to_s
-
end
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require_relative './base'
-
-
1
module GQLi
-
# Query node
-
1
class Query < Base
-
# Serializes to a GraphQL string
-
1
def to_gql
-
40
result = <<~GQL
-
query #{__name ? __name + ' ' : ''}{
-
#{__nodes.map(&:to_gql).join("\n")}
-
}
-
GQL
-
-
40
result.lstrip
-
end
-
-
# Delegates itself to the client to be executed
-
1
def __execute(client)
-
1
client.execute(self)
-
end
-
-
# Serializes to a GraphQL string
-
1
def to_s
-
1
to_gql
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
require 'hashie/mash'
-
-
1
module GQLi
-
# Response object wrapper
-
1
class Response
-
1
attr_reader :data, :query
-
-
1
def initialize(data, query)
-
24
@data = Hashie::Mash.new(data)
-
24
@query = query
-
end
-
end
-
end
-
# frozen_string_literal: true
-
-
1
module GQLi
-
# Validations
-
1
class Validation
-
1
attr_reader :schema, :query, :errors
-
-
1
def initialize(schema, query)
-
30
@schema = schema
-
30
@query = query
-
30
@errors = []
-
-
30
validate
-
end
-
-
# Returns wether the query is valid or not
-
1
def valid?
-
30
errors.empty?
-
end
-
-
1
protected
-
-
1
def validate
-
30
fail 'Not a Query object' unless query.is_a?(Query)
-
-
60
query_type = types.find { |t| t.name.casecmp('query').zero? }
-
30
query.__nodes.each do |node|
-
30
begin
-
30
validate_node(query_type, node)
-
rescue StandardError => e
-
12
errors << e
-
end
-
end
-
-
30
true
-
rescue StandardError => e
-
errors << e
-
end
-
-
1
private
-
-
1
def types
-
132
schema.types
-
end
-
-
1
def validate_node(parent_type, node)
-
88
validate_directives(node)
-
-
85
return valid_match_node?(parent_type, node) if node.__name.start_with?('... on')
-
-
449
node_type = parent_type.fetch('fields', []).find { |f| f.name == node.__name }
-
81
fail "Node type not found for '#{node.__name}'" if node_type.nil?
-
-
78
validate_params(node_type, node)
-
-
78
resolved_node_type = type_for(node_type)
-
78
fail "Node type not found for '#{node.__name}'" if resolved_node_type.nil?
-
-
78
validate_nesting_node(resolved_node_type, node)
-
-
132
node.__nodes.each { |n| validate_node(resolved_node_type, n) }
-
end
-
-
1
def valid_match_node?(parent_type, node)
-
14
return if parent_type.fetch('possibleTypes', []).find { |t| t.name == node.__name.gsub('... on ', '') }
-
2
fail "Match type '#{node.__name.gsub('... on ', '')}' invalid"
-
end
-
-
1
def validate_directives(node)
-
88
return unless node.__params.size == 1
-
17
node.__params.first.tap do |k, v|
-
17
break unless k.to_s.start_with?('@')
-
-
7
fail "Directive unknown '#{k}'" unless %i[@include @skip].include?(k)
-
6
fail "Missing arguments for directive '#{k}'" if v.nil? || !v.is_a?(::Hash) || v.empty?
-
4
v.each do |arg, value|
-
5
begin
-
5
fail "Invalid argument '#{arg}' for directive '#{k}'" if arg.to_s != 'if'
-
3
fail "Invalid value for 'if`, must be a boolean" if value != !!value
-
rescue StandardError => e
-
3
errors << e
-
end
-
end
-
end
-
end
-
-
1
def validate_params(node_type, node)
-
98
node.__params.reject { |p, _| p.to_s.start_with?('@') }.each do |param, value|
-
16
begin
-
90
arg = node_type.fetch('args', []).find { |a| a.name == param.to_s }
-
16
fail "Invalid argument '#{param}'" if arg.nil?
-
-
14
arg_type = type_for(arg)
-
14
fail "Argument type not found for '#{param}'" if arg_type.nil?
-
-
14
validate_value_for_type(arg_type, value, param)
-
rescue StandardError => e
-
8
errors << e
-
end
-
end
-
end
-
-
1
def validate_nesting_node(node_type, node)
-
78
fail "Invalid object for node '#{node.__name}'" unless valid_object_node?(node_type, node)
-
end
-
-
1
def valid_object_node?(node_type, node)
-
78
return false if %w[OBJECT INTERFACE].include?(node_type.kind) && node.__nodes.empty?
-
74
true
-
end
-
-
1
def valid_array_node?(node_type, node)
-
return false if %w[OBJECT INTERFACE].include?(node_type.kind) && node.__nodes.empty?
-
true
-
end
-
-
1
def value_type_error(is_type, should_be, for_arg)
-
6
should_be = should_be.kind == 'ENUM' ? 'Enum' : should_be.name
-
6
additional_message = '. Wrap the value with `__enum`.' if should_be == 'Enum'
-
-
6
fail "Value is '#{is_type}', but should be '#{should_be}' for '#{for_arg}'#{additional_message}"
-
end
-
-
1
def validate_value_for_type(arg_type, value, for_arg)
-
20
case value
-
when EnumValue
-
2
if arg_type.kind == 'ENUM' && !arg_type.enumValues.map(&:name).include?(value.to_s)
-
fail "Invalid value for Enum '#{arg_type.name}' for '#{for_arg}'"
-
end
-
when ::String
-
10
unless arg_type.name == 'String' || arg_type.name == 'ID'
-
4
value_type_error('String or ID', arg_type, for_arg)
-
end
-
when ::Integer
-
4
value_type_error('Integer', arg_type, for_arg) unless arg_type.name == 'Int'
-
when ::Float
-
value_type_error('Float', arg_type, for_arg) unless arg_type.name == 'Float'
-
when ::Hash
-
4
validate_hash_value(arg_type, value, for_arg)
-
when true, false
-
value_type_error('Boolean', arg_type, for_arg) unless arg_type.name == 'Boolean'
-
else
-
value_type_error(value.class.name, arg_type, for_arg)
-
end
-
end
-
-
1
def validate_hash_value(arg_type, value, for_arg)
-
4
value_type_error('Object', arg_type.name, for_arg) unless arg_type.kind == 'INPUT_OBJECT'
-
-
96
type = types.find { |f| f.name == arg_type.name }
-
4
fail "Type not found for '#{arg_type.name}'" if type.nil?
-
-
4
value.each do |k, v|
-
6
begin
-
104
input_field = type.fetch('inputFields', []).find { |f| f.name == k.to_s }
-
6
fail "Input field definition not found for '#{k}'" if input_field.nil?
-
-
6
input_field_type = type_for(input_field)
-
6
fail "Input field type not found for '#{k}'" if input_field_type.nil?
-
-
6
validate_value_for_type(input_field_type, v, k)
-
rescue StandardError => e
-
errors << e
-
end
-
end
-
end
-
-
1
def type_for(field_type)
-
98
type = case field_type.type.kind
-
when 'NON_NULL'
-
22
non_null_type(field_type.type.ofType)
-
when 'LIST'
-
8
field_type.type.ofType
-
when 'OBJECT', 'INTERFACE', 'INPUT_OBJECT'
-
32
field_type.type
-
when 'SCALAR'
-
36
field_type.type
-
end
-
-
978
types.find { |t| t.name == type.name }
-
end
-
-
1
def non_null_type(non_null)
-
22
case non_null.kind
-
when 'LIST'
-
22
non_null.ofType
-
else
-
non_null
-
end
-
end
-
end
-
end
-
1
require 'spec_helper'
-
-
1
describe GQLi::Introspection do
-
18
let(:dsl) { GQLi::DSL }
-
1
let(:client) do
-
18
vcr('client') {
-
18
space_id = 'cfexampleapi'
-
18
token = 'b4c0n73n7fu1'
-
18
GQLi::Client.new(
-
"https://graphql.contentful.com/content/v1/spaces/#{space_id}",
-
headers: { "Authorization" => "Bearer #{token}" }
-
)
-
}
-
end
-
-
19
subject { client.schema }
-
-
1
describe 'introspection schema' do
-
1
it 'queries the API for the schema' do
-
1
expect(subject.types).not_to be_empty
-
-
1
expect(subject.types.map(&:name)).to include('Cat', 'CatCollection', 'Human')
-
end
-
end
-
-
1
describe 'validations' do
-
1
it 'valid query returns true' do
-
1
query = dsl.query {
-
catCollection(
-
locale:"en-US",
-
limit: 1,
-
where: {
-
name:"Nyan Cat",
-
OR: {
-
name:"Happy Cat"
-
}
-
}
-
1
) {
-
1
items {
-
1
name
-
1
color
-
1
birthday
-
1
lives
-
1
bestFriend {
-
1
__on('Cat') {
-
1
name
-
}
-
}
-
1
image {
-
1
url
-
}
-
}
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_truthy
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_truthy
-
1
expect(validation.errors).to be_empty
-
end
-
-
1
it 'wrong node returns false' do
-
1
query = dsl.query {
-
1
foo
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Node type not found for 'foo'")
-
end
-
-
1
it 'object node that doesnt have proper values returns false' do
-
1
query = dsl.query {
-
1
catCollection
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Invalid object for node 'catCollection'")
-
end
-
-
1
it 'object list node that doesnt have proper values returns false' do
-
1
query = dsl.query {
-
1
catCollection {
-
1
items
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Invalid object for node 'items'")
-
end
-
-
1
it 'type matching on invalid type returns false' do
-
1
query = dsl.query {
-
1
catCollection {
-
1
items {
-
1
bestFriend {
-
1
__on('InvalidType') {
-
1
foo
-
}
-
}
-
}
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Match type 'InvalidType' invalid")
-
end
-
-
1
it 'invalid arguments return false' do
-
1
query = dsl.query {
-
1
catCollection(invalidParam: 1) {
-
1
items {
-
1
name
-
}
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Invalid argument 'invalidParam'")
-
end
-
-
1
it 'invalid argument type returns false' do
-
1
query = dsl.query {
-
1
catCollection(limit: 'foo') {
-
1
items {
-
1
name
-
}
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Value is 'String or ID', but should be 'Int' for 'limit'")
-
end
-
-
1
describe 'enum values' do
-
1
it 'can create a query with an enum as a filter and validations should not fail' do
-
1
query = dsl.query {
-
1
catCollection(order: __enum('lives_ASC')) {
-
1
items {
-
1
name
-
}
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_truthy
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_truthy
-
1
expect(validation.errors).to be_empty
-
end
-
-
1
it 'fails when enum value is not provided properly' do
-
1
query = dsl.query {
-
1
catCollection(order: 'lives_ASC') {
-
1
items {
-
1
name
-
}
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Value is 'String or ID', but should be 'Enum' for 'order'. Wrap the value with `__enum`.")
-
end
-
-
1
it 'fails when enum value is not provided properly and is not a string' do
-
1
query = dsl.query {
-
1
catCollection(order: 1) {
-
1
items {
-
1
name
-
}
-
}
-
}
-
-
1
expect(subject.valid?(query)).to be_falsey
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Value is 'Integer', but should be 'Enum' for 'order'. Wrap the value with `__enum`.")
-
end
-
end
-
-
1
describe 'directives' do
-
1
it 'can create a query with a directive and validations should not fail' do
-
1
query = dsl.query {
-
1
catCollection {
-
1
items {
-
1
name(:@include => { if: true })
-
}
-
}
-
}
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_truthy
-
end
-
-
1
it 'unknown directives will fail' do
-
1
query = dsl.query {
-
1
catCollection(:@unknownDirective => nil)
-
}
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Directive unknown '@unknownDirective'")
-
end
-
-
1
it 'known directive will fail if no arguments are passed' do
-
1
query = dsl.query {
-
1
catCollection(:@include => nil)
-
}
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Missing arguments for directive '@include'")
-
end
-
-
1
it 'known directive will fail if arguments are empty' do
-
1
query = dsl.query {
-
1
catCollection(:@include => {})
-
}
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Missing arguments for directive '@include'")
-
end
-
-
1
it 'known directive will fail if arguments is not if' do
-
1
query = dsl.query {
-
1
catCollection {
-
1
items {
-
1
name(:@include => { else: true })
-
}
-
}
-
}
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Invalid argument 'else' for directive '@include'")
-
end
-
-
1
it 'known directive will fail when if value is not boolean' do
-
1
query = dsl.query {
-
1
catCollection {
-
1
items {
-
1
name(:@include => { if: 123 })
-
}
-
}
-
}
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Invalid value for 'if`, must be a boolean")
-
end
-
-
1
it 'known directive will fail when multiple arguments are passed' do
-
1
query = dsl.query {
-
1
catCollection {
-
1
items {
-
1
name(:@include => { if: true, else: false })
-
}
-
}
-
}
-
-
1
validation = subject.validate(query)
-
1
expect(validation.valid?).to be_falsey
-
1
expect(validation.errors).not_to be_empty
-
1
expect(validation.errors.map(&:to_s)).to include("Invalid argument 'else' for directive '@include'")
-
end
-
end
-
end
-
end