graphql 1.4.5 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
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