graphql 1.0.0 → 1.1.0

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +10 -0
  3. data/lib/graphql/base_type.rb +8 -5
  4. data/lib/graphql/compatibility.rb +3 -0
  5. data/lib/graphql/compatibility/execution_specification.rb +414 -0
  6. data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
  7. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +81 -0
  8. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +78 -0
  9. data/lib/graphql/compatibility/schema_parser_specification.rb +239 -0
  10. data/lib/graphql/define/instance_definable.rb +53 -21
  11. data/lib/graphql/directive.rb +1 -1
  12. data/lib/graphql/enum_type.rb +31 -8
  13. data/lib/graphql/execution/directive_checks.rb +0 -6
  14. data/lib/graphql/input_object_type.rb +6 -4
  15. data/lib/graphql/introspection/arguments_field.rb +3 -1
  16. data/lib/graphql/introspection/enum_values_field.rb +10 -5
  17. data/lib/graphql/introspection/fields_field.rb +1 -1
  18. data/lib/graphql/introspection/input_fields_field.rb +2 -2
  19. data/lib/graphql/introspection/interfaces_field.rb +7 -1
  20. data/lib/graphql/introspection/possible_types_field.rb +1 -1
  21. data/lib/graphql/introspection/schema_type.rb +1 -1
  22. data/lib/graphql/introspection/type_by_name_field.rb +4 -2
  23. data/lib/graphql/introspection/type_type.rb +7 -6
  24. data/lib/graphql/language/lexer.rl +0 -4
  25. data/lib/graphql/language/parser.rb +1 -1
  26. data/lib/graphql/language/parser.y +1 -1
  27. data/lib/graphql/list_type.rb +3 -4
  28. data/lib/graphql/non_null_type.rb +4 -8
  29. data/lib/graphql/object_type.rb +5 -3
  30. data/lib/graphql/query.rb +48 -12
  31. data/lib/graphql/query/context.rb +7 -1
  32. data/lib/graphql/query/serial_execution/execution_context.rb +8 -3
  33. data/lib/graphql/query/serial_execution/field_resolution.rb +8 -5
  34. data/lib/graphql/query/serial_execution/operation_resolution.rb +2 -2
  35. data/lib/graphql/query/serial_execution/selection_resolution.rb +4 -21
  36. data/lib/graphql/query/serial_execution/value_resolution.rb +59 -99
  37. data/lib/graphql/query/variables.rb +7 -2
  38. data/lib/graphql/scalar_type.rb +1 -1
  39. data/lib/graphql/schema.rb +49 -18
  40. data/lib/graphql/schema/build_from_definition.rb +248 -0
  41. data/lib/graphql/schema/instrumented_field_map.rb +23 -0
  42. data/lib/graphql/schema/loader.rb +4 -11
  43. data/lib/graphql/schema/possible_types.rb +4 -2
  44. data/lib/graphql/schema/printer.rb +1 -1
  45. data/lib/graphql/schema/type_expression.rb +4 -4
  46. data/lib/graphql/schema/type_map.rb +1 -1
  47. data/lib/graphql/schema/validation.rb +4 -0
  48. data/lib/graphql/schema/warden.rb +114 -0
  49. data/lib/graphql/static_validation/literal_validator.rb +10 -7
  50. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -3
  51. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  52. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  53. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -14
  54. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  55. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  56. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -4
  57. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +2 -1
  58. data/lib/graphql/static_validation/validation_context.rb +7 -1
  59. data/lib/graphql/union_type.rb +6 -3
  60. data/lib/graphql/unresolved_type_error.rb +1 -2
  61. data/lib/graphql/version.rb +1 -1
  62. data/readme.md +1 -5
  63. data/spec/graphql/compatibility/execution_specification_spec.rb +3 -0
  64. data/spec/graphql/compatibility/query_parser_specification_spec.rb +5 -0
  65. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +5 -0
  66. data/spec/graphql/define/instance_definable_spec.rb +20 -0
  67. data/spec/graphql/directive_spec.rb +11 -0
  68. data/spec/graphql/enum_type_spec.rb +20 -1
  69. data/spec/graphql/input_object_type_spec.rb +9 -9
  70. data/spec/graphql/introspection/directive_type_spec.rb +4 -4
  71. data/spec/graphql/introspection/input_value_type_spec.rb +6 -6
  72. data/spec/graphql/introspection/type_type_spec.rb +28 -26
  73. data/spec/graphql/language/parser_spec.rb +27 -17
  74. data/spec/graphql/list_type_spec.rb +2 -2
  75. data/spec/graphql/query/variables_spec.rb +1 -0
  76. data/spec/graphql/scalar_type_spec.rb +3 -3
  77. data/spec/graphql/schema/build_from_definition_spec.rb +693 -0
  78. data/spec/graphql/schema/type_expression_spec.rb +3 -3
  79. data/spec/graphql/schema/validation_spec.rb +7 -3
  80. data/spec/graphql/schema/warden_spec.rb +510 -0
  81. data/spec/graphql/schema_spec.rb +129 -0
  82. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -1
  83. data/spec/graphql/static_validation/type_stack_spec.rb +3 -3
  84. data/spec/spec_helper.rb +27 -1
  85. data/spec/support/dairy_app.rb +8 -5
  86. metadata +21 -3
  87. data/lib/graphql/language/parser_tests.rb +0 -809
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ BuiltInQueryParserSuite = GraphQL::Compatibility::QueryParserSpecification.build_suite do |query_string|
4
+ GraphQL::Language::Parser.parse(query_string)
5
+ end
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ BuiltInSchemaParserSuite = GraphQL::Compatibility::SchemaParserSpecification.build_suite do |query_string|
4
+ GraphQL::Language::Parser.parse(query_string)
5
+ end
@@ -73,6 +73,26 @@ describe GraphQL::Define::InstanceDefinable do
73
73
  end
