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.
- checksums.yaml +4 -4
- data/lib/graphql.rb +10 -0
- data/lib/graphql/base_type.rb +8 -5
- data/lib/graphql/compatibility.rb +3 -0
- data/lib/graphql/compatibility/execution_specification.rb +414 -0
- data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +81 -0
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +78 -0
- data/lib/graphql/compatibility/schema_parser_specification.rb +239 -0
- data/lib/graphql/define/instance_definable.rb +53 -21
- data/lib/graphql/directive.rb +1 -1
- data/lib/graphql/enum_type.rb +31 -8
- data/lib/graphql/execution/directive_checks.rb +0 -6
- data/lib/graphql/input_object_type.rb +6 -4
- data/lib/graphql/introspection/arguments_field.rb +3 -1
- data/lib/graphql/introspection/enum_values_field.rb +10 -5
- data/lib/graphql/introspection/fields_field.rb +1 -1
- data/lib/graphql/introspection/input_fields_field.rb +2 -2
- data/lib/graphql/introspection/interfaces_field.rb +7 -1
- data/lib/graphql/introspection/possible_types_field.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +1 -1
- data/lib/graphql/introspection/type_by_name_field.rb +4 -2
- data/lib/graphql/introspection/type_type.rb +7 -6
- data/lib/graphql/language/lexer.rl +0 -4
- data/lib/graphql/language/parser.rb +1 -1
- data/lib/graphql/language/parser.y +1 -1
- data/lib/graphql/list_type.rb +3 -4
- data/lib/graphql/non_null_type.rb +4 -8
- data/lib/graphql/object_type.rb +5 -3
- data/lib/graphql/query.rb +48 -12
- data/lib/graphql/query/context.rb +7 -1
- data/lib/graphql/query/serial_execution/execution_context.rb +8 -3
- data/lib/graphql/query/serial_execution/field_resolution.rb +8 -5
- data/lib/graphql/query/serial_execution/operation_resolution.rb +2 -2
- data/lib/graphql/query/serial_execution/selection_resolution.rb +4 -21
- data/lib/graphql/query/serial_execution/value_resolution.rb +59 -99
- data/lib/graphql/query/variables.rb +7 -2
- data/lib/graphql/scalar_type.rb +1 -1
- data/lib/graphql/schema.rb +49 -18
- data/lib/graphql/schema/build_from_definition.rb +248 -0
- data/lib/graphql/schema/instrumented_field_map.rb +23 -0
- data/lib/graphql/schema/loader.rb +4 -11
- data/lib/graphql/schema/possible_types.rb +4 -2
- data/lib/graphql/schema/printer.rb +1 -1
- data/lib/graphql/schema/type_expression.rb +4 -4
- data/lib/graphql/schema/type_map.rb +1 -1
- data/lib/graphql/schema/validation.rb +4 -0
- data/lib/graphql/schema/warden.rb +114 -0
- data/lib/graphql/static_validation/literal_validator.rb +10 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -3
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -14
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -4
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +2 -1
- data/lib/graphql/static_validation/validation_context.rb +7 -1
- data/lib/graphql/union_type.rb +6 -3
- data/lib/graphql/unresolved_type_error.rb +1 -2
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -5
- data/spec/graphql/compatibility/execution_specification_spec.rb +3 -0
- data/spec/graphql/compatibility/query_parser_specification_spec.rb +5 -0
- data/spec/graphql/compatibility/schema_parser_specification_spec.rb +5 -0
- data/spec/graphql/define/instance_definable_spec.rb +20 -0
- data/spec/graphql/directive_spec.rb +11 -0
- data/spec/graphql/enum_type_spec.rb +20 -1
- data/spec/graphql/input_object_type_spec.rb +9 -9
- data/spec/graphql/introspection/directive_type_spec.rb +4 -4
- data/spec/graphql/introspection/input_value_type_spec.rb +6 -6
- data/spec/graphql/introspection/type_type_spec.rb +28 -26
- data/spec/graphql/language/parser_spec.rb +27 -17
- data/spec/graphql/list_type_spec.rb +2 -2
- data/spec/graphql/query/variables_spec.rb +1 -0
- data/spec/graphql/scalar_type_spec.rb +3 -3
- data/spec/graphql/schema/build_from_definition_spec.rb +693 -0
- data/spec/graphql/schema/type_expression_spec.rb +3 -3
- data/spec/graphql/schema/validation_spec.rb +7 -3
- data/spec/graphql/schema/warden_spec.rb +510 -0
- data/spec/graphql/schema_spec.rb +129 -0
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -1
- data/spec/graphql/static_validation/type_stack_spec.rb +3 -3
- data/spec/spec_helper.rb +27 -1
- data/spec/support/dairy_app.rb +8 -5
- metadata +21 -3
- data/lib/graphql/language/parser_tests.rb +0 -809
@@ -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"=>{"
|
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"=>{"
|
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" =>
|
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"=>{
|
33
|
+
{"name"=>"fatContent", "type"=>{"kind"=>"SCALAR", "name" => "Float"}, "defaultValue"=>"0.3",
|
34
34
|
"description" => "How much fat it has"},
|
35
|
-
{"name"=>"organic", "type"=>{
|
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'] == '
|
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" => { "
|
18
|
-
{"name"=>"id", "isDeprecated" => false, "type" => { "
|
19
|
-
{"name"=>"nullableCheese", "isDeprecated"=>false, "type"=>{"name"=>"Cheese", "ofType"=>nil}},
|
20
|
-
{"name"=>"origin", "isDeprecated" => false, "type" => { "
|
21
|
-
{"name"=>"similarCheese", "isDeprecated"=>false, "type"=>{"name"=>"Cheese", "ofType"=>nil}},
|
22
|
-
{"name"=>"source", "isDeprecated" => false, "type" => { "
|
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",
|
27
|
-
{"name"=>"
|
28
|
-
{"name"=>"
|
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"=>{"
|
45
|
-
{"type"=>{"name"=>"String", "ofType"=>nil}},
|
46
|
-
{"type"=>{"
|
47
|
-
{"type"=>{"
|
48
|
-
{"type"=>{"
|
49
|
-
{"type"=>{"
|
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"=>{"
|
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"=>{
|
117
|
-
{"name"=>"originDairy", "type"=>{"name"=>"String"}, "defaultValue"=>"\"Sugar Hollow Dairy\""},
|
118
|
-
{"name"=>"fatContent", "type"=>{
|
119
|
-
{"name"=>"organic", "type"=>{
|
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
|
-
|
17
|
-
it "parses queries" do
|
18
|
-
assert document
|
19
|
-
end
|
14
|
+
let(:fragment) { document.definitions.first }
|
20
15
|
|
21
|
-
|
22
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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?)
|