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.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/enum_generator.rb +33 -0
  3. data/lib/generators/graphql/function_generator.rb +15 -0
  4. data/lib/generators/graphql/install_generator.rb +118 -0
  5. data/lib/generators/graphql/interface_generator.rb +27 -0
  6. data/lib/generators/graphql/loader_generator.rb +17 -0
  7. data/lib/generators/graphql/mutation_generator.rb +19 -0
  8. data/lib/generators/graphql/object_generator.rb +34 -0
  9. data/lib/generators/graphql/templates/enum.erb +4 -0
  10. data/lib/generators/graphql/templates/function.erb +17 -0
  11. data/lib/generators/graphql/templates/graphql_controller.erb +32 -0
  12. data/lib/generators/graphql/templates/interface.erb +4 -0
  13. data/lib/generators/graphql/templates/loader.erb +15 -0
  14. data/lib/generators/graphql/templates/mutation.erb +12 -0
  15. data/lib/generators/graphql/templates/object.erb +5 -0
  16. data/lib/generators/graphql/templates/query_type.erb +15 -0
  17. data/lib/generators/graphql/templates/schema.erb +34 -0
  18. data/lib/generators/graphql/templates/union.erb +4 -0
  19. data/lib/generators/graphql/type_generator.rb +78 -0
  20. data/lib/generators/graphql/union_generator.rb +33 -0
  21. data/lib/graphql.rb +10 -0
  22. data/lib/graphql/analysis/analyze_query.rb +1 -1
  23. data/lib/graphql/analysis/query_complexity.rb +6 -50
  24. data/lib/graphql/analysis/query_depth.rb +1 -1
  25. data/lib/graphql/argument.rb +21 -0
  26. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +3 -3
  27. data/lib/graphql/define.rb +1 -0
  28. data/lib/graphql/define/assign_argument.rb +3 -19
  29. data/lib/graphql/define/assign_mutation_function.rb +34 -0
  30. data/lib/graphql/define/assign_object_field.rb +26 -14
  31. data/lib/graphql/define/defined_object_proxy.rb +21 -0
  32. data/lib/graphql/define/instance_definable.rb +61 -11
  33. data/lib/graphql/directive.rb +6 -1
  34. data/lib/graphql/execution/directive_checks.rb +1 -0
  35. data/lib/graphql/execution/execute.rb +14 -9
  36. data/lib/graphql/execution/field_result.rb +1 -0
  37. data/lib/graphql/execution/lazy.rb +8 -17
  38. data/lib/graphql/execution/lazy/lazy_method_map.rb +2 -0
  39. data/lib/graphql/execution/lazy/resolve.rb +1 -0
  40. data/lib/graphql/execution/selection_result.rb +1 -0
  41. data/lib/graphql/execution/typecast.rb +39 -26
  42. data/lib/graphql/field.rb +15 -3
  43. data/lib/graphql/field/resolve.rb +3 -3
  44. data/lib/graphql/function.rb +134 -0
  45. data/lib/graphql/id_type.rb +1 -1
  46. data/lib/graphql/input_object_type.rb +1 -1
  47. data/lib/graphql/internal_representation.rb +1 -1
  48. data/lib/graphql/internal_representation/node.rb +35 -107
  49. data/lib/graphql/internal_representation/rewrite.rb +189 -183
  50. data/lib/graphql/internal_representation/visit.rb +38 -0
  51. data/lib/graphql/introspection/input_value_type.rb +10 -1
  52. data/lib/graphql/introspection/schema_type.rb +1 -1
  53. data/lib/graphql/language/lexer.rb +6 -3
  54. data/lib/graphql/language/lexer.rl +6 -3
  55. data/lib/graphql/object_type.rb +53 -13
  56. data/lib/graphql/query.rb +30 -14
  57. data/lib/graphql/query/arguments.rb +2 -0
  58. data/lib/graphql/query/context.rb +2 -2
  59. data/lib/graphql/query/literal_input.rb +9 -0
  60. data/lib/graphql/query/serial_execution/field_resolution.rb +2 -2
  61. data/lib/graphql/query/serial_execution/selection_resolution.rb +1 -1
  62. data/lib/graphql/relay.rb +1 -0
  63. data/lib/graphql/relay/array_connection.rb +1 -1
  64. data/lib/graphql/relay/base_connection.rb +34 -15
  65. data/lib/graphql/relay/connection_resolve.rb +7 -2
  66. data/lib/graphql/relay/mutation.rb +45 -4
  67. data/lib/graphql/relay/node.rb +18 -6
  68. data/lib/graphql/relay/range_add.rb +45 -0
  69. data/lib/graphql/relay/relation_connection.rb +17 -2
  70. data/lib/graphql/runtime_type_error.rb +1 -0
  71. data/lib/graphql/schema.rb +40 -5
  72. data/lib/graphql/schema/base_64_encoder.rb +1 -0
  73. data/lib/graphql/schema/build_from_definition.rb +56 -21
  74. data/lib/graphql/schema/default_parse_error.rb +10 -0
  75. data/lib/graphql/schema/loader.rb +8 -1
  76. data/lib/graphql/schema/null_mask.rb +1 -0
  77. data/lib/graphql/schema/validation.rb +35 -0
  78. data/lib/graphql/static_validation.rb +1 -0
  79. data/lib/graphql/static_validation/all_rules.rb +1 -0
  80. data/lib/graphql/static_validation/arguments_validator.rb +7 -4
  81. data/lib/graphql/static_validation/definition_dependencies.rb +183 -0
  82. data/lib/graphql/static_validation/rules/fields_will_merge.rb +28 -96
  83. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +23 -0
  84. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -5
  85. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +6 -31
  86. data/lib/graphql/static_validation/rules/fragments_are_used.rb +11 -41
  87. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +2 -2
  88. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -7
  89. data/lib/graphql/static_validation/validation_context.rb +22 -1
  90. data/lib/graphql/static_validation/validator.rb +4 -1
  91. data/lib/graphql/string_type.rb +5 -1
  92. data/lib/graphql/version.rb +1 -1
  93. data/readme.md +12 -3
  94. data/spec/generators/graphql/enum_generator_spec.rb +29 -0
  95. data/spec/generators/graphql/function_generator_spec.rb +33 -0
  96. data/spec/generators/graphql/install_generator_spec.rb +185 -0
  97. data/spec/generators/graphql/interface_generator_spec.rb +32 -0
  98. data/spec/generators/graphql/loader_generator_spec.rb +31 -0
  99. data/spec/generators/graphql/mutation_generator_spec.rb +28 -0
  100. data/spec/generators/graphql/object_generator_spec.rb +42 -0
  101. data/spec/generators/graphql/union_generator_spec.rb +50 -0
  102. data/spec/graphql/analysis/query_complexity_spec.rb +2 -1
  103. data/spec/graphql/define/instance_definable_spec.rb +38 -0
  104. data/spec/graphql/directive/skip_directive_spec.rb +1 -0
  105. data/spec/graphql/directive_spec.rb +18 -0
  106. data/spec/graphql/execution/typecast_spec.rb +41 -46
  107. data/spec/graphql/field_spec.rb +1 -1
  108. data/spec/graphql/function_spec.rb +128 -0
  109. data/spec/graphql/internal_representation/rewrite_spec.rb +166 -129
  110. data/spec/graphql/introspection/type_type_spec.rb +1 -1
  111. data/spec/graphql/language/lexer_spec.rb +6 -0
  112. data/spec/graphql/object_type_spec.rb +73 -2
  113. data/spec/graphql/query/arguments_spec.rb +28 -0
  114. data/spec/graphql/query/variables_spec.rb +7 -1
  115. data/spec/graphql/query_spec.rb +30 -0
  116. data/spec/graphql/relay/base_connection_spec.rb +26 -8
  117. data/spec/graphql/relay/connection_resolve_spec.rb +45 -0
  118. data/spec/graphql/relay/connection_type_spec.rb +21 -0
  119. data/spec/graphql/relay/node_spec.rb +30 -2
  120. data/spec/graphql/relay/range_add_spec.rb +113 -0
  121. data/spec/graphql/schema/build_from_definition_spec.rb +114 -0
  122. data/spec/graphql/schema/loader_spec.rb +1 -0
  123. data/spec/graphql/schema/printer_spec.rb +2 -2
  124. data/spec/graphql/schema/validation_spec.rb +80 -11
  125. data/spec/graphql/schema/warden_spec.rb +10 -10
  126. data/spec/graphql/schema_spec.rb +18 -1
  127. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +16 -0
  128. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +50 -3
  129. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +27 -0
  130. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +57 -0
  131. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
  132. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +14 -0
  133. data/spec/graphql/string_type_spec.rb +7 -0
  134. data/spec/spec_helper.rb +3 -3
  135. data/spec/support/base_generator_test.rb +7 -0
  136. data/spec/support/dummy/schema.rb +32 -30
  137. data/spec/support/star_wars/schema.rb +81 -23
  138. metadata +98 -20
  139. 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 3, complexities.last
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) {
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "spec_helper"
2
3
 
3
4
  describe GraphQL::Directive::SkipDirective do
@@ -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
- let(:milk_value) { MILKS[1] }
6
- let(:cheese_value) { CHEESES[1] }
7
-
8
- let(:schema) { Dummy::Schema }
9
- let(:context) { GraphQL::Query::Context.new(query: OpenStruct.new(schema: schema), values: nil) }
10
-
11
- def compatible?(*args)
12
- GraphQL::Execution::Typecast.compatible?(*args)
13
- end
14
-
15
- it "resolves correctly when both types are the same" do
16
- assert compatible?(Dummy::MilkType, Dummy::MilkType, context)
17
-
18
- assert !compatible?(Dummy::MilkType, Dummy::CheeseType, context)
19
- end
20
-
21
- it "resolves a union type to a matching member" do
22
- assert compatible?(Dummy::DairyProductUnion, Dummy::MilkType, context)
23
- assert compatible?(Dummy::DairyProductUnion, Dummy::CheeseType, context)
24
-
25
- assert !compatible?(Dummy::DairyProductUnion, GraphQL::INT_TYPE, context)
26
- assert !compatible?(Dummy::DairyProductUnion, Dummy::HoneyType, context)
27
- end
28
-
29
- it "resolves correcty when potential type is UnionType and current type is a member of that union" do
30
- assert compatible?(Dummy::MilkType, Dummy::DairyProductUnion, context)
31
- assert compatible?(Dummy::CheeseType, Dummy::DairyProductUnion, context)
32
-
33
- assert !compatible?(Dummy::DairyAppQueryType, Dummy::DairyProductUnion, context)
34
- assert !compatible?(Dummy::EdibleInterface, Dummy::DairyProductUnion, context)
35
- end
36
-
37
- it "resolves an object type to one of its interfaces" do
38
- assert compatible?(Dummy::CheeseType, Dummy::EdibleInterface, context)
39
- assert compatible?(Dummy::MilkType, Dummy::EdibleInterface, context)
40
-
41
- assert !compatible?(Dummy::DairyAppQueryType, Dummy::EdibleInterface, context)
42
- assert !compatible?(Dummy::LocalProductInterface, Dummy::EdibleInterface, context)
43
- end
44
-
45
- it "resolves an interface to a matching member" do
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
@@ -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 -> (obj, args, ctx) { args[:value] }
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