graphql 1.9.4 → 1.9.5

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 (65) hide show
  1. checksums.yaml +5 -5
  2. data/lib/graphql/execution/execute.rb +3 -0
  3. data/lib/graphql/execution/interpreter/runtime.rb +2 -2
  4. data/lib/graphql/execution/lookahead.rb +57 -22
  5. data/lib/graphql/introspection/input_value_type.rb +5 -1
  6. data/lib/graphql/language/parser.rb +57 -54
  7. data/lib/graphql/language/parser.y +12 -9
  8. data/lib/graphql/language/token.rb +1 -1
  9. data/lib/graphql/language/visitor.rb +1 -1
  10. data/lib/graphql/query/arguments.rb +3 -3
  11. data/lib/graphql/query/context.rb +6 -6
  12. data/lib/graphql/query/variable_validation_error.rb +14 -0
  13. data/lib/graphql/schema.rb +2 -2
  14. data/lib/graphql/schema/argument.rb +1 -1
  15. data/lib/graphql/schema/field.rb +6 -3
  16. data/lib/graphql/schema/object.rb +2 -2
  17. data/lib/graphql/schema/relay_classic_mutation.rb +1 -1
  18. data/lib/graphql/schema/rescue_middleware.rb +7 -2
  19. data/lib/graphql/schema/validation.rb +9 -4
  20. data/lib/graphql/static_validation/base_visitor.rb +8 -5
  21. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -1
  22. data/lib/graphql/tracing.rb +3 -3
  23. data/lib/graphql/types.rb +1 -0
  24. data/lib/graphql/types/json.rb +25 -0
  25. data/lib/graphql/types/relay/base_edge.rb +3 -2
  26. data/lib/graphql/unauthorized_field_error.rb +1 -1
  27. data/lib/graphql/version.rb +1 -1
  28. data/spec/dummy/Gemfile.lock +157 -0
  29. data/spec/dummy/log/test.log +199 -0
  30. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  31. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +1 -0
  32. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +1 -0
  33. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +1 -0
  34. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +3 -0
  35. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  36. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +2 -0
  37. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +2 -0
  38. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  39. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  40. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +1 -0
  41. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  42. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +1 -0
  43. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +3 -0
  44. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +1 -0
  45. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +1 -0
  46. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  47. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +1 -0
  48. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  49. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  50. data/spec/graphql/authorization_spec.rb +47 -14
  51. data/spec/graphql/execution/lookahead_spec.rb +29 -2
  52. data/spec/graphql/function_spec.rb +28 -5
  53. data/spec/graphql/introspection/input_value_type_spec.rb +40 -1
  54. data/spec/graphql/language/parser_spec.rb +8 -0
  55. data/spec/graphql/query/executor_spec.rb +30 -3
  56. data/spec/graphql/schema/object_spec.rb +71 -0
  57. data/spec/graphql/schema/relay_classic_mutation_spec.rb +18 -0
  58. data/spec/graphql/schema/rescue_middleware_spec.rb +14 -0
  59. data/spec/graphql/schema/warden_spec.rb +1 -1
  60. data/spec/graphql/types/relay/base_edge_spec.rb +33 -0
  61. data/spec/integration/rails/graphql/schema_spec.rb +13 -0
  62. data/spec/integration/tmp/app/graphql/types/bird_type.rb +7 -0
  63. data/spec/support/dummy/schema.rb +19 -0
  64. data/spec/support/jazz.rb +16 -14
  65. metadata +57 -7
@@ -12,7 +12,7 @@ module GraphQL
12
12
 
13
13
  def initialize(value:, name:, line:, col:, prev_token:)
14
14
  @name = name
15
- @value = value.freeze
15
+ @value = -value
16
16
  @line = line
17
17
  @col = col
18
18
  @prev_token = prev_token
@@ -24,7 +24,7 @@ module GraphQL
24
24
  # end
25
25
  #
26
26
  # # Initialize a visitor
