graphql 1.4.5 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|