74
74
  end
75
75
 
76
+ describe "#redefine" do
77
+ it "re-runs definitions without modifying the original object" do
78
+ arugula = Garden::Vegetable.define(name: "Arugula", color: :green)
79
+
80
+ red_arugula = arugula.redefine(color: :red)
81
+ renamed_red_arugula = red_arugula.redefine do
82
+ name "Renamed Red Arugula"
83
+ end
84
+
85
+ assert_equal :green, arugula.metadata[:color]
86
+ assert_equal "Arugula", arugula.name
87
+
88
+ assert_equal :red, red_arugula.metadata[:color]
89
+ assert_equal "Arugula", red_arugula.name
90
+
91
+ assert_equal :red, renamed_red_arugula.metadata[:color]
92
+ assert_equal "Renamed Red Arugula", renamed_red_arugula.name
93
+ end
94
+ end
95
+
76
96
  describe "#metadata" do
77
97
  it "gets values from definitions" do
78
98
  arugula = Garden::Vegetable.define(name: "Arugula", color: :green)
@@ -212,4 +212,15 @@ describe GraphQL::Directive do
212
212
  end
213
213
  end
214
214
  end
215
+
216
+ describe "defining a directive" do
217
+ it "can accept an array of arguments" do
218
+ directive = GraphQL::Directive.define do
219
+ arguments [GraphQL::Argument.define(name: 'skip')]
220
+ end
221
+
222
+ assert_equal 1, directive.arguments.length
223
+ assert_equal 'skip', directive.arguments.first.name
224
+ end
225
+ end
215
226
  end
@@ -15,6 +15,25 @@ describe GraphQL::EnumType do
15
15
  it "coerces result values to value's value" do
16
16
  assert_equal("YAK", enum.coerce_result("YAK"))
17
17
  assert_equal("COW", enum.coerce_result(1))
