graphql 1.4.5 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/enum_generator.rb +33 -0
- data/lib/generators/graphql/function_generator.rb +15 -0
- data/lib/generators/graphql/install_generator.rb +118 -0
- data/lib/generators/graphql/interface_generator.rb +27 -0
- data/lib/generators/graphql/loader_generator.rb +17 -0
- data/lib/generators/graphql/mutation_generator.rb +19 -0
- data/lib/generators/graphql/object_generator.rb +34 -0
- data/lib/generators/graphql/templates/enum.erb +4 -0
- data/lib/generators/graphql/templates/function.erb +17 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +32 -0
- data/lib/generators/graphql/templates/interface.erb +4 -0
- data/lib/generators/graphql/templates/loader.erb +15 -0
- data/lib/generators/graphql/templates/mutation.erb +12 -0
- data/lib/generators/graphql/templates/object.erb +5 -0
- data/lib/generators/graphql/templates/query_type.erb +15 -0
- data/lib/generators/graphql/templates/schema.erb +34 -0
- data/lib/generators/graphql/templates/union.erb +4 -0
- data/lib/generators/graphql/type_generator.rb +78 -0
- data/lib/generators/graphql/union_generator.rb +33 -0
- data/lib/graphql.rb +10 -0
- data/lib/graphql/analysis/analyze_query.rb +1 -1
- data/lib/graphql/analysis/query_complexity.rb +6 -50
- data/lib/graphql/analysis/query_depth.rb +1 -1
- data/lib/graphql/argument.rb +21 -0
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +3 -3
- data/lib/graphql/define.rb +1 -0
- data/lib/graphql/define/assign_argument.rb +3 -19
- data/lib/graphql/define/assign_mutation_function.rb +34 -0
- data/lib/graphql/define/assign_object_field.rb +26 -14
- data/lib/graphql/define/defined_object_proxy.rb +21 -0
- data/lib/graphql/define/instance_definable.rb +61 -11
- data/lib/graphql/directive.rb +6 -1
- data/lib/graphql/execution/directive_checks.rb +1 -0
- data/lib/graphql/execution/execute.rb +14 -9
- data/lib/graphql/execution/field_result.rb +1 -0
- data/lib/graphql/execution/lazy.rb +8 -17
- data/lib/graphql/execution/lazy/lazy_method_map.rb +2 -0
- data/lib/graphql/execution/lazy/resolve.rb +1 -0
- data/lib/graphql/execution/selection_result.rb +1 -0
- data/lib/graphql/execution/typecast.rb +39 -26
- data/lib/graphql/field.rb +15 -3
- data/lib/graphql/field/resolve.rb +3 -3
- data/lib/graphql/function.rb +134 -0
- data/lib/graphql/id_type.rb +1 -1
- data/lib/graphql/input_object_type.rb +1 -1
- data/lib/graphql/internal_representation.rb +1 -1
- data/lib/graphql/internal_representation/node.rb +35 -107
- data/lib/graphql/internal_representation/rewrite.rb +189 -183
- data/lib/graphql/internal_representation/visit.rb +38 -0
- data/lib/graphql/introspection/input_value_type.rb +10 -1
- data/lib/graphql/introspection/schema_type.rb +1 -1
- data/lib/graphql/language/lexer.rb +6 -3
- data/lib/graphql/language/lexer.rl +6 -3
- data/lib/graphql/object_type.rb +53 -13
- data/lib/graphql/query.rb +30 -14
- data/lib/graphql/query/arguments.rb +2 -0
- data/lib/graphql/query/context.rb +2 -2
- data/lib/graphql/query/literal_input.rb +9 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +2 -2
- data/lib/graphql/query/serial_execution/selection_resolution.rb +1 -1
- data/lib/graphql/relay.rb +1 -0
- data/lib/graphql/relay/array_connection.rb +1 -1
- data/lib/graphql/relay/base_connection.rb +34 -15
- data/lib/graphql/relay/connection_resolve.rb +7 -2
- data/lib/graphql/relay/mutation.rb +45 -4
- data/lib/graphql/relay/node.rb +18 -6
- data/lib/graphql/relay/range_add.rb +45 -0
- data/lib/graphql/relay/relation_connection.rb +17 -2
- data/lib/graphql/runtime_type_error.rb +1 -0
- data/lib/graphql/schema.rb +40 -5
- data/lib/graphql/schema/base_64_encoder.rb +1 -0
- data/lib/graphql/schema/build_from_definition.rb +56 -21
- data/lib/graphql/schema/default_parse_error.rb +10 -0
- data/lib/graphql/schema/loader.rb +8 -1
- data/lib/graphql/schema/null_mask.rb +1 -0
- data/lib/graphql/schema/validation.rb +35 -0
- data/lib/graphql/static_validation.rb +1 -0
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/arguments_validator.rb +7 -4
- data/lib/graphql/static_validation/definition_dependencies.rb +183 -0
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +28 -96
- data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +23 -0
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -5
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +6 -31
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +11 -41
- data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +2 -2
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -7
- data/lib/graphql/static_validation/validation_context.rb +22 -1
- data/lib/graphql/static_validation/validator.rb +4 -1
- data/lib/graphql/string_type.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +12 -3
- data/spec/generators/graphql/enum_generator_spec.rb +29 -0
- data/spec/generators/graphql/function_generator_spec.rb +33 -0
- data/spec/generators/graphql/install_generator_spec.rb +185 -0
- data/spec/generators/graphql/interface_generator_spec.rb +32 -0
- data/spec/generators/graphql/loader_generator_spec.rb +31 -0
- data/spec/generators/graphql/mutation_generator_spec.rb +28 -0
- data/spec/generators/graphql/object_generator_spec.rb +42 -0
- data/spec/generators/graphql/union_generator_spec.rb +50 -0
- data/spec/graphql/analysis/query_complexity_spec.rb +2 -1
- data/spec/graphql/define/instance_definable_spec.rb +38 -0
- data/spec/graphql/directive/skip_directive_spec.rb +1 -0
- data/spec/graphql/directive_spec.rb +18 -0
- data/spec/graphql/execution/typecast_spec.rb +41 -46
- data/spec/graphql/field_spec.rb +1 -1
- data/spec/graphql/function_spec.rb +128 -0
- data/spec/graphql/internal_representation/rewrite_spec.rb +166 -129
- data/spec/graphql/introspection/type_type_spec.rb +1 -1
- data/spec/graphql/language/lexer_spec.rb +6 -0
- data/spec/graphql/object_type_spec.rb +73 -2
- data/spec/graphql/query/arguments_spec.rb +28 -0
- data/spec/graphql/query/variables_spec.rb +7 -1
- data/spec/graphql/query_spec.rb +30 -0
- data/spec/graphql/relay/base_connection_spec.rb +26 -8
- data/spec/graphql/relay/connection_resolve_spec.rb +45 -0
- data/spec/graphql/relay/connection_type_spec.rb +21 -0
- data/spec/graphql/relay/node_spec.rb +30 -2
- data/spec/graphql/relay/range_add_spec.rb +113 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +114 -0
- data/spec/graphql/schema/loader_spec.rb +1 -0
- data/spec/graphql/schema/printer_spec.rb +2 -2
- data/spec/graphql/schema/validation_spec.rb +80 -11
- data/spec/graphql/schema/warden_spec.rb +10 -10
- data/spec/graphql/schema_spec.rb +18 -1
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +16 -0
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +50 -3
- data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +27 -0
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +57 -0
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +14 -0
- data/spec/graphql/string_type_spec.rb +7 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/support/base_generator_test.rb +7 -0
- data/spec/support/dummy/schema.rb +32 -30
- data/spec/support/star_wars/schema.rb +81 -23
- metadata +98 -20
- data/lib/graphql/internal_representation/selection.rb +0 -85
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require "generators/graphql/interface_generator"
|
4
|
+
|
5
|
+
class GraphQLGeneratorsInterfaceGeneratorTest < BaseGeneratorTest
|
6
|
+
tests Graphql::Generators::InterfaceGenerator
|
7
|
+
|
8
|
+
test "it generates fields with types" do
|
9
|
+
commands = [
|
10
|
+
# GraphQL-style:
|
11
|
+
["Bird", "wingspan:Int!", "foliage:[Color]"],
|
12
|
+
# Ruby-style:
|
13
|
+
["BirdType", "wingspan:!types.Int", "foliage:types[Types::ColorType]"],
|
14
|
+
# Mixed
|
15
|
+
["BirdType", "wingspan:!Int", "foliage:types[Color]"],
|
16
|
+
]
|
17
|
+
|
18
|
+
expected_content = <<-RUBY
|
19
|
+
Types::BirdType = GraphQL::InterfaceType.define do
|
20
|
+
name "Bird"
|
21
|
+
field :wingspan, !types.Int
|
22
|
+
field :foliage, types[Types::ColorType]
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
|
26
|
+
commands.each do |c|
|
27
|
+
prepare_destination
|
28
|
+
run_generator(c)
|
29
|
+
assert_file "app/graphql/types/bird_type.rb", expected_content
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require "generators/graphql/loader_generator"
|
4
|
+
|
5
|
+
class GraphQLGeneratorsLoaderGeneratorTest < BaseGeneratorTest
|
6
|
+
tests Graphql::Generators::LoaderGenerator
|
7
|
+
|
8
|
+
test "it generates an empty loader by name" do
|
9
|
+
run_generator(["RecordLoader"])
|
10
|
+
|
11
|
+
expected_content = <<-RUBY
|
12
|
+
class Loaders::RecordLoader < GraphQL::Batch::Loader
|
13
|
+
# Define `initialize` to store grouping arguments, eg
|
14
|
+
#
|
15
|
+
# Loaders::RecordLoader.for(group).load(value)
|
16
|
+
#
|
17
|
+
# def initialize()
|
18
|
+
# end
|
19
|
+
|
20
|
+
# `keys` contains each key from `.load(key)`.
|
21
|
+
# Find the corresponding values, then
|
22
|
+
# call `fulfill(key, value)` or `fulfill(key, nil)`
|
23
|
+
# for each key.
|
24
|
+
def perform(keys)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
RUBY
|
28
|
+
|
29
|
+
assert_file "app/graphql/loaders/record_loader.rb", expected_content
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require "generators/graphql/mutation_generator"
|
4
|
+
|
5
|
+
class GraphQLGeneratorsMutationGeneratorTest < BaseGeneratorTest
|
6
|
+
tests Graphql::Generators::MutationGenerator
|
7
|
+
|
8
|
+
test "it generates an empty resolver by name" do
|
9
|
+
run_generator(["UpdateName"])
|
10
|
+
|
11
|
+
expected_content = <<-RUBY
|
12
|
+
Mutations::UpdateName = GraphQL::Relay::Mutation.define do
|
13
|
+
name "UpdateName"
|
14
|
+
# TODO: define return fields
|
15
|
+
# return_field :post, Types::PostType
|
16
|
+
|
17
|
+
# TODO: define arguments
|
18
|
+
# input_field :name, !types.String
|
19
|
+
|
20
|
+
resolve ->(obj, args, ctx) {
|
21
|
+
# TODO: define resolve function
|
22
|
+
}
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
|
26
|
+
assert_file "app/graphql/mutations/update_name.rb", expected_content
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require "generators/graphql/object_generator"
|
4
|
+
|
5
|
+
class GraphQLGeneratorsObjectGeneratorTest < BaseGeneratorTest
|
6
|
+
tests Graphql::Generators::ObjectGenerator
|
7
|
+
|
8
|
+
test "it generates fields with types" do
|
9
|
+
commands = [
|
10
|
+
# GraphQL-style:
|
11
|
+
["Bird", "wingspan:Int!", "foliage:[Color]"],
|
12
|
+
# Ruby-style:
|
13
|
+
["BirdType", "wingspan:!types.Int", "foliage:types[Types::ColorType]"],
|
14
|
+
# Mixed
|
15
|
+
["BirdType", "wingspan:!Int", "foliage:types[Color]"],
|
16
|
+
]
|
17
|
+
|
18
|
+
expected_content = <<-RUBY
|
19
|
+
Types::BirdType = GraphQL::ObjectType.define do
|
20
|
+
name "Bird"
|
21
|
+
field :wingspan, !types.Int
|
22
|
+
field :foliage, types[Types::ColorType]
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
|
26
|
+
commands.each do |c|
|
27
|
+
prepare_destination
|
28
|
+
run_generator(c)
|
29
|
+
assert_file "app/graphql/types/bird_type.rb", expected_content
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
test "it makes Relay nodes" do
|
34
|
+
run_generator(["Page", "--node"])
|
35
|
+
assert_file "app/graphql/types/page_type.rb", <<-RUBY
|
36
|
+
Types::PageType = GraphQL::ObjectType.define do
|
37
|
+
name "Page"
|
38
|
+
implements GraphQL::Relay::Node.interface
|
39
|
+
end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
require "generators/graphql/union_generator"
|
4
|
+
|
5
|
+
class GraphQLGeneratorsUnionGeneratorTest < BaseGeneratorTest
|
6
|
+
tests Graphql::Generators::UnionGenerator
|
7
|
+
|
8
|
+
test "it generates a union with possible types" do
|
9
|
+
commands = [
|
10
|
+
# GraphQL-style:
|
11
|
+
["WingedCreature", "Insect", "Bird"],
|
12
|
+
# Ruby-style:
|
13
|
+
["Types::WingedCreatureType", "Types::InsectType", "Types::BirdType"],
|
14
|
+
]
|
15
|
+
|
16
|
+
expected_content = <<-RUBY
|
17
|
+
Types::WingedCreatureType = GraphQL::UnionType.define do
|
18
|
+
name "WingedCreature"
|
19
|
+
possible_types [Types::InsectType, Types::BirdType]
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
|
23
|
+
commands.each do |c|
|
24
|
+
prepare_destination
|
25
|
+
run_generator(c)
|
26
|
+
assert_file "app/graphql/types/winged_creature_type.rb", expected_content
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
test "it works with no possible types" do
|
31
|
+
commands = [
|
32
|
+
# GraphQL-style:
|
33
|
+
["WingedCreature"],
|
34
|
+
# Ruby-style:
|
35
|
+
["Types::WingedCreatureType"],
|
36
|
+
]
|
37
|
+
|
38
|
+
expected_content = <<-RUBY
|
39
|
+
Types::WingedCreatureType = GraphQL::UnionType.define do
|
40
|
+
name "WingedCreature"
|
41
|
+
end
|
42
|
+
RUBY
|
43
|
+
|
44
|
+
commands.each do |c|
|
45
|
+
prepare_destination
|
46
|
+
run_generator(c)
|
47
|
+
assert_file "app/graphql/types/winged_creature_type.rb", expected_content
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -141,6 +141,7 @@ describe GraphQL::Analysis::QueryComplexity do
|
|
141
141
|
describe "when there are no selections on any object types" do
|
142
142
|
let(:query_string) {%|
|
143
143
|
{
|
144
|
+
# 1 for everybody
|
144
145
|
favoriteEdible {
|
145
146
|
# 1 for everybody
|
146
147
|
fatContent
|
@@ -156,7 +157,7 @@ describe GraphQL::Analysis::QueryComplexity do
|
|
156
157
|
|
157
158
|
it "gets the max among interface types" do
|
158
159
|
reduce_result
|
159
|
-
assert_equal
|
160
|
+
assert_equal 4, complexities.last
|
160
161
|
end
|
161
162
|
end
|
162
163
|
|
@@ -116,6 +116,44 @@ describe GraphQL::Define::InstanceDefinable do
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
+
describe "#use" do
|
120
|
+
class TestPlugin
|
121
|
+
attr_reader :target
|
122
|
+
|
123
|
+
def use(defn)
|
124
|
+
@target = defn.target
|
125
|
+
defn.name('Arugula')
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
module TestPluginWithKwargs
|
130
|
+
extend self
|
131
|
+
|
132
|
+
def use(defn, name:)
|
133
|
+
defn.name(name)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it "sends a message to the specified plugin's :use method with access to the proxy object and target object" do
|
138
|
+
plugin = TestPlugin.new
|
139
|
+
|
140
|
+
arugula = Garden::Vegetable.define do
|
141
|
+
use plugin
|
142
|
+
end
|
143
|
+
|
144
|
+
assert_equal 'Arugula', arugula.name
|
145
|
+
assert_equal arugula, plugin.target
|
146
|
+
end
|
147
|
+
|
148
|
+
it "passes kwargs to plugin's `use` method" do
|
149
|
+
arugula = Garden::Vegetable.define do
|
150
|
+
use TestPluginWithKwargs, name: 'Arugula'
|
151
|
+
end
|
152
|
+
|
153
|
+
assert_equal 'Arugula', arugula.name
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
119
157
|
describe "typos" do
|
120
158
|
it "provides the right class name, method name and line number" do
|
121
159
|
err = assert_raises(NoMethodError) {
|
@@ -28,6 +28,24 @@ describe GraphQL::Directive do
|
|
28
28
|
|
|
29
29
|
}
|
30
30
|
|
31
|
+
describe "child fields" do
|
32
|
+
let(:query_string) { <<-GRAPHQL
|
33
|
+
{
|
34
|
+
__type(name: "Cheese") {
|
35
|
+
fields { name }
|
36
|
+
fields @skip(if: true) { isDeprecated }
|
37
|
+
}
|
38
|
+
}
|
39
|
+
GRAPHQL
|
40
|
+
}
|
41
|
+
|
42
|
+
it "skips child fields too" do
|
43
|
+
first_field = result["data"]["__type"]["fields"].first
|
44
|
+
assert first_field.key?("name")
|
45
|
+
assert !first_field.key?("isDeprecated")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
31
49
|
it "intercepts fields" do
|
32
50
|
expected = { "data" =>{
|
33
51
|
"cheese" => {
|
@@ -2,51 +2,46 @@
|
|
2
2
|
require "spec_helper"
|
3
3
|
|
4
4
|
describe GraphQL::Execution::Typecast do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
assert compatible?(Dummy::EdibleInterface, Dummy::CheeseType, context)
|
47
|
-
assert compatible?(Dummy::EdibleInterface, Dummy::MilkType, context)
|
48
|
-
|
49
|
-
assert !compatible?(Dummy::EdibleInterface, GraphQL::STRING_TYPE, context)
|
50
|
-
assert !compatible?(Dummy::EdibleInterface, Dummy::DairyProductInputType, context)
|
5
|
+
describe ".subtype?" do
|
6
|
+
def subtype?(*args)
|
7
|
+
GraphQL::Execution::Typecast.subtype?(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "counts the same type as a subtype" do
|
11
|
+
assert subtype?(Dummy::MilkType, Dummy::MilkType)
|
12
|
+
assert !subtype?(Dummy::MilkType, Dummy::CheeseType)
|
13
|
+
assert subtype?(Dummy::MilkType.to_list_type.to_non_null_type, Dummy::MilkType.to_list_type.to_non_null_type)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "counts member types as subtypes" do
|
17
|
+
assert subtype?(Dummy::EdibleInterface, Dummy::CheeseType)
|
18
|
+
assert subtype?(Dummy::EdibleInterface, Dummy::MilkType)
|
19
|
+
assert subtype?(Dummy::DairyProductUnion, Dummy::MilkType)
|
20
|
+
assert subtype?(Dummy::DairyProductUnion, Dummy::CheeseType)
|
21
|
+
|
22
|
+
assert !subtype?(Dummy::DairyAppQueryType, Dummy::DairyProductUnion)
|
23
|
+
assert !subtype?(Dummy::CheeseType, Dummy::DairyProductUnion)
|
24
|
+
assert !subtype?(Dummy::EdibleInterface, Dummy::DairyProductUnion)
|
25
|
+
assert !subtype?(Dummy::EdibleInterface, GraphQL::STRING_TYPE)
|
26
|
+
assert !subtype?(Dummy::EdibleInterface, Dummy::DairyProductInputType)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "counts lists as subtypes if their inner types are subtypes" do
|
30
|
+
assert subtype?(Dummy::EdibleInterface.to_list_type, Dummy::MilkType.to_list_type)
|
31
|
+
assert subtype?(Dummy::DairyProductUnion.to_list_type, Dummy::MilkType.to_list_type)
|
32
|
+
assert !subtype?(Dummy::CheeseType.to_list_type, Dummy::DairyProductUnion.to_list_type)
|
33
|
+
assert !subtype?(Dummy::EdibleInterface.to_list_type, Dummy::DairyProductUnion.to_list_type)
|
34
|
+
assert !subtype?(Dummy::EdibleInterface.to_list_type, GraphQL::STRING_TYPE.to_list_type)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "counts non-null types as subtypes of nullable parent types" do
|
38
|
+
assert subtype?(Dummy::MilkType, Dummy::MilkType.to_non_null_type)
|
39
|
+
assert subtype?(Dummy::EdibleInterface, Dummy::MilkType.to_non_null_type)
|
40
|
+
assert subtype?(Dummy::EdibleInterface.to_non_null_type, Dummy::MilkType.to_non_null_type)
|
41
|
+
assert subtype?(
|
42
|
+
GraphQL::STRING_TYPE.to_non_null_type.to_list_type,
|
43
|
+
GraphQL::STRING_TYPE.to_non_null_type.to_list_type.to_non_null_type,
|
44
|
+
)
|
45
|
+
end
|
51
46
|
end
|
52
47
|
end
|
data/spec/graphql/field_spec.rb
CHANGED
@@ -126,7 +126,7 @@ describe GraphQL::Field do
|
|
126
126
|
int_field = GraphQL::Field.define do
|
127
127
|
type types.Int
|
128
128
|
argument :value, types.Int
|
129
|
-
resolve ->
|
129
|
+
resolve ->(obj, args, ctx) { args[:value] }
|
130
130
|
end
|
131
131
|
|
132
132
|
query_type = GraphQL::ObjectType.define do
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe GraphQL::Function do
|
5
|
+
class TestFunc < GraphQL::Function
|
6
|
+
argument :name, GraphQL::STRING_TYPE
|
7
|
+
type do
|
8
|
+
name "TestFuncPayload"
|
9
|
+
field :name, types.String, hash_key: :name
|
10
|
+
end
|
11
|
+
|
12
|
+
description "Returns the string you give it"
|
13
|
+
deprecation_reason "It's useless"
|
14
|
+
complexity 9
|
15
|
+
def call(o, a, c)
|
16
|
+
{ name: a[:name] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "function API" do
|
21
|
+
it "exposes required info" do
|
22
|
+
f = TestFunc.new
|
23
|
+
assert_equal ["name"], f.arguments.keys
|
24
|
+
assert_equal "TestFuncPayload", f.type.name
|
25
|
+
assert_equal "Returns the string you give it", f.description
|
26
|
+
assert_equal "It's useless", f.deprecation_reason
|
27
|
+
assert_equal({name: "stuff"}, f.call(nil, { name: "stuff" }, nil))
|
28
|
+
assert_equal 9, f.complexity
|
29
|
+
|
30
|
+
assert_equal TestFunc.new.type, TestFunc.new.type
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "has default values" do
|
35
|
+
default_func = GraphQL::Function.new
|
36
|
+
assert_equal 1, default_func.complexity
|
37
|
+
assert_equal({}, default_func.arguments)
|
38
|
+
assert_equal(nil, default_func.type)
|
39
|
+
assert_equal(nil, default_func.description)
|
40
|
+
assert_equal(nil, default_func.deprecation_reason)
|
41
|
+
assert_raises(NotImplementedError) {
|
42
|
+
default_func.call(nil, nil, nil)
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "use in a schema" do
|
47
|
+
let(:schema) {
|
48
|
+
query_type = GraphQL::ObjectType.define do
|
49
|
+
name "Query"
|
50
|
+
field :test, function: TestFunc.new
|
51
|
+
connection :testConn, function: TestFunc.new
|
52
|
+
end
|
53
|
+
|
54
|
+
relay_mutation = GraphQL::Relay::Mutation.define do
|
55
|
+
name "Test"
|
56
|
+
function TestFunc.new
|
57
|
+
end
|
58
|
+
|
59
|
+
mutation_type = GraphQL::ObjectType.define do
|
60
|
+
name "Mutation"
|
61
|
+
field :test, field: relay_mutation.field
|
62
|
+
end
|
63
|
+
|
64
|
+
GraphQL::Schema.define do
|
65
|
+
query(query_type)
|
66
|
+
mutation(mutation_type)
|
67
|
+
end
|
68
|
+
}
|
69
|
+
|
70
|
+
it "gets attributes from the function" do
|
71
|
+
field = schema.query.fields["test"]
|
72
|
+
assert_equal ["name"], field.arguments.keys
|
73
|
+
assert_equal "TestFuncPayload", field.type.name
|
74
|
+
assert_equal "Returns the string you give it", field.description
|
75
|
+
assert_equal "It's useless", field.deprecation_reason
|
76
|
+
assert_equal({name: "stuff"}, field.resolve(nil, { name: "stuff" }, nil))
|
77
|
+
assert_equal 9, field.complexity
|
78
|
+
end
|
79
|
+
|
80
|
+
it "can be used as a field" do
|
81
|
+
query_str = <<-GRAPHQL
|
82
|
+
{ test(name: "graphql") { name }}
|
83
|
+
GRAPHQL
|
84
|
+
res = schema.execute(query_str)
|
85
|
+
assert_equal "graphql", res["data"]["test"]["name"]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "can be used as a mutation" do
|
89
|
+
query_str = <<-GRAPHQL
|
90
|
+
mutation { test(input: {clientMutationId: "123", name: "graphql"}) { name, clientMutationId } }
|
91
|
+
GRAPHQL
|
92
|
+
res = schema.execute(query_str)
|
93
|
+
assert_equal "graphql", res["data"]["test"]["name"]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "when overriding" do
|
98
|
+
let(:schema) {
|
99
|
+
query_type = GraphQL::ObjectType.define do
|
100
|
+
name "Query"
|
101
|
+
field :blockOverride, function: TestFunc.new do
|
102
|
+
description "I have altered the description"
|
103
|
+
argument :anArg, types.Int
|
104
|
+
argument :oneMoreArg, types.String
|
105
|
+
end
|
106
|
+
|
107
|
+
field :argOverride, types.String, "New Description", function: TestFunc.new
|
108
|
+
end
|
109
|
+
|
110
|
+
GraphQL::Schema.define do
|
111
|
+
query(query_type)
|
112
|
+
end
|
113
|
+
}
|
114
|
+
|
115
|
+
it "can override description" do
|
116
|
+
field = schema.query.fields["blockOverride"]
|
117
|
+
assert_equal "I have altered the description", field.description
|
118
|
+
assert_equal ["name", "anArg", "oneMoreArg"], field.arguments.keys
|
119
|
+
end
|
120
|
+
|
121
|
+
it "can add to arguments" do
|
122
|
+
field = schema.query.fields["argOverride"]
|
123
|
+
assert_equal "New Description", field.description
|
124
|
+
assert_equal GraphQL::STRING_TYPE, field.type
|
125
|
+
assert_equal ["name"], field.arguments.keys
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|