graphql 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/graph_ql/{types → definition_helpers}/argument_definer.rb +0 -0
- data/lib/graph_ql/definition_helpers/definable.rb +18 -0
- data/lib/graph_ql/{types → definition_helpers}/field_definer.rb +0 -0
- data/lib/graph_ql/definition_helpers/forwardable.rb +10 -0
- data/lib/graph_ql/definition_helpers/non_null_with_bang.rb +9 -0
- data/lib/graph_ql/definition_helpers/string_named_hash.rb +12 -0
- data/lib/graph_ql/{types → definition_helpers}/type_definer.rb +1 -0
- data/lib/graph_ql/directive.rb +9 -5
- data/lib/graph_ql/directives/directive_chain.rb +1 -1
- data/lib/graph_ql/field.rb +1 -5
- data/lib/graph_ql/parser/transform.rb +1 -3
- data/lib/graph_ql/query.rb +14 -3
- data/lib/graph_ql/query/arguments.rb +6 -5
- data/lib/graph_ql/query/field_resolution_strategy.rb +3 -3
- data/lib/graph_ql/{types → scalars}/boolean_type.rb +0 -0
- data/lib/graph_ql/{types → scalars}/float_type.rb +1 -1
- data/lib/graph_ql/scalars/id_type.rb +6 -0
- data/lib/graph_ql/{types → scalars}/int_type.rb +0 -0
- data/lib/graph_ql/{types → scalars}/scalar_type.rb +0 -4
- data/lib/graph_ql/{types → scalars}/string_type.rb +0 -0
- data/lib/graph_ql/static_validation.rb +7 -10
- data/lib/graph_ql/static_validation/all_rules.rb +23 -0
- data/lib/graph_ql/static_validation/literal_validator.rb +0 -3
- data/lib/graph_ql/static_validation/{argument_literals_are_compatible.rb → rules/argument_literals_are_compatible.rb} +0 -0
- data/lib/graph_ql/static_validation/{arguments_are_defined.rb → rules/arguments_are_defined.rb} +5 -0
- data/lib/graph_ql/static_validation/{directives_are_defined.rb → rules/directives_are_defined.rb} +0 -0
- data/lib/graph_ql/static_validation/{fields_are_defined_on_type.rb → rules/fields_are_defined_on_type.rb} +0 -0
- data/lib/graph_ql/static_validation/{fields_have_appropriate_selections.rb → rules/fields_have_appropriate_selections.rb} +0 -0
- data/lib/graph_ql/static_validation/{fields_will_merge.rb → rules/fields_will_merge.rb} +13 -5
- data/lib/graph_ql/static_validation/rules/fragment_spreads_are_possible.rb +50 -0
- data/lib/graph_ql/static_validation/{fragment_types_exist.rb → rules/fragment_types_exist.rb} +0 -0
- data/lib/graph_ql/static_validation/rules/fragments_are_finite.rb +23 -0
- data/lib/graph_ql/static_validation/rules/fragments_are_on_composite_types.rb +27 -0
- data/lib/graph_ql/static_validation/{fragments_are_used.rb → rules/fragments_are_used.rb} +0 -0
- data/lib/graph_ql/static_validation/{required_arguments_are_present.rb → rules/required_arguments_are_present.rb} +0 -0
- data/lib/graph_ql/static_validation/rules/variable_default_values_are_correctly_typed.rb +24 -0
- data/lib/graph_ql/static_validation/rules/variable_usages_are_allowed.rb +47 -0
- data/lib/graph_ql/static_validation/rules/variables_are_input_types.rb +27 -0
- data/lib/graph_ql/static_validation/rules/variables_are_used_and_defined.rb +31 -0
- data/lib/graph_ql/static_validation/type_stack.rb +13 -1
- data/lib/graph_ql/static_validation/validator.rb +14 -18
- data/lib/graph_ql/type_kinds.rb +8 -4
- data/lib/graph_ql/{enum.rb → types/enum.rb} +7 -6
- data/lib/graph_ql/types/input_object_type.rb +3 -10
- data/lib/graph_ql/{interface.rb → types/interface.rb} +0 -4
- data/lib/graph_ql/types/list_type.rb +0 -4
- data/lib/graph_ql/types/non_null_type.rb +0 -4
- data/lib/graph_ql/types/object_type.rb +28 -13
- data/lib/graph_ql/{union.rb → types/union.rb} +0 -4
- data/lib/graph_ql/version.rb +1 -1
- data/lib/graphql.rb +9 -40
- data/readme.md +26 -20
- data/spec/graph_ql/directive_spec.rb +4 -4
- data/spec/graph_ql/introspection/directive_type_spec.rb +2 -2
- data/spec/graph_ql/introspection/schema_type_spec.rb +3 -2
- data/spec/graph_ql/introspection/type_type_spec.rb +7 -7
- data/spec/graph_ql/parser/parser_spec.rb +6 -2
- data/spec/graph_ql/query_spec.rb +26 -8
- data/spec/graph_ql/scalars/id_type_spec.rb +24 -0
- data/spec/graph_ql/schema/type_reducer_spec.rb +1 -0
- data/spec/graph_ql/schema/type_validator_spec.rb +1 -1
- data/spec/graph_ql/static_validation/{argument_literals_are_compatible_spec.rb → rules/argument_literals_are_compatible_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{arguments_are_defined_spec.rb → rules/arguments_are_defined_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{directives_are_defined_spec.rb → rules/directives_are_defined_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{fields_are_defined_on_type_spec.rb → rules/fields_are_defined_on_type_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{fields_have_appropriate_selections_spec.rb → rules/fields_have_appropriate_selections_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{fields_will_merge_spec.rb → rules/fields_will_merge_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/rules/fragment_spreads_are_possible_spec.rb +46 -0
- data/spec/graph_ql/static_validation/{fragment_types_exist_spec.rb → rules/fragment_types_exist_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/rules/fragments_are_finite_spec.rb +43 -0
- data/spec/graph_ql/static_validation/rules/fragments_are_on_composite_types_spec.rb +48 -0
- data/spec/graph_ql/static_validation/{fragments_are_used_spec.rb → rules/fragments_are_used_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/{required_arguments_are_present_spec.rb → rules/required_arguments_are_present_spec.rb} +1 -1
- data/spec/graph_ql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +43 -0
- data/spec/graph_ql/static_validation/rules/variable_usages_are_allowed_spec.rb +45 -0
- data/spec/graph_ql/static_validation/rules/variables_are_input_types_spec.rb +36 -0
- data/spec/graph_ql/static_validation/rules/variables_are_used_and_defined_spec.rb +44 -0
- data/spec/graph_ql/static_validation/type_stack_spec.rb +2 -2
- data/spec/graph_ql/static_validation/validator_spec.rb +44 -5
- data/spec/graph_ql/types/enum_spec.rb +10 -0
- data/spec/graph_ql/{interface_spec.rb → types/interface_spec.rb} +1 -1
- data/spec/graph_ql/types/object_type_spec.rb +13 -0
- data/spec/graph_ql/{union_spec.rb → types/union_spec.rb} +0 -0
- data/spec/support/dummy_app.rb +7 -6
- data/spec/support/dummy_data.rb +3 -3
- metadata +74 -46
- data/lib/graph_ql/types/non_null_with_bang.rb +0 -5
- data/spec/graph_ql/enum_spec.rb +0 -5
data/lib/graph_ql/version.rb
CHANGED
data/lib/graphql.rb
CHANGED
@@ -12,56 +12,26 @@ module GraphQL
|
|
12
12
|
raise [line, col, string].join(", ")
|
13
13
|
end
|
14
14
|
|
15
|
-
module Definable
|
16
|
-
def attr_definable(*names)
|
17
|
-
attr_accessor(*names)
|
18
|
-
names.each do |name|
|
19
|
-
ivar_name = "@#{name}".to_sym
|
20
|
-
define_method(name) do |new_value=nil|
|
21
|
-
new_value && self.instance_variable_set(ivar_name, new_value)
|
22
|
-
instance_variable_get(ivar_name)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
module Forwardable
|
29
|
-
def delegate(*methods, to:)
|
30
|
-
methods.each do |method_name|
|
31
|
-
define_method(method_name) do |*args|
|
32
|
-
self.public_send(to).public_send(method_name, *args)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
15
|
module Introspection; end
|
39
16
|
end
|
40
17
|
|
18
|
+
def require_dir(dir)
|
19
|
+
Dir.glob(File.expand_path("../graph_ql/#{dir}/*.rb", __FILE__)).each do |file|
|
20
|
+
require file
|
21
|
+
end
|
22
|
+
end
|
41
23
|
# Order matters for these:
|
42
24
|
|
43
|
-
|
25
|
+
require_dir('definition_helpers')
|
44
26
|
require 'graph_ql/types/object_type'
|
45
|
-
|
46
|
-
require 'graph_ql/types/scalar_type'
|
47
|
-
require 'graph_ql/types/non_null_type'
|
48
|
-
require 'graph_ql/types/input_value'
|
49
|
-
require 'graph_ql/types/input_object_type'
|
50
|
-
|
51
|
-
require 'graph_ql/types/type_definer'
|
52
|
-
require 'graph_ql/types/field_definer'
|
53
|
-
require 'graph_ql/types/argument_definer'
|
27
|
+
require_dir('types')
|
54
28
|
|
55
|
-
require 'graph_ql/enum'
|
56
29
|
require 'graph_ql/field'
|
57
|
-
require 'graph_ql/union'
|
58
30
|
require 'graph_ql/type_kinds'
|
59
31
|
require 'graph_ql/introspection/typename_field'
|
60
32
|
|
61
|
-
require 'graph_ql/
|
62
|
-
|
63
|
-
require 'graph_ql/types/float_type'
|
64
|
-
require 'graph_ql/types/boolean_type'
|
33
|
+
require 'graph_ql/scalars/scalar_type'
|
34
|
+
require_dir('scalars')
|
65
35
|
|
66
36
|
require 'graph_ql/introspection/input_value_type'
|
67
37
|
require 'graph_ql/introspection/enum_value_type'
|
@@ -87,7 +57,6 @@ require 'graph_ql/schema'
|
|
87
57
|
|
88
58
|
# Order does not matter for these:
|
89
59
|
|
90
|
-
require 'graph_ql/interface'
|
91
60
|
require 'graph_ql/query'
|
92
61
|
require 'graph_ql/repl'
|
93
62
|
require 'graph_ql/static_validation'
|
data/readme.md
CHANGED
@@ -27,7 +27,7 @@
|
|
27
27
|
t.name "Post"
|
28
28
|
t.description "A blog post"
|
29
29
|
t.fields({
|
30
|
-
id: field.build(type: !types.Int)
|
30
|
+
id: field.build(type: !types.Int),
|
31
31
|
title: field.build(type: !types.String),
|
32
32
|
body: field.build(type: !types.String),
|
33
33
|
comments: field.build(type: types[!CommentType])
|
@@ -76,29 +76,35 @@
|
|
76
76
|
- [`queries_controller.rb`](https://github.com/rmosolgo/graphql-ruby-demo/blob/master/app/controllers/queries_controller.rb) for a Rails example
|
77
77
|
- Try it on [heroku](http://graphql-ruby-demo.herokuapp.com)
|
78
78
|
|
79
|
-
## To Do
|
80
|
-
|
81
|
-
-
|
82
|
-
-
|
83
|
-
-
|
84
|
-
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
- [In abstract scope, object-typed fragments fit that type](http://facebook.github.io/graphql/#sec-Object-Spreads-In-Abstract-Scope)
|
89
|
-
- [In abstract scope, abstract-typed fragments must share a type](http://facebook.github.io/graphql/#sec-Abstract-Spreads-in-Abstract-Scope)
|
90
|
-
- everything in [Variables](http://facebook.github.io/graphql/#sec-Validation.Operations.Variables)
|
91
|
-
- directives:
|
92
|
-
- `@skip` has precedence over `@include`
|
93
|
-
- directives on fragments: http://facebook.github.io/graphql/#sec-Fragment-Directives
|
94
|
-
- Support any "real" value for enum, not just stringified name (see `Character::EPISODES` in demo)
|
95
|
-
- field merging (https://github.com/graphql/graphql-js/issues/19#issuecomment-118515077)
|
79
|
+
## To Do
|
80
|
+
|
81
|
+
- To match spec:
|
82
|
+
- Directives:
|
83
|
+
- `@skip` has precedence over `@include`
|
84
|
+
- directives on fragments: http://facebook.github.io/graphql/#sec-Fragment-Directives
|
85
|
+
- Field merging
|
86
|
+
- if you were to request a field, then request it in a fragment, it would get looked up twice
|
87
|
+
- https://github.com/graphql/graphql-js/issues/19#issuecomment-118515077
|
96
88
|
- Code clean-up
|
97
89
|
- Unify unwrapping types (It's on `TypeKind` but it's still not right)
|
98
|
-
|
90
|
+
- Cook up some path other than "n+1s everywhere"
|
99
91
|
|
100
|
-
## Goals
|
92
|
+
## Goals
|
101
93
|
|
102
94
|
- Implement the GraphQL spec & support a Relay front end
|
103
95
|
- Provide idiomatic, plain-Ruby API with similarities to reference implementation where possible
|
104
96
|
- Support `graphql-rails`
|
97
|
+
|
98
|
+
## Getting Involved
|
99
|
+
|
100
|
+
- __Say hi & ask questions__ in the [#ruby channel on Slack](https://graphql-slack.herokuapp.com/) or [on Twitter](https://twitter.com/rmosolgo)!
|
101
|
+
- __Report bugs__ by posting a description, full stack trace, and all relevant code in a [GitHub issue](https://github.com/rmosolgo/graphql-ruby/issues).
|
102
|
+
- __Features & patches__ are welcome! Consider discussing it in an [issue](https://github.com/rmosolgo/graphql-ruby/issues) or in the [#ruby channel on Slack](https://graphql-slack.herokuapp.com/) to make sure we're on the same page.
|
103
|
+
- __Run the tests__ with `rake test` or start up guard with `bundle exec guard`.
|
104
|
+
|
105
|
+
## Other Resources
|
106
|
+
|
107
|
+
- [GraphQL Spec](http://facebook.github.io/graphql/)
|
108
|
+
- Other implementations: [graphql-links](https://github.com/emmenko/graphql-links)
|
109
|
+
- `graphql-ruby` + Rails demo ([src](https://github.com/rmosolgo/graphql-ruby-demo) / [heroku](http://graphql-ruby-demo.herokuapp.com))
|
110
|
+
- [GraphQL Slack](https://graphql-slack.herokuapp.com/)
|
@@ -23,14 +23,14 @@ describe GraphQL::Directive do
|
|
23
23
|
fragment dontSkipIdField on Cheese { dontSkipId: id @skip(if: false) }
|
24
24
|
|}
|
25
25
|
it 'intercepts fields' do
|
26
|
-
expected = { "data" =>
|
26
|
+
expected = { "data" =>{
|
27
27
|
"cheese" => {
|
28
28
|
"dontSkipFlavor" => "Brie",
|
29
29
|
"includeFlavor" => "Brie",
|
30
30
|
"includeId" => 1,
|
31
31
|
"dontSkipId" => 1,
|
32
32
|
},
|
33
|
-
}}
|
33
|
+
}}
|
34
34
|
assert_equal(expected, result)
|
35
35
|
end
|
36
36
|
end
|
@@ -65,7 +65,7 @@ describe GraphQL::Directive do
|
|
65
65
|
|}
|
66
66
|
|
67
67
|
it 'intercepts fragment spreads' do
|
68
|
-
expected = { "data" => {
|
68
|
+
expected = { "data" => {
|
69
69
|
"cheese" => {
|
70
70
|
"dontSkipFlavor" => "Brie",
|
71
71
|
"includeFlavor" => "Brie",
|
@@ -74,7 +74,7 @@ describe GraphQL::Directive do
|
|
74
74
|
"dontSkipInlineId" => 1,
|
75
75
|
"includeInlineId" => 1,
|
76
76
|
},
|
77
|
-
}}
|
77
|
+
}}
|
78
78
|
assert_equal(expected, result)
|
79
79
|
end
|
80
80
|
end
|
@@ -11,7 +11,7 @@ describe GraphQL::Introspection::DirectiveType do
|
|
11
11
|
let(:result) { GraphQL::Query.new(DummySchema, query_string).result }
|
12
12
|
|
13
13
|
it 'shows directive info ' do
|
14
|
-
expected = { "data" => {
|
14
|
+
expected = { "data" => {
|
15
15
|
"__schema" => {
|
16
16
|
"directives" => [
|
17
17
|
{
|
@@ -34,7 +34,7 @@ describe GraphQL::Introspection::DirectiveType do
|
|
34
34
|
},
|
35
35
|
]
|
36
36
|
}
|
37
|
-
}}
|
37
|
+
}}
|
38
38
|
assert_equal(expected, result)
|
39
39
|
end
|
40
40
|
end
|
@@ -12,12 +12,13 @@ describe GraphQL::Introspection::SchemaType do
|
|
12
12
|
|}
|
13
13
|
let(:result) { GraphQL::Query.new(DummySchema, query_string).result }
|
14
14
|
it 'exposes the schema' do
|
15
|
-
expected = { "data" => {
|
15
|
+
expected = { "data" => {
|
16
16
|
"__schema" => {
|
17
17
|
"types" => DummySchema.types.values.map { |t| t.name.nil? ? (p t; raise("no name for #{t}")) : {"name" => t.name} },
|
18
18
|
"queryType"=>{
|
19
19
|
"fields"=>[
|
20
20
|
{"name"=>"cheese"},
|
21
|
+
{"name"=>"milk"},
|
21
22
|
{"name"=>"fromSource"},
|
22
23
|
{"name"=>"favoriteEdible"},
|
23
24
|
{"name"=>"searchDairy"},
|
@@ -34,7 +35,7 @@ describe GraphQL::Introspection::SchemaType do
|
|
34
35
|
]
|
35
36
|
},
|
36
37
|
}
|
37
|
-
}}
|
38
|
+
}}
|
38
39
|
assert_equal(expected, result)
|
39
40
|
end
|
40
41
|
end
|
@@ -25,7 +25,7 @@ describe GraphQL::Introspection::TypeType do
|
|
25
25
|
{"name"=>"SHEEP", "isDeprecated"=> false },
|
26
26
|
]}
|
27
27
|
it 'exposes metadata about types' do
|
28
|
-
expected = {"data"=> {
|
28
|
+
expected = {"data"=> {
|
29
29
|
"cheeseType" => {
|
30
30
|
"name"=> "Cheese",
|
31
31
|
"kind" => "OBJECT",
|
@@ -37,7 +37,7 @@ describe GraphQL::Introspection::TypeType do
|
|
37
37
|
{"name"=>"AnimalProduct"}
|
38
38
|
],
|
39
39
|
"fields"=>[
|
40
|
-
{"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"
|
40
|
+
{"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"ID"}}},
|
41
41
|
{"type"=>{"name"=>"DairyAnimal", "ofType"=>nil}},
|
42
42
|
{"type"=>{"name"=>"Non-Null", "ofType"=>{"name"=>"Float"}}},
|
43
43
|
{"type"=>{"name"=>"List", "ofType"=>{"name"=>"String"}}},
|
@@ -63,7 +63,7 @@ describe GraphQL::Introspection::TypeType do
|
|
63
63
|
{"name"=>"__typename"},
|
64
64
|
]
|
65
65
|
}
|
66
|
-
}}
|
66
|
+
}}
|
67
67
|
assert_equal(expected, query.result)
|
68
68
|
end
|
69
69
|
|
@@ -78,7 +78,7 @@ describe GraphQL::Introspection::TypeType do
|
|
78
78
|
it 'can expose deprecated fields' do
|
79
79
|
typename = cheese_fields.pop
|
80
80
|
new_cheese_fields = cheese_fields + [deprecated_fields, typename]
|
81
|
-
expected = { "data" => {
|
81
|
+
expected = { "data" => {
|
82
82
|
"cheeseType" => {
|
83
83
|
"name"=> "Cheese",
|
84
84
|
"kind" => "OBJECT",
|
@@ -89,7 +89,7 @@ describe GraphQL::Introspection::TypeType do
|
|
89
89
|
"kind"=>"ENUM",
|
90
90
|
"enumValues"=> dairy_animals + [{"name" => "YAK", "isDeprecated" => true}],
|
91
91
|
},
|
92
|
-
}}
|
92
|
+
}}
|
93
93
|
assert_equal(expected, query.result)
|
94
94
|
end
|
95
95
|
|
@@ -101,7 +101,7 @@ describe GraphQL::Introspection::TypeType do
|
|
101
101
|
|}
|
102
102
|
|
103
103
|
it 'exposes metadata about input objects' do
|
104
|
-
expected = { "data" => {
|
104
|
+
expected = { "data" => {
|
105
105
|
"__type" => {
|
106
106
|
"name"=>"DairyProductInput",
|
107
107
|
"description"=>"Properties for finding a dairy product",
|
@@ -111,7 +111,7 @@ describe GraphQL::Introspection::TypeType do
|
|
111
111
|
{"name"=>"fatContent", "type"=>{ "name" => "Float"}, "defaultValue"=>nil}
|
112
112
|
]
|
113
113
|
}
|
114
|
-
}}
|
114
|
+
}}
|
115
115
|
assert_equal(expected, query.result)
|
116
116
|
end
|
117
117
|
end
|
@@ -9,7 +9,11 @@ describe GraphQL::Parser do
|
|
9
9
|
# a read-only:
|
10
10
|
query getStuff {id, name @skip(if: true)}
|
11
11
|
# a mutation:
|
12
|
-
mutation changeStuff(
|
12
|
+
mutation changeStuff(
|
13
|
+
$override: Boolean = true,
|
14
|
+
$cucumbers: [Vegetable]!,
|
15
|
+
$input: SomeInputType = {key: "value"},
|
16
|
+
) @veggie, @healthy(vitamins: true) {
|
13
17
|
# change the cucumber
|
14
18
|
changeStuff(thing: $cucumbers) {
|
15
19
|
id,
|
@@ -72,7 +76,7 @@ describe GraphQL::Parser do
|
|
72
76
|
assert(parser.operation_variable_definition.parse_with_debug("$myVar: [Int]"), "it gets list variables")
|
73
77
|
assert(parser.operation_variable_definition.parse_with_debug("$myVar: Elephant!"), "it gets non-null variables")
|
74
78
|
assert(parser.operation_variable_definition.parse_with_debug("$myVar: [Food]!"), "it gets non-null list variables")
|
75
|
-
assert(parser.operation_variable_definitions.parse_with_debug(%|($myVar: Elephant!, $myList: [Float], $myString: String="Cheese")|), "it gets a list of defns")
|
79
|
+
assert(parser.operation_variable_definitions.parse_with_debug(%|($myVar: Elephant!, $myList: [Float], $myString: String = "Cheese")|), "it gets a list of defns")
|
76
80
|
end
|
77
81
|
|
78
82
|
describe 'value' do
|
data/spec/graph_ql/query_spec.rb
CHANGED
@@ -4,17 +4,17 @@ describe GraphQL::Query do
|
|
4
4
|
describe '#execute' do
|
5
5
|
let(:query_string) { %|
|
6
6
|
query getFlavor($cheeseId: Int!) {
|
7
|
-
brie: cheese(id: 1) { ...cheeseFields,
|
7
|
+
brie: cheese(id: 1) { ...cheeseFields, taste: flavor },
|
8
8
|
cheese(id: $cheeseId) {
|
9
9
|
__typename,
|
10
10
|
id,
|
11
11
|
...cheeseFields,
|
12
12
|
... edibleFields,
|
13
13
|
... on Cheese { cheeseKind: flavor },
|
14
|
-
... on Milk { source }
|
15
14
|
}
|
16
15
|
fromSource(source: COW) { id }
|
17
|
-
|
16
|
+
fromSheep: fromSource(source: SHEEP) { id }
|
17
|
+
firstSheep: searchDairy(product: {source: SHEEP}) { ... dairyFields, ... milkFields }
|
18
18
|
favoriteEdible { __typename, fatContent }
|
19
19
|
}
|
20
20
|
fragment cheeseFields on Cheese { flavor }
|
@@ -26,11 +26,11 @@ describe GraphQL::Query do
|
|
26
26
|
}
|
27
27
|
|}
|
28
28
|
let(:debug) { false }
|
29
|
-
let(:query) { GraphQL::Query.new(DummySchema, query_string,
|
29
|
+
let(:query) { GraphQL::Query.new(DummySchema, query_string, params: {"cheeseId" => 2}, debug: debug)}
|
30
30
|
let(:result) { query.result }
|
31
31
|
|
32
32
|
it 'returns fields on objects' do
|
33
|
-
expected = {"data"=> {
|
33
|
+
expected = {"data"=> {
|
34
34
|
"brie" => { "flavor" => "Brie", "taste" => "Brie" },
|
35
35
|
"cheese" => {
|
36
36
|
"__typename" => "Cheese",
|
@@ -40,9 +40,10 @@ describe GraphQL::Query do
|
|
40
40
|
"cheeseKind" => "Gouda",
|
41
41
|
},
|
42
42
|
"fromSource" => [{ "id" => 1 }, {"id" => 2}],
|
43
|
+
"fromSheep"=>[{"id"=>3}],
|
43
44
|
"firstSheep" => { "flavor" => "Manchego" },
|
44
45
|
"favoriteEdible"=>{"__typename"=>"Milk", "fatContent"=>0.04},
|
45
|
-
}}
|
46
|
+
}}
|
46
47
|
assert_equal(expected, result)
|
47
48
|
end
|
48
49
|
|
@@ -81,14 +82,31 @@ describe GraphQL::Query do
|
|
81
82
|
|}
|
82
83
|
it 'executes mutations in order' do
|
83
84
|
expected = {"data"=>{
|
84
|
-
"setInOrder"=>{
|
85
85
|
"first"=> [1],
|
86
86
|
"second"=>[1, 5],
|
87
87
|
"third"=> [1, 5, 2],
|
88
|
-
}
|
89
88
|
}}
|
90
89
|
assert_equal(expected, result)
|
91
90
|
end
|
92
91
|
end
|
93
92
|
end
|
93
|
+
|
94
|
+
describe 'context' do
|
95
|
+
let(:context_field) { GraphQL::Field.new do |f, types, field, args|
|
96
|
+
f.type(GraphQL::STRING_TYPE)
|
97
|
+
f.arguments(key: args.build(type: types.String))
|
98
|
+
f.resolve -> (target, args, ctx) { ctx[args["key"]] }
|
99
|
+
end}
|
100
|
+
let(:query_type) { GraphQL::ObjectType.new {|t| t.fields({context: context_field})}}
|
101
|
+
let(:schema) { GraphQL::Schema.new(query: query_type, mutation: nil)}
|
102
|
+
let(:query) { GraphQL::Query.new(schema, query_string, context: {"some_key" => "some value"})}
|
103
|
+
let(:query_string) { %|
|
104
|
+
query getCtx { context(key: "some_key") }
|
105
|
+
|}
|
106
|
+
|
107
|
+
it 'passes context to fields' do
|
108
|
+
expected = {"data" => {"context" => "some value"}}
|
109
|
+
assert_equal(expected, query.result)
|
110
|
+
end
|
111
|
+
end
|
94
112
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::ID_TYPE do
|
4
|
+
let(:query) { GraphQL::Query.new(DummySchema, query_string)}
|
5
|
+
let(:result) { query.result }
|
6
|
+
|
7
|
+
describe 'coercion for int inputs' do
|
8
|
+
let(:query_string) { %|query getMilk { cow: milk(id: 1) { id } }| }
|
9
|
+
|
10
|
+
it 'coerces IDs from ints and serializes as strings' do
|
11
|
+
expected = {"data" => {"cow" => {"id" => "1"}}}
|
12
|
+
assert_equal(expected, result)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'coercion for string inputs' do
|
17
|
+
let(:query_string) { %|query getMilk { cow: milk(id: "1") { id } }| }
|
18
|
+
|
19
|
+
it 'coerces IDs from strings and serializes as strings' do
|
20
|
+
expected = {"data" => {"cow" => {"id" => "1"}}}
|
21
|
+
assert_equal(expected, result)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -11,6 +11,7 @@ describe GraphQL::Schema::TypeReducer do
|
|
11
11
|
"Float" => GraphQL::FLOAT_TYPE,
|
12
12
|
"Edible" => EdibleInterface,
|
13
13
|
"Milk" => MilkType,
|
14
|
+
"ID" => GraphQL::ID_TYPE,
|
14
15
|
"AnimalProduct" => AnimalProductInterface,
|
15
16
|
}
|
16
17
|
assert_equal(expected.keys, reducer.result.keys)
|
@@ -45,7 +45,7 @@ describe GraphQL::Schema::TypeValidator do
|
|
45
45
|
let(:errors) { e = []; GraphQL::Schema::TypeValidator.new.validate(object, e); e;}
|
46
46
|
it 'must be 2+ types, must be only object types' do
|
47
47
|
expected = [
|
48
|
-
"Something.possible_types must be objects, but some aren't:
|
48
|
+
"Something.possible_types must be objects, but some aren't: DairyProductInput",
|
49
49
|
"Union Something must be defined with 2 or more types, not 1",
|
50
50
|
]
|
51
51
|
assert_equal(expected, errors)
|
@@ -14,7 +14,7 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
14
14
|
}
|
15
15
|
|)}
|
16
16
|
|
17
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
17
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::ArgumentLiteralsAreCompatible]) }
|
18
18
|
let(:errors) { validator.validate(document) }
|
19
19
|
|
20
20
|
it 'finds undefined arguments to fields and directives' do
|