graphql 0.12.1 → 0.13.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 +31 -41
- data/lib/graphql/argument.rb +23 -21
- data/lib/graphql/base_type.rb +5 -8
- data/lib/graphql/define/assign_argument.rb +5 -2
- data/lib/graphql/define/type_definer.rb +2 -1
- data/lib/graphql/directive.rb +34 -36
- data/lib/graphql/directive/include_directive.rb +3 -7
- data/lib/graphql/directive/skip_directive.rb +3 -7
- data/lib/graphql/enum_type.rb +78 -76
- data/lib/graphql/execution_error.rb +1 -3
- data/lib/graphql/field.rb +99 -95
- data/lib/graphql/input_object_type.rb +49 -47
- data/lib/graphql/interface_type.rb +31 -34
- data/lib/graphql/introspection.rb +19 -18
- data/lib/graphql/introspection/directive_location_enum.rb +8 -0
- data/lib/graphql/introspection/directive_type.rb +1 -3
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/fields_field.rb +1 -1
- data/lib/graphql/introspection/introspection_query.rb +1 -3
- data/lib/graphql/introspection/possible_types_field.rb +7 -1
- data/lib/graphql/introspection/schema_field.rb +13 -9
- data/lib/graphql/introspection/type_by_name_field.rb +13 -17
- data/lib/graphql/introspection/typename_field.rb +12 -8
- data/lib/graphql/language.rb +5 -9
- data/lib/graphql/language/lexer.rb +668 -0
- data/lib/graphql/language/lexer.rl +149 -0
- data/lib/graphql/language/parser.rb +842 -116
- data/lib/graphql/language/parser.y +264 -0
- data/lib/graphql/language/token.rb +21 -0
- data/lib/graphql/list_type.rb +33 -31
- data/lib/graphql/non_null_type.rb +33 -31
- data/lib/graphql/object_type.rb +52 -55
- data/lib/graphql/query.rb +83 -80
- data/lib/graphql/query/context.rb +5 -1
- data/lib/graphql/query/directive_resolution.rb +16 -0
- data/lib/graphql/query/executor.rb +3 -3
- data/lib/graphql/query/input_validation_result.rb +17 -15
- data/lib/graphql/query/serial_execution.rb +5 -5
- data/lib/graphql/query/serial_execution/execution_context.rb +4 -3
- data/lib/graphql/query/serial_execution/selection_resolution.rb +19 -21
- data/lib/graphql/query/serial_execution/value_resolution.rb +1 -1
- data/lib/graphql/query/type_resolver.rb +22 -18
- data/lib/graphql/query/variable_validation_error.rb +14 -12
- data/lib/graphql/schema.rb +87 -77
- data/lib/graphql/schema/each_item_validator.rb +16 -12
- data/lib/graphql/schema/field_validator.rb +14 -10
- data/lib/graphql/schema/implementation_validator.rb +26 -22
- data/lib/graphql/schema/middleware_chain.rb +2 -1
- data/lib/graphql/schema/possible_types.rb +34 -0
- data/lib/graphql/schema/printer.rb +122 -120
- data/lib/graphql/schema/type_expression.rb +1 -0
- data/lib/graphql/schema/type_map.rb +3 -10
- data/lib/graphql/schema/type_reducer.rb +65 -81
- data/lib/graphql/schema/type_validator.rb +45 -41
- data/lib/graphql/static_validation.rb +7 -9
- data/lib/graphql/static_validation/all_rules.rb +29 -24
- data/lib/graphql/static_validation/arguments_validator.rb +39 -35
- data/lib/graphql/static_validation/literal_validator.rb +44 -40
- data/lib/graphql/static_validation/message.rb +30 -26
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +15 -11
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +14 -10
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +16 -12
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +59 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +25 -21
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +28 -24
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +84 -80
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +49 -43
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +22 -17
- data/lib/graphql/static_validation/rules/fragments_are_finite.rb +19 -15
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +25 -20
- data/lib/graphql/static_validation/rules/fragments_are_used.rb +36 -23
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +29 -25
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +21 -17
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +79 -70
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +24 -20
- data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +122 -119
- data/lib/graphql/static_validation/type_stack.rb +138 -129
- data/lib/graphql/static_validation/validator.rb +29 -25
- data/lib/graphql/type_kinds.rb +42 -40
- data/lib/graphql/union_type.rb +22 -16
- data/lib/graphql/version.rb +1 -1
- data/readme.md +12 -27
- data/spec/graphql/base_type_spec.rb +3 -3
- data/spec/graphql/directive_spec.rb +10 -18
- data/spec/graphql/enum_type_spec.rb +7 -7
- data/spec/graphql/execution_error_spec.rb +1 -1
- data/spec/graphql/field_spec.rb +14 -13
- data/spec/graphql/id_type_spec.rb +6 -6
- data/spec/graphql/input_object_type_spec.rb +39 -39
- data/spec/graphql/interface_type_spec.rb +16 -32
- data/spec/graphql/introspection/directive_type_spec.rb +5 -9
- data/spec/graphql/introspection/input_value_type_spec.rb +10 -4
- data/spec/graphql/introspection/introspection_query_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +2 -2
- data/spec/graphql/introspection/type_type_spec.rb +34 -6
- data/spec/graphql/language/parser_spec.rb +299 -105
- data/spec/graphql/language/visitor_spec.rb +4 -4
- data/spec/graphql/list_type_spec.rb +11 -11
- data/spec/graphql/object_type_spec.rb +10 -10
- data/spec/graphql/query/arguments_spec.rb +7 -7
- data/spec/graphql/query/context_spec.rb +11 -3
- data/spec/graphql/query/executor_spec.rb +26 -19
- data/spec/graphql/query/serial_execution/execution_context_spec.rb +6 -6
- data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -2
- data/spec/graphql/query/type_resolver_spec.rb +3 -3
- data/spec/graphql/query_spec.rb +6 -38
- data/spec/graphql/scalar_type_spec.rb +28 -19
- data/spec/graphql/schema/field_validator_spec.rb +1 -1
- data/spec/graphql/schema/middleware_chain_spec.rb +12 -1
- data/spec/graphql/schema/printer_spec.rb +12 -4
- data/spec/graphql/schema/rescue_middleware_spec.rb +1 -1
- data/spec/graphql/schema/type_expression_spec.rb +2 -2
- data/spec/graphql/schema/type_reducer_spec.rb +21 -36
- data/spec/graphql/schema/type_validator_spec.rb +9 -9
- data/spec/graphql/schema_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +4 -4
- data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +4 -4
- data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +5 -5
- data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +39 -0
- data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +5 -5
- data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +4 -4
- data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +1 -1
- data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +2 -2
- data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +3 -3
- data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +3 -3
- data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +5 -5
- data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +3 -1
- data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +4 -4
- data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +3 -3
- data/spec/graphql/static_validation/type_stack_spec.rb +3 -2
- data/spec/graphql/static_validation/validator_spec.rb +26 -6
- data/spec/graphql/union_type_spec.rb +5 -4
- data/spec/spec_helper.rb +2 -5
- data/spec/support/dairy_app.rb +30 -9
- data/spec/support/dairy_data.rb +1 -1
- data/spec/support/star_wars_data.rb +26 -26
- data/spec/support/star_wars_schema.rb +1 -1
- metadata +40 -21
- data/lib/graphql/language/transform.rb +0 -113
- data/lib/graphql/query/directive_chain.rb +0 -44
- data/lib/graphql/repl.rb +0 -27
- data/spec/graphql/language/transform_spec.rb +0 -156
@@ -1,31 +1,31 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::ListType do
|
4
4
|
let(:float_list) { GraphQL::ListType.new(of_type: GraphQL::FLOAT_TYPE) }
|
5
5
|
|
6
|
-
it
|
6
|
+
it "coerces elements in the list" do
|
7
7
|
assert_equal([1.0, 2.0, 3.0].inspect, float_list.coerce_input([1, 2, 3]).inspect)
|
8
8
|
end
|
9
9
|
|
10
|
-
describe
|
11
|
-
let(:bad_num) {
|
10
|
+
describe "validate_input with bad input" do
|
11
|
+
let(:bad_num) { "bad_num" }
|
12
12
|
let(:result) { float_list.validate_input([bad_num, 2.0, 3.0]) }
|
13
13
|
|
14
|
-
it
|
14
|
+
it "returns an invalid result" do
|
15
15
|
assert(!result.valid?)
|
16
16
|
end
|
17
17
|
|
18
|
-
it
|
18
|
+
it "has one problem" do
|
19
19
|
assert_equal(result.problems.length, 1)
|
20
20
|
end
|
21
21
|
|
22
|
-
it
|
23
|
-
assert_equal(result.problems[0][
|
22
|
+
it "has path [0]" do
|
23
|
+
assert_equal(result.problems[0]["path"], [0])
|
24
24
|
end
|
25
25
|
|
26
|
-
it
|
27
|
-
expected = GraphQL::FLOAT_TYPE.validate_input(bad_num).problems[0][
|
28
|
-
actual = result.problems[0][
|
26
|
+
it "has the correct explanation" do
|
27
|
+
expected = GraphQL::FLOAT_TYPE.validate_input(bad_num).problems[0]["explanation"]
|
28
|
+
actual = result.problems[0]["explanation"]
|
29
29
|
assert_equal(actual, expected)
|
30
30
|
end
|
31
31
|
end
|
@@ -1,40 +1,40 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::ObjectType do
|
4
4
|
let(:type) { CheeseType }
|
5
5
|
|
6
|
-
it
|
6
|
+
it "has a name" do
|
7
7
|
assert_equal("Cheese", type.name)
|
8
8
|
type.name = "Fromage"
|
9
9
|
assert_equal("Fromage", type.name)
|
10
10
|
type.name = "Cheese"
|
11
11
|
end
|
12
12
|
|
13
|
-
it
|
13
|
+
it "has a description" do
|
14
14
|
assert_equal(22, type.description.length)
|
15
15
|
end
|
16
16
|
|
17
|
-
it
|
17
|
+
it "may have interfaces" do
|
18
18
|
assert_equal([EdibleInterface, AnimalProductInterface], type.interfaces)
|
19
19
|
end
|
20
20
|
|
21
21
|
describe '#get_field ' do
|
22
|
-
it
|
22
|
+
it "exposes fields" do
|
23
23
|
field = type.get_field("id")
|
24
24
|
assert_equal(GraphQL::TypeKinds::NON_NULL, field.type.kind)
|
25
25
|
assert_equal(GraphQL::TypeKinds::SCALAR, field.type.of_type.kind)
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
29
|
-
field_without_prop = CheeseType.get_field(
|
30
|
-
field_with_prop = CheeseType.get_field(
|
28
|
+
it "exposes defined field property" do
|
29
|
+
field_without_prop = CheeseType.get_field("flavor")
|
30
|
+
field_with_prop = CheeseType.get_field("fatContent")
|
31
31
|
assert_equal(field_without_prop.property, nil)
|
32
32
|
assert_equal(field_with_prop.property, :fat_content)
|
33
33
|
end
|
34
34
|
|
35
35
|
it "looks up from interfaces" do
|
36
|
-
field_from_self = CheeseType.get_field(
|
37
|
-
field_from_iface = MilkType.get_field(
|
36
|
+
field_from_self = CheeseType.get_field("fatContent")
|
37
|
+
field_from_iface = MilkType.get_field("fatContent")
|
38
38
|
assert_equal(field_from_self.property, :fat_content)
|
39
39
|
assert_equal(field_from_iface.property, nil)
|
40
40
|
end
|
@@ -3,23 +3,23 @@ require "spec_helper"
|
|
3
3
|
describe GraphQL::Query::Arguments do
|
4
4
|
let(:arguments) { GraphQL::Query::Arguments.new({ a: 1, b: 2, c: GraphQL::Query::Arguments.new({ d: 3, e: 4}) }) }
|
5
5
|
|
6
|
-
it
|
7
|
-
assert_equal([
|
6
|
+
it "returns keys as strings" do
|
7
|
+
assert_equal(["a", "b", "c"], arguments.keys)
|
8
8
|
end
|
9
9
|
|
10
|
-
it
|
11
|
-
assert_equal([1, 2, {
|
10
|
+
it "delegates values to values hash" do
|
11
|
+
assert_equal([1, 2, {"d" => 3, "e" => 4}], arguments.values)
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
14
|
+
it "delegates each to values hash" do
|
15
15
|
pairs = []
|
16
16
|
arguments.each do |key, value|
|
17
17
|
pairs << [key, value]
|
18
18
|
end
|
19
|
-
assert_equal([[
|
19
|
+
assert_equal([["a", 1], ["b", 2], ["c", {"d" => 3, "e" => 4}]], pairs)
|
20
20
|
end
|
21
21
|
|
22
|
-
it
|
22
|
+
it "returns original Ruby hash values with to_h" do
|
23
23
|
assert_equal({ a: 1, b: 2, c: { d: 3, e: 4 } }, arguments.to_h)
|
24
24
|
end
|
25
25
|
end
|
@@ -22,7 +22,7 @@ describe GraphQL::Query::Context do
|
|
22
22
|
query getCtx { context(key: "some_key") }
|
23
23
|
|}
|
24
24
|
|
25
|
-
it
|
25
|
+
it "passes context to fields" do
|
26
26
|
expected = {"data" => {"context" => "some value"}}
|
27
27
|
assert_equal(expected, result)
|
28
28
|
end
|
@@ -33,7 +33,7 @@ describe GraphQL::Query::Context do
|
|
33
33
|
query getCtx { contextAstNodeName }
|
34
34
|
|}
|
35
35
|
|
36
|
-
it
|
36
|
+
it "provides access to the AST node" do
|
37
37
|
expected = {"data" => {"contextAstNodeName" => "GraphQL::Language::Nodes::Field"}}
|
38
38
|
assert_equal(expected, result)
|
39
39
|
end
|
@@ -44,9 +44,17 @@ describe GraphQL::Query::Context do
|
|
44
44
|
query getCtx { queryName }
|
45
45
|
|}
|
46
46
|
|
47
|
-
it
|
47
|
+
it "provides access to the AST node" do
|
48
48
|
expected = {"data" => {"queryName" => "GraphQL::Query"}}
|
49
49
|
assert_equal(expected, result)
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
describe "empty values" do
|
54
|
+
let(:context) { GraphQL::Query::Context.new(query: OpenStruct.new(schema: schema), values: nil) }
|
55
|
+
|
56
|
+
it "returns nil for any key" do
|
57
|
+
assert_equal(nil, context[:some_key])
|
58
|
+
end
|
59
|
+
end
|
52
60
|
end
|
@@ -1,16 +1,18 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::Query::Executor do
|
4
4
|
let(:debug) { true }
|
5
5
|
let(:operation_name) { nil }
|
6
6
|
let(:schema) { DummySchema }
|
7
7
|
let(:variables) { {"cheeseId" => 2} }
|
8
|
-
let(:
|
8
|
+
let(:query) { GraphQL::Query.new(
|
9
|
+
schema,
|
9
10
|
query_string,
|
10
11
|
variables: variables,
|
11
12
|
debug: debug,
|
12
13
|
operation_name: operation_name,
|
13
14
|
)}
|
15
|
+
let(:result) { query.result }
|
14
16
|
|
15
17
|
describe "multiple operations" do
|
16
18
|
let(:query_string) { %|
|
@@ -46,7 +48,7 @@ describe GraphQL::Query::Executor do
|
|
46
48
|
end
|
47
49
|
|
48
50
|
|
49
|
-
describe
|
51
|
+
describe "execution order" do
|
50
52
|
let(:query_string) {%|
|
51
53
|
mutation setInOrder {
|
52
54
|
first: pushValue(value: 1)
|
@@ -56,7 +58,7 @@ describe GraphQL::Query::Executor do
|
|
56
58
|
}
|
57
59
|
|}
|
58
60
|
|
59
|
-
it
|
61
|
+
it "executes mutations in order" do
|
60
62
|
expected = {"data"=>{
|
61
63
|
"first"=> [1],
|
62
64
|
"second"=>[1, 5],
|
@@ -68,7 +70,7 @@ describe GraphQL::Query::Executor do
|
|
68
70
|
end
|
69
71
|
|
70
72
|
|
71
|
-
describe
|
73
|
+
describe "fragment resolution" do
|
72
74
|
let(:schema) {
|
73
75
|
# we will raise if the dairy field is resolved more than one time
|
74
76
|
resolved = false
|
@@ -103,7 +105,7 @@ describe GraphQL::Query::Executor do
|
|
103
105
|
}
|
104
106
|
|}
|
105
107
|
|
106
|
-
it
|
108
|
+
it "resolves each field only one time, even when present in multiple fragments" do
|
107
109
|
expected = {"data" => {
|
108
110
|
"dairy" => { "id" => "1" }
|
109
111
|
}}
|
@@ -113,28 +115,33 @@ describe GraphQL::Query::Executor do
|
|
113
115
|
end
|
114
116
|
|
115
117
|
|
116
|
-
describe
|
118
|
+
describe "runtime errors" do
|
117
119
|
let(:query_string) {%| query noMilk { error }|}
|
118
|
-
|
120
|
+
|
121
|
+
describe "if debug: false" do
|
119
122
|
let(:debug) { false }
|
120
|
-
|
123
|
+
let(:errors) { query.context.errors }
|
124
|
+
|
125
|
+
it "turns into error messages" do
|
121
126
|
expected = {"errors"=>[
|
122
|
-
{"message"=>"
|
127
|
+
{"message"=>"Internal error"}
|
123
128
|
]}
|
124
129
|
assert_equal(expected, result)
|
130
|
+
assert_equal([RuntimeError], errors.map(&:class))
|
131
|
+
assert_equal("This error was raised on purpose", errors.first.message)
|
125
132
|
end
|
126
133
|
end
|
127
134
|
|
128
|
-
describe
|
135
|
+
describe "if debug: true" do
|
129
136
|
let(:debug) { true }
|
130
|
-
it
|
137
|
+
it "raises error" do
|
131
138
|
assert_raises(RuntimeError) { result }
|
132
139
|
end
|
133
140
|
end
|
134
141
|
|
135
|
-
describe
|
142
|
+
describe "if nil is given for a non-null field" do
|
136
143
|
let(:query_string) {%| query noMilk { cow { name cantBeNullButIs } }|}
|
137
|
-
it
|
144
|
+
it "turns into error message and nulls the entire selection" do
|
138
145
|
expected = {
|
139
146
|
"data" => { "cow" => nil },
|
140
147
|
"errors" => [
|
@@ -147,9 +154,9 @@ describe GraphQL::Query::Executor do
|
|
147
154
|
end
|
148
155
|
end
|
149
156
|
|
150
|
-
describe
|
157
|
+
describe "if an execution error is raised for a non-null field" do
|
151
158
|
let(:query_string) {%| query noMilk { cow { name cantBeNullButRaisesExecutionError } }|}
|
152
|
-
it
|
159
|
+
it "uses provided error message and nulls the entire selection" do
|
153
160
|
expected = {
|
154
161
|
"data" => { "cow" => nil },
|
155
162
|
"errors" => [
|
@@ -229,7 +236,7 @@ describe GraphQL::Query::Executor do
|
|
229
236
|
"errors"=>[
|
230
237
|
{
|
231
238
|
"message" => "Variable input of type ReplaceValuesInput! was provided invalid value",
|
232
|
-
"locations" => [{ "line" => 1, "column" =>
|
239
|
+
"locations" => [{ "line" => 1, "column" => 13 }],
|
233
240
|
"value" => nil,
|
234
241
|
"problems" => [
|
235
242
|
{ "path" => [], "explanation" => "Expected value to not be null" }
|
@@ -249,7 +256,7 @@ describe GraphQL::Query::Executor do
|
|
249
256
|
"errors"=>[
|
250
257
|
{
|
251
258
|
"message" => "Variable input of type ReplaceValuesInput! was provided invalid value",
|
252
|
-
"locations" => [{ "line" => 1, "column" =>
|
259
|
+
"locations" => [{ "line" => 1, "column" => 13 }],
|
253
260
|
"value" => {},
|
254
261
|
"problems" => [
|
255
262
|
{ "path" => ["values"], "explanation" => "Expected value to not be null" }
|
@@ -269,7 +276,7 @@ describe GraphQL::Query::Executor do
|
|
269
276
|
"errors"=>[
|
270
277
|
{
|
271
278
|
"message" => "Variable input of type [DairyProductInput] was provided invalid value",
|
272
|
-
"locations" => [{ "line" => 1, "column" =>
|
279
|
+
"locations" => [{ "line" => 1, "column" => 10 }],
|
273
280
|
"value" => [{ "foo" => "bar" }],
|
274
281
|
"problems" => [
|
275
282
|
{ "path" => [0, "foo"], "explanation" => "Field is not defined on DairyProductInput" },
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::Query::SerialExecution::ExecutionContext do
|
4
4
|
let(:query_string) { %|
|
@@ -34,22 +34,22 @@ describe GraphQL::Query::SerialExecution::ExecutionContext do
|
|
34
34
|
|
35
35
|
describe "get_type" do
|
36
36
|
it "returns the respective type from the schema" do
|
37
|
-
type = execution_context.get_type(
|
37
|
+
type = execution_context.get_type("Dairy")
|
38
38
|
assert_equal(DairyType, type)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
describe "get_field" do
|
43
43
|
it "returns the respective field from the schema" do
|
44
|
-
field = execution_context.get_field(DairyType,
|
45
|
-
assert_equal(
|
44
|
+
field = execution_context.get_field(DairyType, "cheese")
|
45
|
+
assert_equal("cheese", field.name)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
describe "get_fragment" do
|
50
50
|
it "returns a fragment on the query by name" do
|
51
|
-
fragment = execution_context.get_fragment(
|
52
|
-
assert_equal(
|
51
|
+
fragment = execution_context.get_fragment("cheeseFields")
|
52
|
+
assert_equal("cheeseFields", fragment.name)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::Query::SerialExecution::ValueResolution do
|
4
4
|
let(:debug) { false }
|
@@ -17,7 +17,7 @@ describe GraphQL::Query::SerialExecution::ValueResolution do
|
|
17
17
|
name "Query"
|
18
18
|
field :tomorrow, day_of_week_enum do
|
19
19
|
argument :today, day_of_week_enum
|
20
|
-
resolve ->(obj, args, ctx) { (args[
|
20
|
+
resolve ->(obj, args, ctx) { (args["today"] + 1) % 7 }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
}
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::Query::TypeResolver do
|
4
|
-
it
|
5
|
-
type = GraphQL::Query::TypeResolver.new(MILKS[1], DairyProductUnion, MilkType).type
|
4
|
+
it "resolves correcty when child_type is UnionType" do
|
5
|
+
type = GraphQL::Query::TypeResolver.new(MILKS[1], DairyProductUnion, MilkType, nil).type
|
6
6
|
assert_equal(MilkType, type)
|
7
7
|
end
|
8
8
|
end
|
data/spec/graphql/query_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::Query do
|
4
4
|
let(:query_string) { %|
|
@@ -43,7 +43,7 @@ describe GraphQL::Query do
|
|
43
43
|
)}
|
44
44
|
let(:result) { query.result }
|
45
45
|
describe '#result' do
|
46
|
-
it
|
46
|
+
it "returns fields on objects" do
|
47
47
|
expected = {"data"=> {
|
48
48
|
"brie" => { "flavor" => "Brie", "taste" => "Brie" },
|
49
49
|
"cheese" => {
|
@@ -82,24 +82,8 @@ describe GraphQL::Query do
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
it
|
86
|
-
assert_equal(GraphQL::Language::Nodes::FragmentDefinition, query.fragments[
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'correctly identifies parse error location' do
|
90
|
-
# "Correct" is a bit of an overstatement. All Parslet errors get surfaced
|
91
|
-
# at the beginning of the query they were in, since Parslet sees the query
|
92
|
-
# as invalid. It would be great to have more granularity here.
|
93
|
-
e = assert_raises(GraphQL::ParseError) do
|
94
|
-
GraphQL.parse("
|
95
|
-
query getCoupons {
|
96
|
-
allCoupons: {data{id}}
|
97
|
-
}
|
98
|
-
")
|
99
|
-
end
|
100
|
-
assert_equal('Extra input after last repetition at line 2 char 9.', e.message)
|
101
|
-
assert_equal(2, e.line)
|
102
|
-
assert_equal(9, e.col)
|
85
|
+
it "exposes fragments" do
|
86
|
+
assert_equal(GraphQL::Language::Nodes::FragmentDefinition, query.fragments["cheeseFields"].class)
|
103
87
|
end
|
104
88
|
|
105
89
|
describe "merging fragments with different keys" do
|
@@ -167,22 +151,6 @@ describe GraphQL::Query do
|
|
167
151
|
end
|
168
152
|
end
|
169
153
|
|
170
|
-
describe "malformed queries" do
|
171
|
-
describe "whitespace-only" do
|
172
|
-
let(:query_string) { " " }
|
173
|
-
it "doesn't blow up" do
|
174
|
-
assert_equal({}, result)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
describe "empty string" do
|
179
|
-
let(:query_string) { "" }
|
180
|
-
it "doesn't blow up" do
|
181
|
-
assert_equal({}, result)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
154
|
describe "field argument default values" do
|
187
155
|
let(:query_string) {%|
|
188
156
|
query getCheeses(
|
@@ -250,7 +218,7 @@ describe GraphQL::Query do
|
|
250
218
|
"errors" => [
|
251
219
|
{
|
252
220
|
"message" => "Variable cheeseId of type Int! was provided invalid value",
|
253
|
-
"locations"=>[{ "line" => 2, "column" =>
|
221
|
+
"locations"=>[{ "line" => 2, "column" => 23 }],
|
254
222
|
"value" => "2",
|
255
223
|
"problems" => [{ "path" => [], "explanation" => 'Could not coerce value "2" to Int' }]
|
256
224
|
}
|
@@ -268,7 +236,7 @@ describe GraphQL::Query do
|
|
268
236
|
"errors" => [
|
269
237
|
{
|
270
238
|
"message" => "Variable cheeseId of type Int! was provided invalid value",
|
271
|
-
"locations" => [{"line" => 2, "column" =>
|
239
|
+
"locations" => [{"line" => 2, "column" => 23}],
|
272
240
|
"value" => nil,
|
273
241
|
"problems" => [{ "path" => [], "explanation" => "Expected value to not be null" }]
|
274
242
|
}
|
@@ -1,52 +1,61 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe GraphQL::ScalarType do
|
4
|
-
let(:
|
4
|
+
let(:custom_scalar) {
|
5
5
|
GraphQL::ScalarType.define do
|
6
6
|
name "BigInt"
|
7
|
-
coerce_input ->(value) { Integer(value) }
|
7
|
+
coerce_input ->(value) { value =~ /\d+/ ? Integer(value) : nil }
|
8
8
|
coerce_result ->(value) { value.to_s }
|
9
9
|
end
|
10
10
|
}
|
11
11
|
let(:bignum) { 2 ** 128 }
|
12
12
|
|
13
|
-
it
|
14
|
-
assert_equal(nil,
|
13
|
+
it "coerces nil into nil" do
|
14
|
+
assert_equal(nil, custom_scalar.coerce_input(nil))
|
15
15
|
end
|
16
16
|
|
17
|
-
it
|
18
|
-
assert_equal(bignum,
|
17
|
+
it "coerces input into objects" do
|
18
|
+
assert_equal(bignum, custom_scalar.coerce_input(bignum.to_s))
|
19
19
|
end
|
20
20
|
|
21
|
-
it
|
22
|
-
assert_equal(bignum.to_s,
|
21
|
+
it "coerces result value for serialization" do
|
22
|
+
assert_equal(bignum.to_s, custom_scalar.coerce_result(bignum))
|
23
23
|
end
|
24
24
|
|
25
|
-
describe
|
25
|
+
describe "custom scalar errors" do
|
26
|
+
let(:result) { custom_scalar.validate_input("xyz") }
|
27
|
+
|
28
|
+
it "returns an invalid result" do
|
29
|
+
assert !result.valid?
|
30
|
+
assert_equal 'Could not coerce value "xyz" to BigInt', result.problems[0]["explanation"]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "validate_input with good input" do
|
26
35
|
let(:result) { GraphQL::INT_TYPE.validate_input(150) }
|
27
36
|
|
28
|
-
it
|
37
|
+
it "returns a valid result" do
|
29
38
|
assert(result.valid?)
|
30
39
|
end
|
31
40
|
end
|
32
41
|
|
33
|
-
describe
|
34
|
-
let(:result) { GraphQL::INT_TYPE.validate_input(
|
42
|
+
describe "validate_input with bad input" do
|
43
|
+
let(:result) { GraphQL::INT_TYPE.validate_input("bad num") }
|
35
44
|
|
36
|
-
it
|
45
|
+
it "returns an invalid result for bad input" do
|
37
46
|
assert(!result.valid?)
|
38
47
|
end
|
39
48
|
|
40
|
-
it
|
49
|
+
it "has one problem" do
|
41
50
|
assert_equal(result.problems.length, 1)
|
42
51
|
end
|
43
52
|
|
44
|
-
it
|
45
|
-
assert(result.problems[0][
|
53
|
+
it "has the correct explanation" do
|
54
|
+
assert(result.problems[0]["explanation"].include?("Could not coerce value"))
|
46
55
|
end
|
47
56
|
|
48
|
-
it
|
49
|
-
assert(result.problems[0][
|
57
|
+
it "has an empty path" do
|
58
|
+
assert(result.problems[0]["path"].empty?)
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|