18
+ assert_equal("REINDEER", enum.coerce_result('reindeer'))
19
+ assert_equal("DONKEY", enum.coerce_result(:donkey))
20
+ end
21
+
22
+ it "raises when a result value can't be coerced" do
23
+ assert_raises(GraphQL::EnumType::UnresolvedValueError) {
24
+ enum.coerce_result(:nonsense)
25
+ }
26
+ end
27
+
28
+ describe "resolving with a warden" do
29
+ it "gets values from the warden" do
30
+ # OK
31
+ assert_equal("YAK", enum.coerce_result("YAK"))
32
+ # NOT OK
33
+ assert_raises(GraphQL::EnumType::UnresolvedValueError) {
34
+ enum.coerce_result("YAK", NothingWarden)
35
+ }
36
+ end
18
37
  end
19
38
 
20
39
  it "has value description" do
@@ -22,7 +41,7 @@ describe GraphQL::EnumType do
22
41
  end
23
42
 
24
43
  describe "validate_input with bad input" do
25
- let(:result) { DairyAnimalEnum.validate_input("bad enum") }
44
+ let(:result) { DairyAnimalEnum.validate_input("bad enum", PermissiveWarden) }
26
45
 
27
46
  it "returns an invalid result" do
28
47
  assert(!result.valid?)
@@ -13,18 +13,18 @@ describe GraphQL::InputObjectType do
13
13
  describe "input validation" do
14
14
  it "Accepts anything that yields key-value pairs to #all?" do
15
15
  values_obj = MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4})
16
- assert DairyProductInputType.valid_input?(values_obj)
16
+ assert DairyProductInputType.valid_input?(values_obj, PermissiveWarden)
17
17
  end
18
18
 
19
19
  describe "validate_input with non-enumerable input" do
20
20
  it "returns a valid result for MinimumInputObject" do
21
- result = DairyProductInputType.validate_input(MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4}))
21
+ result = DairyProductInputType.validate_input(MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4}), PermissiveWarden)
22
22
  assert(result.valid?)
23
23
  end
24
24
 
25
25
  it "returns an invalid result for MinimumInvalidInputObject" do
26
26
  invalid_input = MinimumInputObject.new({"source" => "KOALA", "fatContent" => 0.4})
27
- result = DairyProductInputType.validate_input(invalid_input)
27
+ result = DairyProductInputType.validate_input(invalid_input, PermissiveWarden)
28
28
  assert(!result.valid?)
29
29
  end
30
30
  end
@@ -37,7 +37,7 @@ describe GraphQL::InputObjectType do
37
37
  "fatContent" => 0.4
38
38
  }
39
39
  end
40
- let(:result) { DairyProductInputType.validate_input(input) }
40
+ let(:result) { DairyProductInputType.validate_input(input, PermissiveWarden) }
41
41
 
42
42
  it "returns a valid result" do
43
43
  assert(result.valid?)
@@ -45,7 +45,7 @@ describe GraphQL::InputObjectType do
45
45
  end
46
46
 
47
47
  describe "with bad enum and float" do
48
- let(:result) { DairyProductInputType.validate_input("source" => "KOALA", "fatContent" => "bad_num") }
48
+ let(:result) { DairyProductInputType.validate_input({"source" => "KOALA", "fatContent" => "bad_num"}, PermissiveWarden) }
49
49
 
50
50
  it "returns an invalid result" do
51
51
  assert(!result.valid?)
@@ -58,7 +58,7 @@ describe GraphQL::InputObjectType do
58
58
  end
59
59
 
60
60
  it "has correct problem explanation" do
61
- expected = DairyAnimalEnum.validate_input("KOALA").problems[0]["explanation"]
61
+ expected = DairyAnimalEnum.validate_input("KOALA", PermissiveWarden).problems[0]["explanation"]
62
62
 
63
63
  source_problem = result.problems.detect { |p| p["path"] == ["source"] }
64
64
  actual = source_problem["explanation"]
@@ -68,7 +68,7 @@ describe GraphQL::InputObjectType do
68
68
  end
69
69
 
70
70
  describe "with extra argument" do
