graphql 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/introspection/schema_type.rb +3 -3
  3. data/lib/graphql/language/nodes.rb +1 -1
  4. data/lib/graphql/query.rb +39 -27
  5. data/lib/graphql/query/executor.rb +1 -1
  6. data/lib/graphql/query/variables.rb +21 -28
  7. data/lib/graphql/relay/connection_type.rb +2 -0
  8. data/lib/graphql/relay/relation_connection.rb +8 -2
  9. data/lib/graphql/schema.rb +3 -0
  10. data/lib/graphql/schema/warden.rb +9 -0
  11. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  12. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  13. data/lib/graphql/version.rb +1 -1
  14. data/spec/graphql/analysis/analyze_query_spec.rb +15 -15
  15. data/spec/graphql/analysis/field_usage_spec.rb +1 -1
  16. data/spec/graphql/analysis/max_query_complexity_spec.rb +8 -8
  17. data/spec/graphql/analysis/max_query_depth_spec.rb +7 -7
  18. data/spec/graphql/analysis/query_complexity_spec.rb +2 -2
  19. data/spec/graphql/analysis/query_depth_spec.rb +1 -1
  20. data/spec/graphql/base_type_spec.rb +19 -11
  21. data/spec/graphql/directive_spec.rb +1 -1
  22. data/spec/graphql/enum_type_spec.rb +2 -2
  23. data/spec/graphql/execution/typecast_spec.rb +19 -19
  24. data/spec/graphql/execution_error_spec.rb +1 -1
  25. data/spec/graphql/field_spec.rb +15 -7
  26. data/spec/graphql/id_type_spec.rb +1 -1
  27. data/spec/graphql/input_object_type_spec.rb +16 -16
  28. data/spec/graphql/interface_type_spec.rb +6 -6
  29. data/spec/graphql/internal_representation/rewrite_spec.rb +34 -34
  30. data/spec/graphql/introspection/directive_type_spec.rb +1 -1
  31. data/spec/graphql/introspection/input_value_type_spec.rb +2 -2
  32. data/spec/graphql/introspection/introspection_query_spec.rb +1 -1
  33. data/spec/graphql/introspection/schema_type_spec.rb +2 -2
  34. data/spec/graphql/introspection/type_type_spec.rb +1 -1
  35. data/spec/graphql/language/parser_spec.rb +1 -1
  36. data/spec/graphql/non_null_type_spec.rb +3 -3
  37. data/spec/graphql/object_type_spec.rb +8 -8
  38. data/spec/graphql/query/executor_spec.rb +4 -4
  39. data/spec/graphql/query/variables_spec.rb +20 -4
  40. data/spec/graphql/query_spec.rb +20 -2
  41. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  42. data/spec/graphql/relay/mutation_spec.rb +9 -9
  43. data/spec/graphql/relay/node_spec.rb +8 -8
  44. data/spec/graphql/relay/relation_connection_spec.rb +24 -6
  45. data/spec/graphql/schema/catchall_middleware_spec.rb +3 -3
  46. data/spec/graphql/schema/reduce_types_spec.rb +9 -9
  47. data/spec/graphql/schema/type_expression_spec.rb +3 -3
  48. data/spec/graphql/schema/validation_spec.rb +1 -1
  49. data/spec/graphql/schema/warden_spec.rb +79 -0
  50. data/spec/graphql/schema_spec.rb +2 -2
  51. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -1
  52. data/spec/graphql/static_validation/type_stack_spec.rb +2 -2
  53. data/spec/graphql/static_validation/validator_spec.rb +2 -2
  54. data/spec/graphql/union_type_spec.rb +2 -2
  55. data/spec/spec_helper.rb +1 -1
  56. data/spec/support/dummy/data.rb +27 -0
  57. data/spec/support/dummy/schema.rb +369 -0
  58. data/spec/support/star_wars/data.rb +81 -0
  59. data/spec/support/star_wars/schema.rb +250 -0
  60. data/spec/support/static_validation_helpers.rb +2 -2
  61. metadata +10 -10
  62. data/spec/support/dairy_app.rb +0 -369
  63. data/spec/support/dairy_data.rb +0 -26
  64. data/spec/support/star_wars_data.rb +0 -80
  65. data/spec/support/star_wars_schema.rb +0 -242
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'ostruct'
3
-
4
- Cheese = Struct.new(:id, :flavor, :origin, :fat_content, :source)
5
- CHEESES = {
6
- 1 => Cheese.new(1, "Brie", "France", 0.19, 1),
7
- 2 => Cheese.new(2, "Gouda", "Netherlands", 0.3, 1),
8
- 3 => Cheese.new(3, "Manchego", "Spain", 0.065, "SHEEP")
9
- }
10
-
11
- Milk = Struct.new(:id, :fatContent, :origin, :source, :flavors)
12
- MILKS = {
13
- 1 => Milk.new(1, 0.04, "Antiquity", 1, ["Natural", "Chocolate", "Strawberry"]),
14
- }
15
-
16
- DAIRY = OpenStruct.new(
17
- id: 1,
18
- cheese: CHEESES[1],
19
- milks: [MILKS[1]]
20
- )
21
-
22
- COW = OpenStruct.new(
23
- id: 1,
24
- name: "Billy",
25
- last_produced_dairy: MILKS[1]
26
- )
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'ostruct'
3
-
4
- names = [
5
- 'X-Wing',
6
- 'Y-Wing',
7
- 'A-Wing',
8
- 'Millenium Falcon',
9
- 'Home One',
10
- 'TIE Fighter',
11
- 'TIE Interceptor',
12
- 'Executor',
13
- ]
14
-
15
- # ActiveRecord::Base.logger = Logger.new(STDOUT)
16
- `rm -f ./_test_.db`
17
- # Set up "Bases" in ActiveRecord
18
- ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: "./_test_.db")
19
-
20
- ActiveRecord::Schema.define do
21
- self.verbose = false
22
- create_table :bases do |t|
23
- t.column :name, :string
24
- t.column :planet, :string
25
- t.column :faction_id, :integer
26
- end
27
- end
28
-
29
- class Base < ActiveRecord::Base
30
- end
31
-
32
- Base.create!(name: "Yavin", planet: "Yavin 4", faction_id: 1)
33
- Base.create!(name: "Echo Base", planet: "Hoth", faction_id: 1)
34
- Base.create!(name: "Secret Hideout", planet: "Dantooine", faction_id: 1)
35
- Base.create!(name: "Death Star", planet: nil, faction_id: 2)
36
- Base.create!(name: "Shield Generator", planet: "Endor", faction_id: 2)
37
- Base.create!(name: "Headquarters", planet: "Coruscant", faction_id: 2)
38
-
39
- # Also, set up Bases with Sequel
40
- DB = Sequel.sqlite("./_test_.db")
41
- class SequelBase < Sequel::Model(:bases)
42
- end
43
-
44
- rebels = OpenStruct.new({
45
- id: '1',
46
- name: 'Alliance to Restore the Republic',
47
- ships: ['1', '2', '3', '4', '5'],
48
- bases: Base.where(faction_id: 1),
49
- basesClone: Base.where(faction_id: 1),
50
- })
51
-
52
-
53
- empire = OpenStruct.new({
54
- id: '2',
55
- name: 'Galactic Empire',
56
- ships: ['6', '7', '8'],
57
- bases: Base.where(faction_id: 2),
58
- basesClone: Base.where(faction_id: 2),
59
- })
60
-
61
- STAR_WARS_DATA = {
62
- "Faction" => {
63
- "1" => rebels,
64
- "2" => empire,
65
- },
66
- "Ship" => names.each_with_index.reduce({}) do |memo, (name, idx)|
67
- id = (idx + 1).to_s
68
- memo[id] = OpenStruct.new(name: name, id: id)
69
- memo
70
- end,
71
- "Base" => Hash.new { |h, k| h[k] = Base.find(k) }
72
- }
73
-
74
- def STAR_WARS_DATA.create_ship(name, faction_id)
75
- new_id = (self["Ship"].keys.map(&:to_i).max + 1).to_s
76
- new_ship = OpenStruct.new(id: new_id, name: name)
77
- self["Ship"][new_id] = new_ship
78
- self["Faction"][faction_id].ships << new_id
79
- new_ship
80
- end
@@ -1,242 +0,0 @@
1
- # frozen_string_literal: true
2
- # Adapted from graphql-relay-js
3
- # https://github.com/graphql/graphql-relay-js/blob/master/src/__tests__/starWarsSchema.js
4
-
5
- Ship = GraphQL::ObjectType.define do
6
- name "Ship"
7
- interfaces [GraphQL::Relay::Node.interface]
8
- global_id_field :id
9
- field :name, types.String
10
- end
11
-
12
- BaseType = GraphQL::ObjectType.define do
13
- name "Base"
14
- interfaces [GraphQL::Relay::Node.interface]
15
- global_id_field :id
16
- field :name, types.String
17
- field :planet, types.String
18
- end
19
-
20
- # Use an optional block to add fields to the connection type:
21
- BaseConnectionWithTotalCountType = BaseType.define_connection(nodes_field: true) do
22
- name "BasesConnectionWithTotalCount"
23
- field :totalCount do
24
- type types.Int
25
- resolve ->(obj, args, ctx) { obj.nodes.count }
26
- end
27
- end
28
-
29
- class CustomBaseEdge < GraphQL::Relay::Edge
30
- def upcased_name
31
- node.name.upcase
32
- end
33
-
34
- def upcased_parent_name
35
- parent.name.upcase
36
- end
37
- end
38
-
39
- CustomBaseEdgeType = BaseType.define_edge do
40
- name "CustomBaseEdge"
41
- field :upcasedName, types.String, property: :upcased_name
42
- field :upcasedParentName, types.String, property: :upcased_parent_name
43
- field :edgeClassName, types.String do
44
- resolve ->(obj, args, ctx) { obj.class.name }
45
- end
46
- end
47
-
48
- CustomEdgeBaseConnectionType = BaseType.define_connection(edge_class: CustomBaseEdge, edge_type: CustomBaseEdgeType, nodes_field: true) do
49
- name "CustomEdgeBaseConnection"
50
-
51
- field :totalCountTimes100 do
52
- type types.Int
53
- resolve ->(obj, args, ctx) { obj.nodes.count * 100 }
54
- end
55
-
56
- field :fieldName, types.String, resolve: ->(obj, args, ctx) { obj.field.name }
57
- end
58
-
59
- Faction = GraphQL::ObjectType.define do
60
- name "Faction"
61
- interfaces [GraphQL::Relay::Node.interface]
62
-
63
- field :id, !types.ID, resolve: GraphQL::Relay::GlobalIdResolve.new(type: Faction)
64
- field :name, types.String
65
- connection :ships, Ship.connection_type do
66
- resolve ->(obj, args, ctx) {
67
- all_ships = obj.ships.map {|ship_id| STAR_WARS_DATA["Ship"][ship_id] }
68
- if args[:nameIncludes]
69
- all_ships = all_ships.select { |ship| ship.name.include?(args[:nameIncludes])}
70
- end
71
- all_ships
72
- }
73
- # You can define arguments here and use them in the connection
74
- argument :nameIncludes, types.String
75
- end
76
- connection :shipsWithMaxPageSize, Ship.connection_type, max_page_size: 2 do
77
- resolve ->(obj, args, ctx) {
78
- all_ships = obj.ships.map {|ship_id| STAR_WARS_DATA["Ship"][ship_id] }
79
- if args[:nameIncludes]
80
- all_ships = all_ships.select { |ship| ship.name.include?(args[:nameIncludes])}
81
- end
82
- all_ships
83
- }
84
- # You can define arguments here and use them in the connection
85
- argument :nameIncludes, types.String
86
- end
87
-
88
- connection :bases, BaseConnectionWithTotalCountType do
89
- # Resolve field should return an Array, the Connection
90
- # will do the rest!
91
- resolve ->(obj, args, ctx) {
92
- all_bases = Base.where(id: obj.bases)
93
- if args[:nameIncludes]
94
- all_bases = all_bases.where("name LIKE ?", "%#{args[:nameIncludes]}%")
95
- end
96
- all_bases
97
- }
98
- argument :nameIncludes, types.String
99
- end
100
-
101
- connection :basesClone, BaseType.connection_type
102
- connection :basesByName, BaseType.connection_type, property: :bases do
103
- argument :order, types.String, default_value: "name"
104
- resolve ->(obj, args, ctx) {
105
- if args[:order].present?
106
- obj.bases.order(args[:order])
107
- else
108
- obj.bases
109
- end
110
- }
111
- end
112
-
113
- connection :basesWithMaxLimitRelation, BaseType.connection_type, max_page_size: 2 do
114
- resolve ->(object, args, context) { Base.all }
115
- end
116
-
117
- connection :basesWithMaxLimitArray, BaseType.connection_type, max_page_size: 2 do
118
- resolve ->(object, args, context) { Base.all.to_a }
119
- end
120
-
121
- connection :basesAsSequelDataset, BaseConnectionWithTotalCountType do
122
- argument :nameIncludes, types.String
123
- resolve ->(obj, args, ctx) {
124
- all_bases = SequelBase.where(faction_id: obj.id)
125
- if args[:nameIncludes]
126
- all_bases = all_bases.where("name LIKE ?", "%#{args[:nameIncludes]}%")
127
- end
128
- all_bases
129
- }
130
- end
131
-
132
- connection :basesWithCustomEdge, CustomEdgeBaseConnectionType, property: :bases
133
- end
134
-
135
- # Define a mutation. It will also:
136
- # - define a derived InputObjectType
137
- # - define a derived ObjectType (for return)
138
- # - define a field, accessible from {Mutation#field}
139
- #
140
- # The resolve proc takes `inputs, ctx`, where:
141
- # - `inputs` has the keys defined with `input_field`
142
- # - `ctx` is the Query context (like normal fields)
143
- #
144
- # Notice that you leave out clientMutationId.
145
- IntroduceShipMutation = GraphQL::Relay::Mutation.define do
146
- # Used as the root for derived types:
147
- name "IntroduceShip"
148
- description "Add a ship to this faction"
149
-
150
- # Nested under `input` in the query:
151
- input_field :shipName, types.String
152
- input_field :factionId, !types.ID
153
-
154
- # Result may have access to these fields:
155
- return_field :shipEdge, Ship.edge_type
156
- return_field :faction, Faction
157
-
158
- # Here's the mutation operation:
159
- resolve ->(root_obj, inputs, ctx) {
160
- faction_id = inputs["factionId"]
161
- if inputs["shipName"] == 'Millennium Falcon'
162
- GraphQL::ExecutionError.new("Sorry, Millennium Falcon ship is reserved")
163
-
164
- else
165
- ship = STAR_WARS_DATA.create_ship(inputs["shipName"], faction_id)
166
- faction = STAR_WARS_DATA["Faction"][faction_id]
167
- connection_class = GraphQL::Relay::BaseConnection.connection_for_nodes(faction.ships)
168
- ships_connection = connection_class.new(faction.ships, inputs)
169
- ship_edge = GraphQL::Relay::Edge.new(ship, ships_connection)
170
- result = {
171
- shipEdge: ship_edge,
172
- faction: faction
173
- }
174
- if inputs["shipName"] == "Slave II"
175
- LazyWrapper.new(result)
176
- else
177
- result
178
- end
179
- end
180
- }
181
- end
182
-
183
-
184
- class LazyWrapper
185
- attr_reader :value
186
- def initialize(value)
187
- @value = value
188
- end
189
- end
190
-
191
- QueryType = GraphQL::ObjectType.define do
192
- name "Query"
193
- field :rebels, Faction do
194
- resolve ->(obj, args, ctx) { STAR_WARS_DATA["Faction"]["1"]}
195
- end
196
-
197
- field :empire, Faction do
198
- resolve ->(obj, args, ctx) { STAR_WARS_DATA["Faction"]["2"]}
199
- end
200
-
201
- field :largestBase, BaseType do
202
- resolve ->(obj, args, ctx) { Base.find(3) }
203
- end
204
-
205
- field :node, GraphQL::Relay::Node.field
206
- end
207
-
208
- MutationType = GraphQL::ObjectType.define do
209
- name "Mutation"
210
- # The mutation object exposes a field:
211
- field :introduceShip, field: IntroduceShipMutation.field
212
- end
213
-
214
- StarWarsSchema = GraphQL::Schema.define do
215
- query(QueryType)
216
- mutation(MutationType)
217
-
218
- resolve_type ->(object, ctx) {
219
- if object == :test_error
220
- :not_a_type
221
- elsif object.is_a?(Base)
222
- BaseType
223
- elsif STAR_WARS_DATA["Faction"].values.include?(object)
224
- Faction
225
- elsif STAR_WARS_DATA["Ship"].values.include?(object)
226
- Ship
227
- else
228
- nil
229
- end
230
- }
231
-
232
- object_from_id ->(node_id, ctx) do
233
- type_name, id = GraphQL::Schema::UniqueWithinType.decode(node_id)
234
- STAR_WARS_DATA[type_name][id]
235
- end
236
-
237
- id_from_object ->(object, type, ctx) do
238
- GraphQL::Schema::UniqueWithinType.encode(type.name, object.id)
239
- end
240
-
241
- lazy_resolve(LazyWrapper, :value)
242
- end