27
- # visitor = GraphQL::Language::Visitor.new(document, "name")
27
+ # visitor = NameCounter.new(document, "name")
28
28
  # # Run it
29
29
  # visitor.visit
30
30
  # # Check the result
@@ -14,12 +14,12 @@ module GraphQL
14
14
  self.argument_definitions = argument_definitions
15
15
 
16
16
  argument_definitions.each do |_arg_name, arg_definition|
17
- expose_as = arg_definition.expose_as.to_s
18
- expose_as_underscored = GraphQL::Schema::Member::BuildType.underscore(expose_as)
17
+ expose_as = -arg_definition.expose_as.to_s
18
+ expose_as_underscored = -GraphQL::Schema::Member::BuildType.underscore(expose_as)
19
19
  method_names = [expose_as, expose_as_underscored].uniq
20
20
  method_names.each do |method_name|
21
21
  # Don't define a helper method if it would override something.
22
- if instance_methods.include?(method_name.to_sym)
22
+ if method_defined?(method_name)
23
23
  warn(
24
24
  "Unable to define a helper for argument with name '#{method_name}' "\
25
25
  "as this is a reserved name. If you're using an argument such as "\
@@ -44,11 +44,11 @@ module GraphQL
44
44
  # @api private
45
45
  def spawn_child(key:, irep_node:, object:)
46
46
  FieldResolutionContext.new(
47
- context: @context,
48
- parent: self,
49
- object: object,
50
- key: key,
51
- irep_node: irep_node,
47
+ @context,
48
+ key,
49
+ irep_node,
50
+ self,
51
+ object
52
52
  )
53
53
  end
54
54
 
@@ -203,7 +203,7 @@ module GraphQL
203
203
  attr_reader :irep_node, :field, :parent_type, :query, :schema, :parent, :key, :type
204
204
  alias :selection :irep_node
205
205
 
206
- def initialize(context:, key:, irep_node:, parent:, object:)
206
+ def initialize(context, key, irep_node, parent, object)
207
207
  @context = context
208
208
  @key = key
209
209
  @parent = parent
@@ -9,6 +9,11 @@ module GraphQL
9
9
  @validation_result = validation_result
10
10
 
11
11
  msg = "Variable #{variable_ast.name} of type #{type} was provided invalid value"
12
+
13
+ if problem_fields.any?
14
+ msg += " for #{problem_fields.join(", ")}"
15
+ end
16
+
12
17
  super(msg)
13
18
  self.ast_node = variable_ast
14
19
  end
@@ -25,6 +30,15 @@ module GraphQL
25
30
  end
26
31
  end
27
32
  end
33
+
34
+ private
35
+
36
+ def problem_fields
37
+ @problem_fields ||= @validation_result
38
+ .problems
39
+ .reject { |problem| problem["path"].empty? }
40
+ .map { |problem| "#{problem['path'].join('.')} (#{problem['explanation']})" }
41
+ end
28
42
  end
29
43
  end
30
44
  end
@@ -246,13 +246,13 @@ module GraphQL
246
246
  # Validate a query string according to this schema.
247
247
  # @param string_or_document [String, GraphQL::Language::Nodes::Document]
248
248
  # @return [Array<GraphQL::StaticValidation::Error >]
249
- def validate(string_or_document, rules: nil)
249
+ def validate(string_or_document, rules: nil, context: nil)
250
250
  doc = if string_or_document.is_a?(String)
251
251
  GraphQL.parse(string_or_document)
252
252
  else
253
253
  string_or_document
254
254
  end
255
- query = GraphQL::Query.new(self, document: doc)
255
+ query = GraphQL::Query.new(self, document: doc, context: context)
256
256
  validator_opts = { schema: self }
257
257
  rules && (validator_opts[:rules] = rules)
258
258
  validator = GraphQL::StaticValidation::Validator.new(validator_opts)
@@ -32,7 +32,7 @@ module GraphQL
32
32
  # @param camelize [Boolean] if true, the name will be camelized when building the schema
33
33
  def initialize(arg_name = nil, type_expr = nil, desc = nil, required:, type: nil, name: nil, description: nil, default_value: NO_DEFAULT, as: nil, camelize: true, prepare: nil, owner:, &definition_block)
34
34
  arg_name ||= name
35
- @name = camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s
35
+ @name = -(camelize ? Member::BuildType.camelize(arg_name.to_s) : arg_name.to_s)
36
36
  @type_expr = type_expr || type
37
37
  @description = desc || description
38
38
  @null = !required
@@ -130,7 +130,7 @@ module GraphQL
130
130
  # The default was overridden
131
131
  @scope
132
132
  else
133
- @return_type_expr.is_a?(Array) || (@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) || connection?
133
+ @return_type_expr && (@return_type_expr.is_a?(Array) || (@return_type_expr.is_a?(String) && @return_type_expr.include?("[")) || connection?)
134
134
  end
135
135
  end
136
136
 
@@ -173,8 +173,8 @@ module GraphQL
173
173
  raise ArgumentError, "keyword `extras:` may only be used with method-based resolve and class-based field such as mutation class, please remove `field:`, `function:` or `resolve:`"
174
174
  end
175
175
  @original_name = name
176
- @underscored_name = Member::BuildType.underscore(name.to_s)
177
- @name = camelize ? Member::BuildType.camelize(name.to_s) : name.to_s
176
+ @underscored_name = -Member::BuildType.underscore(name.to_s)
177
+ @name = -(camelize ? Member::BuildType.camelize(name.to_s) : name.to_s)
178
178
  @description = description
179
179
  if field.is_a?(GraphQL::Schema::Field)
180
180
  raise ArgumentError, "Instead of passing a field as `field:`, use `add_field(field)` to add an already-defined field."
@@ -504,6 +504,9 @@ module GraphQL
504
504
  err = GraphQL::UnauthorizedFieldError.new(object: application_object, type: object.class, context: ctx, field: self)
505
505
  ctx.schema.unauthorized_field(err)
506
506
  end
507
+ rescue GraphQL::UnauthorizedFieldError => err
508
+ err.field ||= self
509
+ ctx.schema.unauthorized_field(err)
507
510
  rescue GraphQL::UnauthorizedError => err
508
511
  ctx.schema.unauthorized_object(err)
509
512
  end
@@ -37,8 +37,8 @@ module GraphQL
37
37
  def authorized_new(object, context)
38
38
  auth_val = begin
39
39
  authorized?(object, context)
40
- # rescue GraphQL::UnauthorizedError => err
41
- # context.schema.unauthorized_object(err)
40
+ rescue GraphQL::UnauthorizedError => err
41
+ context.schema.unauthorized_object(err)
42
42
  end
43
43
 
44
44
  context.schema.after_lazy(auth_val) do |is_authorized|
@@ -32,7 +32,7 @@ module GraphQL
32
32
  # Without the interpreter, the inputs are unwrapped by an instrumenter.
33
33
  # But when using the interpreter, no instrumenters are applied.
34
34
  if context.interpreter?
35
- input = inputs[:input].to_h
35
+ input = inputs[:input].to_kwargs
36
36
  # Transfer these from the top-level hash to the
37
37
  # shortcutted `input:` object
38
38
  self.class.extras.each do |ext|
@@ -43,8 +43,13 @@ module GraphQL
43
43
  def attempt_rescue(err)
44
44
  rescue_table.each { |klass, handler|
45
45
  if klass.is_a?(Class) && err.is_a?(klass) && handler
46
- message = handler.call(err)
47
- return GraphQL::ExecutionError.new(message)
46
+ result = handler.call(err)
47
+ case result
48
+ when String
49
+ return GraphQL::ExecutionError.new(result)
50
+ when GraphQL::ExecutionError
51
+ return result
52
+ end
48
53
  end
49
54
  }
50
55
 
@@ -12,11 +12,16 @@ module GraphQL
12
12
  # @param object [Object] something to be validated
13
13
  # @return [String, Nil] error message, if there was one
14
14
  def self.validate(object)
15
- rules = RULES.reduce([]) do |memo, (parent_class, validations)|
16
- memo + (object.is_a?(parent_class) ? validations : [])
15
+ RULES.each do |parent_class, validations|
16
+ if object.is_a?(parent_class)
17
+ validations.each do |rule|
18
+ if error = rule.call(object)
19
+ return error
20
+ end
21
+ end
22
+ end
17
23
  end
18
- # Stops after the first error
19
- rules.reduce(nil) { |memo, rule| memo || rule.call(object) }
24
+ nil
20
25
  end
21
26
 
22
27
  module Rules
@@ -146,11 +146,14 @@ module GraphQL
146
146
  end
147
147
 
148
148
  def on_input_object(node, parent)
149
- is_list = @argument_definitions.last&.type&.list? == true
150
-
151
- @path.push(parent.children.index(node)) if is_list
152
- super
153
- @path.pop if is_list
149
+ arg_defn = @argument_definitions.last
150
+ if arg_defn && arg_defn.type.list?
151
+ @path.push(parent.children.index(node))
152
+ super
153
+ @path.pop
154
+ else
155
+ super
156
+ end
154
157
  end
155
158
 
156
159
  # @return [GraphQL::BaseType] The current object type
@@ -26,7 +26,9 @@ module GraphQL
26
26
  # variables = ensure_hash(data["variables"])
27
27
  # operation_name = data["operationName"]
28
28
  # context = {
29
- # current_user: current_user,
29
+ # # Re-implement whatever context methods you need
30
+ # # in this channel or ApplicationCable::Channel
31
+ # # current_user: current_user,
30
32
  # # Make sure the channel is in the context
31
33
  # channel: self,
32
34
  # }
@@ -42,12 +42,12 @@ module GraphQL
42
42
  # execute_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
43
43
  # execute_query | `{ query: GraphQL::Query }`
44
44
  # execute_query_lazy | `{ query: GraphQL::Query?, multiplex: GraphQL::Execution::Multiplex? }`
45
- # execute_field | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
46
- # execute_field_lazy | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, path: Array<String, Integer>?}`
45
+ # execute_field | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, query: GraphQL::Query?, path: Array<String, Integer>?}`
46
+ # execute_field_lazy | `{ context: GraphQL::Query::Context::FieldResolutionContext?, owner: Class?, field: GraphQL::Schema::Field?, query: GraphqL::Query?, path: Array<String, Integer>?}`
47
47
  #
48
48
  # Note that `execute_field` and `execute_field_lazy` receive different data in different settings:
49
49
  #
50
- # - When using {GraphQL::Execution::Interpreter}, they receive `{field:, path:}`
50
+ # - When using {GraphQL::Execution::Interpreter}, they receive `{field:, path:, query:}`
51
51
  # - Otherwise, they receive `{context: ...}`
52
52
  #
53
53
  module Tracing
@@ -5,5 +5,6 @@ require "graphql/types/float"
5
5
  require "graphql/types/id"
6
6
  require "graphql/types/int"
7
7
  require "graphql/types/iso_8601_date_time"
8
+ require "graphql/types/json"
8
9
  require "graphql/types/string"
9
10
  require "graphql/types/relay"
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Types
4
+ # An untyped JSON scalar that maps to Ruby hashes, arrays, strings, integers, floats, booleans and nils.
5
+ # This should be used judiciously because it subverts the GraphQL type system.
6
+ #
7
+ # Use it for fields or arguments as follows:
8
+ #
9
+ # field :template_parameters, GraphQL::Types::JSON, null: false
10
+ #
11
+ # argument :template_parameters, GraphQL::Types::JSON, null: false
12
+ #
13
+ class JSON < GraphQL::Schema::Scalar
14
+ description "Represents untyped JSON"
15
+
16
+ def self.coerce_input(value, _context)
17
+ value
18
+ end
19
+
20
+ def self.coerce_result(value, _context)
21
+ value
22
+ end
23
+ end
24
+ end
25
+ end
@@ -28,14 +28,15 @@ module GraphQL
28
28
  # Get or set the Object type that this edge wraps.
29
29
  #
30
30
  # @param node_type [Class] A `Schema::Object` subclass
31
- def node_type(node_type = nil)
31
+ # @param null [Boolean]
32
+ def node_type(node_type = nil, null: true)
32
33
  if node_type
33
34
  @node_type = node_type
34
35
  wrapped_type_name = node_type.graphql_name
35
36
  # Set this to be named like the node type, but suffixed with `Edge`
36
37
  graphql_name("#{wrapped_type_name}Edge")
37
38
  # Add a default `node` field
38
- field :node, node_type, null: true, description: "The item at the end of the edge."
39
+ field :node, node_type, null: null, description: "The item at the end of the edge."
39
40
  end
40
41
  @node_type
41
42
  end
@@ -2,7 +2,7 @@
2
2
  module GraphQL
3
3
  class UnauthorizedFieldError < GraphQL::UnauthorizedError
4
4
  # @return [Field] the field that failed the authorization check
5
- attr_reader :field
5
+ attr_accessor :field
6
6
 
7
7
  def initialize(message = nil, object: nil, type: nil, context: nil, field: nil)
8
8
  if message.nil? && [field, type].any?(&:nil?)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "1.9.4"
3
+ VERSION = "1.9.5"
4
4
  end
@@ -0,0 +1,157 @@
1
+ PATH
2
+ remote: /Users/rmosolgo/code/graphql-ruby
3
+ specs:
4
+ graphql (1.9.0.pre2)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actioncable (5.2.1)
10
+ actionpack (= 5.2.1)
11
+ nio4r (~> 2.0)
12
+ websocket-driver (>= 0.6.1)
13
+ actionmailer (5.2.1)
14
+ actionpack (= 5.2.1)
15
+ actionview (= 5.2.1)
16
+ activejob (= 5.2.1)
17
+ mail (~> 2.5, >= 2.5.4)
18
+ rails-dom-testing (~> 2.0)
19
+ actionpack (5.2.1)
20
+ actionview (= 5.2.1)
21
+ activesupport (= 5.2.1)
22
+ rack (~> 2.0)
23
+ rack-test (>= 0.6.3)
24
+ rails-dom-testing (~> 2.0)
25
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
26
+ actionview (5.2.1)
27
+ activesupport (= 5.2.1)
28
+ builder (~> 3.1)
29
+ erubi (~> 1.4)
30
+ rails-dom-testing (~> 2.0)
31
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
32
+ activejob (5.2.1)
33
+ activesupport (= 5.2.1)
34
+ globalid (>= 0.3.6)
35
+ activemodel (5.2.1)
36
+ activesupport (= 5.2.1)
37
+ activerecord (5.2.1)
38
+ activemodel (= 5.2.1)
39
+ activesupport (= 5.2.1)
40
+ arel (>= 9.0)
41
+ activestorage (5.2.1)
42
+ actionpack (= 5.2.1)
43
+ activerecord (= 5.2.1)
44
+ marcel (~> 0.3.1)
45
+ activesupport (5.2.1)
46
+ concurrent-ruby (~> 1.0, >= 1.0.2)
47
+ i18n (>= 0.7, < 2)
48
+ minitest (~> 5.1)
49
+ tzinfo (~> 1.1)
50
+ addressable (2.5.2)
51
+ public_suffix (>= 2.0.2, < 4.0)
52
+ arel (9.0.0)
53
+ builder (3.2.3)
54
+ capybara (3.7.2)
55
+ addressable
56
+ mini_mime (>= 0.1.3)
57
+ nokogiri (~> 1.8)
58
+ rack (>= 1.6.0)
59
+ rack-test (>= 0.6.3)
60
+ xpath (~> 3.1)
61
+ childprocess (0.9.0)
62
+ ffi (~> 1.0, >= 1.0.11)
63
+ concurrent-ruby (1.0.5)
64
+ crass (1.0.4)
65
+ erubi (1.7.1)
66
+ ffi (1.9.25)
67
+ globalid (0.4.1)
68
+ activesupport (>= 4.2.0)
69
+ i18n (1.1.0)
70
+ concurrent-ruby (~> 1.0)
71
+ listen (3.1.5)
72
+ rb-fsevent (~> 0.9, >= 0.9.4)
73
+ rb-inotify (~> 0.9, >= 0.9.7)
74
+ ruby_dep (~> 1.2)
75
+ loofah (2.2.2)
76
+ crass (~> 1.0.2)
77
+ nokogiri (>= 1.5.9)
78
+ mail (2.7.0)
79
+ mini_mime (>= 0.1.1)
80
+ marcel (0.3.3)
81
+ mimemagic (~> 0.3.2)
82
+ method_source (0.9.0)
83
+ mimemagic (0.3.2)
84
+ mini_mime (1.0.1)
85
+ mini_portile2 (2.3.0)
86
+ minitest (5.11.3)
87
+ nio4r (2.3.1)
88
+ nokogiri (1.8.4)
89
+ mini_portile2 (~> 2.3.0)
90
+ public_suffix (3.0.3)
91
+ puma (3.12.0)
92
+ rack (2.0.5)
93
+ rack-test (1.1.0)
94
+ rack (>= 1.0, < 3)
95
+ rails (5.2.1)
96
+ actioncable (= 5.2.1)
97
+ actionmailer (= 5.2.1)
98
+ actionpack (= 5.2.1)
99
+ actionview (= 5.2.1)
100
+ activejob (= 5.2.1)
101
+ activemodel (= 5.2.1)
102
+ activerecord (= 5.2.1)
103
+ activestorage (= 5.2.1)
104
+ activesupport (= 5.2.1)
105
+ bundler (>= 1.3.0)
106
+ railties (= 5.2.1)
107
+ sprockets-rails (>= 2.0.0)
108
+ rails-dom-testing (2.0.3)
109
+ activesupport (>= 4.2.0)
110
+ nokogiri (>= 1.6)
111
+ rails-html-sanitizer (1.0.4)
112
+ loofah (~> 2.2, >= 2.2.2)
113
+ railties (5.2.1)
114
+ actionpack (= 5.2.1)
115
+ activesupport (= 5.2.1)
116
+ method_source
117
+ rake (>= 0.8.7)
118
+ thor (>= 0.19.0, < 2.0)
119
+ rake (12.3.1)
120
+ rb-fsevent (0.10.3)
121
+ rb-inotify (0.9.10)
122
+ ffi (>= 0.5.0, < 2)
123
+ ruby_dep (1.5.0)
124
+ rubyzip (1.2.2)
125
+ selenium-webdriver (3.14.0)
126
+ childprocess (~> 0.5)
127
+ rubyzip (~> 1.2)
128
+ sprockets (3.7.2)
129
+ concurrent-ruby (~> 1.0)
130
+ rack (> 1, < 3)
131
+ sprockets-rails (3.2.1)
132
+ actionpack (>= 4.0)
133
+ activesupport (>= 4.0)
134
+ sprockets (>= 3.0.0)
135
+ thor (0.20.0)
136
+ thread_safe (0.3.6)
137
+ tzinfo (1.2.5)
138
+ thread_safe (~> 0.1)
139
+ websocket-driver (0.7.0)
140
+ websocket-extensions (>= 0.1.0)
141
+ websocket-extensions (0.1.3)
142
+ xpath (3.1.0)
143
+ nokogiri (~> 1.8)
144
+
145
+ PLATFORMS
146
+ ruby
147
+
148
+ DEPENDENCIES
149
+ capybara
150
+ graphql!
151
+ listen
152
+ puma
153
+ rails (~> 5.2.1)
154
+ selenium-webdriver
155
+
156
+ BUNDLED WITH
157
+ 2.0.1