71
- let(:result) { DairyProductInputType.validate_input("source" => "COW", "fatContent" => 0.4, "isDelicious" => false) }
71
+ let(:result) { DairyProductInputType.validate_input({"source" => "COW", "fatContent" => 0.4, "isDelicious" => false}, PermissiveWarden) }
72
72
 
73
73
  it "returns an invalid result" do
74
74
  assert(!result.valid?)
@@ -90,7 +90,7 @@ describe GraphQL::InputObjectType do
90
90
  list_type.validate_input([
91
91
  { "source" => "COW", "fatContent" => 0.4 },
92
92
  { "source" => "KOALA", "fatContent" => 0.4 }
93
- ])
93
+ ], PermissiveWarden)
94
94
  end
95
95
 
96
96
  it "returns an invalid result" do
@@ -107,7 +107,7 @@ describe GraphQL::InputObjectType do
107
107
  end
108
108
 
109
109
  it "has problem with correct explanation" do
110
- expected = DairyAnimalEnum.validate_input("KOALA").problems[0]["explanation"]
110
+ expected = DairyAnimalEnum.validate_input("KOALA", PermissiveWarden).problems[0]["explanation"]
111
111
  actual = result.problems[0]["explanation"]
112
112
  assert_equal(expected, actual)
113
113
  end
@@ -6,7 +6,7 @@ describe GraphQL::Introspection::DirectiveType do
6
6
  __schema {
7
7
  directives {
8
8
  name,
9
- args { name, type { name, ofType { name } } },
9
+ args { name, type { kind, name, ofType { name } } },
10
10
  locations
11
11
  # Deprecated fields:
12
12
  onField
@@ -25,7 +25,7 @@ describe GraphQL::Introspection::DirectiveType do
25
25
  {
26
26
  "name" => "include",
27
27
  "args" => [
28
- {"name"=>"if", "type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"Boolean"}}}
28
+ {"name"=>"if", "type"=>{"kind"=>"NON_NULL", "name"=>nil, "ofType"=>{"name"=>"Boolean"}}}
29
29
  ],
30
30
  "locations"=>["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"],
31
31
  "onField" => true,
@@ -35,7 +35,7 @@ describe GraphQL::Introspection::DirectiveType do
35
35
  {
36
36
  "name" => "skip",
37
37
  "args" => [
38
- {"name"=>"if", "type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"Boolean"}}}
38
+ {"name"=>"if", "type"=>{"kind"=>"NON_NULL", "name"=>nil, "ofType"=>{"name"=>"Boolean"}}}
39
39
  ],
40
40
  "locations"=>["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"],
41
41
  "onField" => true,
@@ -45,7 +45,7 @@ describe GraphQL::Introspection::DirectiveType do
45
45
  {
46
46
  "name" => "deprecated",
47
47
  "args" => [
48
- {"name"=>"reason", "type"=>{"name"=>"String", "ofType"=>nil}}
48
+ {"name"=>"reason", "type"=>{"kind"=>"SCALAR", "name"=>"String", "ofType"=>nil}}
49
49
  ],
50
50
  "locations"=>["FIELD_DEFINITION", "ENUM_VALUE"],
51
51
  "onField" => false,
@@ -10,7 +10,7 @@ describe GraphQL::Introspection::InputValueType do
10
10
  kind,
11
11
  inputFields {
12
12
  name,
13
- type { name },
13
+ type { kind, name },
14
14
  defaultValue
15
15
  description
16
16
  }
@@ -26,13 +26,13 @@ describe GraphQL::Introspection::InputValueType do
26
26
  "description"=>"Properties for finding a dairy product",
27
27
  "kind"=>"INPUT_OBJECT",
28
28
  "inputFields"=>[
29
- {"name"=>"source", "type"=>{ "name" => "Non-Null"}, "defaultValue"=>nil,
29
+ {"name"=>"source", "type"=>{"kind"=>"NON_NULL", "name" => nil}, "defaultValue"=>nil,
30
30
  "description" => "Where it came from"},
31
- {"name"=>"originDairy", "type"=>{ "name" => "String"}, "defaultValue"=>"\"Sugar Hollow Dairy\"",
31
+ {"name"=>"originDairy", "type"=>{"kind"=>"SCALAR", "name" => "String"}, "defaultValue"=>"\"Sugar Hollow Dairy\"",
32
32
  "description" => "Dairy which produced it"},
33
- {"name"=>"fatContent", "type"=>{ "name" => "Float"}, "defaultValue"=>"0.3",
33
+ {"name"=>"fatContent", "type"=>{"kind"=>"SCALAR", "name" => "Float"}, "defaultValue"=>"0.3",
34
34
  "description" => "How much fat it has"},
35
- {"name"=>"organic", "type"=>{ "name" => "Boolean"}, "defaultValue"=>"false",
35
+ {"name"=>"organic", "type"=>{"kind"=>"SCALAR", "name" => "Boolean"}, "defaultValue"=>"false",
36
36
  "description" => nil}
37
37
  ]
38
38
  }
@@ -58,7 +58,7 @@ describe GraphQL::Introspection::InputValueType do
58
58
 
59
59
  it "converts default values to GraphQL values" do
60
60
  field = cheese_type['data']['__type']['fields'].detect { |f| f['name'] == 'similarCheese' }
61
- arg = field['args'].detect { |a| a['name'] == 'source' }
61
+ arg = field['args'].detect { |a| a['name'] == 'nullableSource' }
62
62
 
63
63
  assert_equal('["COW"]', arg['defaultValue'])
64
64
  end
@@ -3,8 +3,8 @@ require "spec_helper"
3
3
  describe GraphQL::Introspection::TypeType do
4
4
  let(:query_string) {%|
5
5
  query introspectionQuery {
6
- cheeseType: __type(name: "Cheese") { name, kind, fields { name, isDeprecated, type { name, ofType { name } } } }
7
- milkType: __type(name: "Milk") { interfaces { name }, fields { type { name, ofType { name } } } }
6
+ cheeseType: __type(name: "Cheese") { name, kind, fields { name, isDeprecated, type { kind, name, ofType { name } } } }
7
+ milkType: __type(name: "Milk") { interfaces { name }, fields { type { kind, name, ofType { name } } } }
8
8
  dairyAnimal: __type(name: "DairyAnimal") { name, kind, enumValues(includeDeprecated: false) { name, isDeprecated } }
9
9
  dairyProduct: __type(name: "DairyProduct") { name, kind, possibleTypes { name } }
10
10
  animalProduct: __type(name: "AnimalProduct") { name, kind, possibleTypes { name }, fields { name } }
@@ -13,19 +13,21 @@ describe GraphQL::Introspection::TypeType do
13
13
  |}
14
14
  let(:result) { DummySchema.execute(query_string, context: {}, variables: {"cheeseId" => 2}) }
15
15
  let(:cheese_fields) {[
16
- {"name"=>"deeplyNullableCheese", "isDeprecated"=>false, "type"=>{"name"=>"Cheese", "ofType"=>nil}},
17
- {"name"=>"flavor", "isDeprecated" => false, "type" => { "name" => "Non-Null", "ofType" => { "name" => "String"}}},
18
- {"name"=>"id", "isDeprecated" => false, "type" => { "name" => "Non-Null", "ofType" => { "name" => "Int"}}},
19
- {"name"=>"nullableCheese", "isDeprecated"=>false, "type"=>{"name"=>"Cheese", "ofType"=>nil}},
20
- {"name"=>"origin", "isDeprecated" => false, "type" => { "name" => "Non-Null", "ofType" => { "name" => "String"}}},
21
- {"name"=>"similarCheese", "isDeprecated"=>false, "type"=>{"name"=>"Cheese", "ofType"=>nil}},
22
- {"name"=>"source", "isDeprecated" => false, "type" => { "name" => "Non-Null", "ofType" => { "name" => "DairyAnimal"}}},
16
+ {"name"=>"deeplyNullableCheese", "isDeprecated" => false, "type"=>{ "kind" => "OBJECT", "name" => "Cheese", "ofType" => nil}},
17
+ {"name"=>"flavor", "isDeprecated" => false, "type" => { "kind" => "NON_NULL", "name" => nil, "ofType" => { "name" => "String"}}},
18
+ {"name"=>"id", "isDeprecated" => false, "type" => { "kind" => "NON_NULL", "name" => nil, "ofType" => { "name" => "Int"}}},
19
+ {"name"=>"nullableCheese", "isDeprecated"=>false, "type"=>{ "kind" => "OBJECT", "name" => "Cheese", "ofType"=>nil}},
20
+ {"name"=>"origin", "isDeprecated" => false, "type" => { "kind" => "NON_NULL", "name" => nil, "ofType" => { "name" => "String"}}},
21
+ {"name"=>"similarCheese", "isDeprecated"=>false, "type"=>{ "kind" => "OBJECT", "name"=>"Cheese", "ofType"=>nil}},
22
+ {"name"=>"source", "isDeprecated" => false, "type" => { "kind" => "NON_NULL", "name" => nil, "ofType" => { "name" => "DairyAnimal"}}},
23
23
  ]}
24
24
 
25
25
  let(:dairy_animals) {[
26
- {"name"=>"COW", "isDeprecated"=> false },
27
- {"name"=>"GOAT", "isDeprecated"=> false },
28
- {"name"=>"SHEEP", "isDeprecated"=> false },
26
+ {"name"=>"COW", "isDeprecated"=> false },
27
+ {"name"=>"DONKEY", "isDeprecated"=> false },
28
+ {"name"=>"GOAT", "isDeprecated"=> false },
29
+ {"name"=>"REINDEER", "isDeprecated"=> false },
30
+ {"name"=>"SHEEP", "isDeprecated"=> false },
29
31
  ]}
30
32
  it "exposes metadata about types" do
31
33
  expected = {"data"=> {
@@ -41,13 +43,13 @@ describe GraphQL::Introspection::TypeType do
41
43
  {"name"=>"LocalProduct"},
42
44
  ],
43
45
  "fields"=>[
44
- {"type"=>{"name"=>"List", "ofType"=>{"name"=>"DairyProduct"}}},
45
- {"type"=>{"name"=>"String", "ofType"=>nil}},
46
- {"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"Float"}}},
47
- {"type"=>{"name"=>"List", "ofType"=>{"name"=>"String"}}},
48
- {"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"ID"}}},
49
- {"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"String"}}},
50
- {"type"=>{"name"=>"DairyAnimal", "ofType"=>nil}},
46
+ {"type"=>{"kind"=>"LIST","name"=>nil, "ofType"=>{"name"=>"DairyProduct"}}},
47
+ {"type"=>{"kind"=>"SCALAR","name"=>"String", "ofType"=>nil}},
48
+ {"type"=>{"kind"=>"NON_NULL","name"=>nil, "ofType"=>{"name"=>"Float"}}},
49
+ {"type"=>{"kind"=>"LIST","name"=>nil, "ofType"=>{"name"=>"String"}}},
50
+ {"type"=>{"kind"=>"NON_NULL","name"=>nil, "ofType"=>{"name"=>"ID"}}},
51
+ {"type"=>{"kind"=>"NON_NULL","name"=>nil, "ofType"=>{"name"=>"String"}}},
52
+ {"type"=>{"kind"=>"ENUM","name"=>"DairyAnimal", "ofType"=>nil}},
51
53
  ]
52
54
  },
53
55
  "dairyAnimal"=>{
@@ -76,11 +78,11 @@ describe GraphQL::Introspection::TypeType do
76
78
  describe "deprecated fields" do
77
79
  let(:query_string) {%|
78
80
  query introspectionQuery {
79
- cheeseType: __type(name: "Cheese") { name, kind, fields(includeDeprecated: true) { name, isDeprecated, type { name, ofType { name } } } }
81
+ cheeseType: __type(name: "Cheese") { name, kind, fields(includeDeprecated: true) { name, isDeprecated, type { kind, name, ofType { name } } } }
80
82
  dairyAnimal: __type(name: "DairyAnimal") { name, kind, enumValues(includeDeprecated: true) { name, isDeprecated } }
81
83
  }
82
84
  |}
83
- let(:deprecated_fields) { {"name"=>"fatContent", "isDeprecated"=>true, "type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"Float"}}} }
85
+ let(:deprecated_fields) { {"name"=>"fatContent", "isDeprecated"=>true, "type"=>{"kind"=>"NON_NULL","name"=>nil, "ofType"=>{"name"=>"Float"}}} }
84
86
 
85
87
  it "can expose deprecated fields" do
86
88
  new_cheese_fields = ([deprecated_fields] + cheese_fields).sort_by { |f| f["name"] }
@@ -102,7 +104,7 @@ describe GraphQL::Introspection::TypeType do
102
104
  describe "input objects" do
103
105
  let(:query_string) {%|
104
106
  query introspectionQuery {
105
- __type(name: "DairyProductInput") { name, description, kind, inputFields { name, type { name }, defaultValue } }
107
+ __type(name: "DairyProductInput") { name, description, kind, inputFields { name, type { kind, name }, defaultValue } }
106
108
  }
107
109
  |}
108
110
 
@@ -113,10 +115,10 @@ describe GraphQL::Introspection::TypeType do
113
115
  "description"=>"Properties for finding a dairy product",
114
116
  "kind"=>"INPUT_OBJECT",
115
117
  "inputFields"=>[
116
- {"name"=>"source", "type"=>{ "name" => "Non-Null"}, "defaultValue"=>nil},
117
- {"name"=>"originDairy", "type"=>{"name"=>"String"}, "defaultValue"=>"\"Sugar Hollow Dairy\""},
118
- {"name"=>"fatContent", "type"=>{ "name" => "Float"}, "defaultValue"=>"0.3"},
119
- {"name"=>"organic", "type"=>{ "name" => "Boolean"}, "defaultValue"=>"false"},
118
+ {"name"=>"source", "type"=>{"kind"=>"NON_NULL","name"=>nil, }, "defaultValue"=>nil},
119
+ {"name"=>"originDairy", "type"=>{"kind"=>"SCALAR","name"=>"String"}, "defaultValue"=>"\"Sugar Hollow Dairy\""},
120
+ {"name"=>"fatContent", "type"=>{"kind"=>"SCALAR","name" => "Float"}, "defaultValue"=>"0.3"},
121
+ {"name"=>"organic", "type"=>{"kind"=>"SCALAR","name" => "Boolean"}, "defaultValue"=>"false"},
120
122
  ]
121
123
  }
122
124
  }}
@@ -1,8 +1,6 @@
1
1
  require "spec_helper"
2
- require 'graphql/language/parser_tests'
3
2
 
4
3
  describe GraphQL::Language::Parser do
5
- include GraphQL::Language::ParserTests
6
4
  subject { GraphQL::Language::Parser }
7
5
 
8
6
  describe "anonymous fragment extension" do
@@ -13,23 +11,35 @@ describe GraphQL::Language::Parser do
13
11
  }
14
12
  |}
15
13
 
16
- describe ".parse" do
17
- it "parses queries" do
18
- assert document
19
- end
14
+ let(:fragment) { document.definitions.first }
20
15
 
21
- describe "visited nodes" do
22
- let(:fragment) { document.definitions.first }
16
+ it "creates an anonymous fragment definition" do
17
+ assert fragment.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
18
+ assert_equal nil, fragment.name
19
+ assert_equal 1, fragment.selections.length
20
+ assert_equal "NestedType", fragment.type.name
21
+ assert_equal 1, fragment.directives.length
22
+ assert_equal [2, 7], fragment.position
23
+ end
24
+ end
23
25
 
24
- it "creates an anonymous fragment definition" do
25
- assert fragment.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
26
- assert_equal nil, fragment.name
27
- assert_equal 1, fragment.selections.length
28
- assert_equal "NestedType", fragment.type.name
29
- assert_equal 1, fragment.directives.length
30
- assert_equal [2, 7], fragment.position
31
- end
32
- end
26
+ it "parses empty arguments" do
27
+ strings = [
28
+ "{ field { inner } }",
29
+ "{ field() { inner }}",
30
+ ]
31
+ strings.each do |query_str|
32
+ doc = subject.parse(query_str)
33
+ field = doc.definitions.first.selections.first
34
+ assert_equal 0, field.arguments.length
35
+ assert_equal 1, field.selections.length
33
36
  end
34
37
  end
38
+
39
+ it "parses the test schema" do
40
+ schema = DummySchema
41
+ schema_string = GraphQL::Schema::Printer.print_schema(schema)
42
+ document = subject.parse(schema_string)
43
+ assert_equal schema_string, document.to_query_string
44
+ end
35
45
  end
@@ -9,7 +9,7 @@ describe GraphQL::ListType do
9
9
 
10
10
  describe "validate_input with bad input" do
11
11
  let(:bad_num) { "bad_num" }
12
- let(:result) { float_list.validate_input([bad_num, 2.0, 3.0]) }
12
+ let(:result) { float_list.validate_input([bad_num, 2.0, 3.0], PermissiveWarden) }
13
13
 
14
14
  it "returns an invalid result" do
15
15
  assert(!result.valid?)
@@ -24,7 +24,7 @@ describe GraphQL::ListType do
24
24
  end
25
25
 
26
26
  it "has the correct explanation" do
27
- expected = GraphQL::FLOAT_TYPE.validate_input(bad_num).problems[0]["explanation"]
27
+ expected = GraphQL::FLOAT_TYPE.validate_input(bad_num, PermissiveWarden).problems[0]["explanation"]
28
28
  actual = result.problems[0]["explanation"]
29
29
  assert_equal(actual, expected)
30
30
  end
@@ -11,6 +11,7 @@ describe GraphQL::Query::Variables do
11
11
  let(:ast_variables) { GraphQL.parse(query_string).definitions.first.variables }
12
12
  let(:variables) { GraphQL::Query::Variables.new(
13
13
  DummySchema,
14
+ GraphQL::Schema::Warden.new(DummySchema, GraphQL::Query::NullExcept),
14
15
  ast_variables,
15
16
  provided_variables)
16
17
  }
@@ -23,7 +23,7 @@ describe GraphQL::ScalarType do
23
23
  end
24
24
 
25
25
  describe "custom scalar errors" do
26
- let(:result) { custom_scalar.validate_input("xyz") }
26
+ let(:result) { custom_scalar.validate_input("xyz", PermissiveWarden) }
27
27
 
28
28
  it "returns an invalid result" do
29
29
  assert !result.valid?
@@ -32,7 +32,7 @@ describe GraphQL::ScalarType do
32
32
  end
33
33
 
34
34
  describe "validate_input with good input" do
35
- let(:result) { GraphQL::INT_TYPE.validate_input(150) }
35
+ let(:result) { GraphQL::INT_TYPE.validate_input(150, PermissiveWarden) }
36
36
 
37
37
  it "returns a valid result" do
38
38
  assert(result.valid?)
@@ -40,7 +40,7 @@ describe GraphQL::ScalarType do
40
40
  end
41
41
 
42
42
  describe "validate_input with bad input" do
43
- let(:result) { GraphQL::INT_TYPE.validate_input("bad num") }
43
+ let(:result) { GraphQL::INT_TYPE.validate_input("bad num", PermissiveWarden) }
44
44
 
45
45
  it "returns an invalid result for bad input" do
46
46
  assert(!result.valid?)