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
@@ -13,7 +13,7 @@ describe GraphQL::StaticValidation::ArgumentsAreDefined do
|
|
13
13
|
}
|
14
14
|
")}
|
15
15
|
|
16
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
16
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::ArgumentsAreDefined]) }
|
17
17
|
let(:errors) { validator.validate(document) }
|
18
18
|
|
19
19
|
it 'finds undefined arguments to fields and directives' do
|
@@ -13,7 +13,7 @@ describe GraphQL::StaticValidation::DirectivesAreDefined do
|
|
13
13
|
}
|
14
14
|
")}
|
15
15
|
|
16
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
16
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::DirectivesAreDefined]) }
|
17
17
|
let(:errors) { validator.validate(document) }
|
18
18
|
|
19
19
|
describe 'non-existent directives' do
|
@@ -11,7 +11,7 @@ describe GraphQL::StaticValidation::FieldsAreDefinedOnType do
|
|
11
11
|
fragment cheeseFields on Cheese { fatContent, hogwashField }
|
12
12
|
"}
|
13
13
|
|
14
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
14
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsAreDefinedOnType]) }
|
15
15
|
let(:errors) { validator.validate(GraphQL.parse(query_string)) }
|
16
16
|
let(:error_messages) { errors.map { |e| e["message" ] }}
|
17
17
|
|
@@ -9,7 +9,7 @@ describe GraphQL::StaticValidation::FieldsHaveAppropriateSelections do
|
|
9
9
|
}
|
10
10
|
")}
|
11
11
|
|
12
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
12
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsHaveAppropriateSelections]) }
|
13
13
|
let(:errors) { validator.validate(document) }
|
14
14
|
|
15
15
|
it 'adds errors for selections on scalars' do
|
data/spec/graph_ql/static_validation/{fields_will_merge_spec.rb → rules/fields_will_merge_spec.rb}
RENAMED
@@ -29,7 +29,7 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
|
|
29
29
|
}
|
30
30
|
")}
|
31
31
|
|
32
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
32
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsWillMerge]) }
|
33
33
|
let(:errors) { validator.validate(document) }
|
34
34
|
let(:error_messages) { errors.map { |e| e["message" ] }}
|
35
35
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
|
4
|
+
let(:document) { GraphQL.parse(%|
|
5
|
+
query getCheese {
|
6
|
+
cheese(id: 1) {
|
7
|
+
... milkFields
|
8
|
+
... cheeseFields
|
9
|
+
... on Milk { fatContent }
|
10
|
+
... on AnimalProduct { source }
|
11
|
+
... on DairyProduct {
|
12
|
+
fatContent
|
13
|
+
... on Edible { fatContent }
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
fragment milkFields on Milk { fatContent }
|
19
|
+
fragment cheeseFields on Cheese {
|
20
|
+
fatContent
|
21
|
+
... milkFields
|
22
|
+
}
|
23
|
+
|)}
|
24
|
+
|
25
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentSpreadsArePossible]) }
|
26
|
+
let(:errors) { validator.validate(document) }
|
27
|
+
|
28
|
+
it "doesnt allow spreads where they'll never apply" do
|
29
|
+
# TODO: more negative, abstract examples here, add stuff to the schema
|
30
|
+
expected = [
|
31
|
+
{
|
32
|
+
"message"=>"Fragment on Milk can't be spread inside Cheese",
|
33
|
+
"locations"=>[{"line"=>6, "column"=>9}]
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"message"=>"Fragment milkFields on Milk can't be spread inside Cheese",
|
37
|
+
"locations"=>[{"line"=>4, "column"=>9}]
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"message"=>"Fragment milkFields on Milk can't be spread inside Cheese",
|
41
|
+
"locations"=>[{"line"=>18, "column"=>7}]
|
42
|
+
}
|
43
|
+
]
|
44
|
+
assert_equal(expected, errors)
|
45
|
+
end
|
46
|
+
end
|
@@ -19,7 +19,7 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
|
|
19
19
|
}
|
20
20
|
")}
|
21
21
|
|
22
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
22
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentTypesExist]) }
|
23
23
|
let(:errors) { validator.validate(document) }
|
24
24
|
|
25
25
|
it 'finds non-existent types on fragments' do
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::FragmentsAreFinite do
|
4
|
+
let(:document) { GraphQL.parse(%|
|
5
|
+
query getCheese {
|
6
|
+
cheese(id: 1) {
|
7
|
+
... idField
|
8
|
+
... sourceField
|
9
|
+
... flavorField
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
fragment sourceField on Cheese {
|
14
|
+
source,
|
15
|
+
... flavorField
|
16
|
+
... idField
|
17
|
+
}
|
18
|
+
fragment flavorField on Cheese {
|
19
|
+
flavor,
|
20
|
+
... sourceField
|
21
|
+
}
|
22
|
+
fragment idField on Cheese {
|
23
|
+
id
|
24
|
+
}
|
25
|
+
|)}
|
26
|
+
|
27
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreFinite]) }
|
28
|
+
let(:errors) { validator.validate(document) }
|
29
|
+
|
30
|
+
it 'doesnt allow infinite loops' do
|
31
|
+
expected = [
|
32
|
+
{
|
33
|
+
"message"=>"Fragment sourceField contains an infinite loop",
|
34
|
+
"locations"=>[{"line"=>10, "column"=>5}]
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"message"=>"Fragment flavorField contains an infinite loop",
|
38
|
+
"locations"=>[{"line"=>15, "column"=>5}]
|
39
|
+
}
|
40
|
+
]
|
41
|
+
assert_equal(expected, errors)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
|
4
|
+
let(:document) { GraphQL.parse(%|
|
5
|
+
query getCheese {
|
6
|
+
cheese(id: 1) {
|
7
|
+
... on Cheese {
|
8
|
+
source
|
9
|
+
... on Boolean {
|
10
|
+
something
|
11
|
+
}
|
12
|
+
}
|
13
|
+
... intFields
|
14
|
+
... on DairyProduct {
|
15
|
+
name
|
16
|
+
}
|
17
|
+
... on DairyProductInput {
|
18
|
+
something
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
fragment intFields on Int {
|
24
|
+
something
|
25
|
+
}
|
26
|
+
|)}
|
27
|
+
|
28
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreOnCompositeTypes]) }
|
29
|
+
let(:errors) { validator.validate(document) }
|
30
|
+
|
31
|
+
it 'requires Object/Union/Interface fragment types' do
|
32
|
+
expected = [
|
33
|
+
{
|
34
|
+
"message"=>"Invalid fragment on type Boolean (must be Union, Interface or Object)",
|
35
|
+
"locations"=>[{"line"=>6, "column"=>11}]
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"message"=>"Invalid fragment on type DairyProductInput (must be Union, Interface or Object)",
|
39
|
+
"locations"=>[{"line"=>14, "column"=>9}],
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"message"=>"Invalid fragment on type Int (must be Union, Interface or Object)",
|
43
|
+
"locations"=>[{"line"=>20, "column"=>5}]
|
44
|
+
},
|
45
|
+
]
|
46
|
+
assert_equal(expected, errors)
|
47
|
+
end
|
48
|
+
end
|
data/spec/graph_ql/static_validation/{fragments_are_used_spec.rb → rules/fragments_are_used_spec.rb}
RENAMED
@@ -11,7 +11,7 @@ describe GraphQL::StaticValidation::FragmentsAreUsed do
|
|
11
11
|
fragment unusedFields on Cheese { is, not, used }
|
12
12
|
")}
|
13
13
|
|
14
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
14
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreUsed]) }
|
15
15
|
let(:errors) { validator.validate(document) }
|
16
16
|
|
17
17
|
it 'adds errors for unused fragment definitions' do
|
@@ -14,7 +14,7 @@ describe GraphQL::StaticValidation::RequiredArgumentsArePresent 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::RequiredArgumentsArePresent]) }
|
18
18
|
let(:errors) { validator.validate(document) }
|
19
19
|
|
20
20
|
it 'finds undefined arguments to fields and directives' do
|
data/spec/graph_ql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
|
4
|
+
let(:document) { GraphQL.parse('
|
5
|
+
query getCheese(
|
6
|
+
$id: Int = 1,
|
7
|
+
$bool: Boolean = 3.4e24, # can be coerced
|
8
|
+
$str: String!,
|
9
|
+
$badFloat: Float = true,
|
10
|
+
$badInt: Int = "abc",
|
11
|
+
$input: DairyProductInput = {source: YAK, fatContent: 1},
|
12
|
+
$badInput: DairyProductInput = {source: YAK, fatContent: true},
|
13
|
+
$nonNull: Int! = 1,
|
14
|
+
) {
|
15
|
+
cheese(id: $id) { source }
|
16
|
+
}
|
17
|
+
')}
|
18
|
+
|
19
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped]) }
|
20
|
+
let(:errors) { validator.validate(document) }
|
21
|
+
|
22
|
+
it "finds default values that don't match their types" do
|
23
|
+
expected = [
|
24
|
+
{
|
25
|
+
"message"=>"Default value for $badFloat doesn't match type Float",
|
26
|
+
"locations"=>[{"line"=>6, "column"=>8}]
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"message"=>"Default value for $badInt doesn't match type Int",
|
30
|
+
"locations"=>[{"line"=>7, "column"=>8}]
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"message"=>"Default value for $badInput doesn't match type DairyProductInput",
|
34
|
+
"locations"=>[{"line"=>9, "column"=>8}]
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"message"=>"Non-null variable $nonNull can't have a default value",
|
38
|
+
"locations"=>[{"line"=>10, "column"=>8}]
|
39
|
+
}
|
40
|
+
]
|
41
|
+
assert_equal(expected, errors)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
|
4
|
+
let(:document) { GraphQL.parse('
|
5
|
+
query getCheese(
|
6
|
+
$goodInt: Int = 1,
|
7
|
+
$okInt: Int!,
|
8
|
+
$badInt: Int,
|
9
|
+
$badStr: String!,
|
10
|
+
$goodAnimals: [DairyAnimal!]!,
|
11
|
+
$badAnimals: [DairyAnimal]!,
|
12
|
+
) {
|
13
|
+
goodCheese: cheese(id: $goodInt) { source }
|
14
|
+
okCheese: cheese(id: $okInt) { source }
|
15
|
+
badCheese: cheese(id: $badInt) { source }
|
16
|
+
badStrCheese: cheese(id: $badStr) { source }
|
17
|
+
cheese(id: 1) {
|
18
|
+
similarCheeses(source: $goodAnimals)
|
19
|
+
other: similarCheeses(source: $badAnimals)
|
20
|
+
}
|
21
|
+
}
|
22
|
+
')}
|
23
|
+
|
24
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableUsagesAreAllowed]) }
|
25
|
+
let(:errors) { validator.validate(document) }
|
26
|
+
|
27
|
+
it "finds variables used as arguments but don't match the argument's type" do
|
28
|
+
assert_equal(3, errors.length)
|
29
|
+
expected = [
|
30
|
+
{
|
31
|
+
"message"=>"Type mismatch on variable $badInt and argument id (Int / Int!)",
|
32
|
+
"locations"=>[{"line"=>12, "column"=>28}]
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"message"=>"Type mismatch on variable $badStr and argument id (String! / Int!)",
|
36
|
+
"locations"=>[{"line"=>13, "column"=>28}]
|
37
|
+
},
|
38
|
+
{
|
39
|
+
"message"=>"Type mismatch on variable $badAnimals and argument source ([DairyAnimal]! / [DairyAnimal!]!)",
|
40
|
+
"locations"=>[{"line"=>16, "column"=>31}]
|
41
|
+
}
|
42
|
+
]
|
43
|
+
assert_equal(expected, errors)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::VariablesAreInputTypes do
|
4
|
+
let(:document) { GraphQL.parse('
|
5
|
+
query getCheese(
|
6
|
+
$id: Int = 1,
|
7
|
+
$str: [String!],
|
8
|
+
$interface: AnimalProduct!,
|
9
|
+
$object: Milk = 1,
|
10
|
+
$objects: [Cheese]!,
|
11
|
+
) {
|
12
|
+
cheese(id: $id) { source }
|
13
|
+
}
|
14
|
+
')}
|
15
|
+
|
16
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreInputTypes]) }
|
17
|
+
let(:errors) { validator.validate(document) }
|
18
|
+
|
19
|
+
it "finds variables whose types are invalid" do
|
20
|
+
expected = [
|
21
|
+
{
|
22
|
+
"message"=>"AnimalProduct isn't a valid input type (on $interface)",
|
23
|
+
"locations"=>[{"line"=>5, "column"=>8}]
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"message"=>"Milk isn't a valid input type (on $object)",
|
27
|
+
"locations"=>[{"line"=>6, "column"=>8}]
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"message"=>"Cheese isn't a valid input type (on $objects)",
|
31
|
+
"locations"=>[{"line"=>7, "column"=>8}]
|
32
|
+
}
|
33
|
+
]
|
34
|
+
assert_equal(expected, errors)
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::VariablesAreUsedAndDefined do
|
4
|
+
let(:document) { GraphQL.parse('
|
5
|
+
query getCheese($id: Int, $str: String, $notUsedVar: Float, $bool: Boolean) {
|
6
|
+
cheese(id: $id) {
|
7
|
+
source(str: $str)
|
8
|
+
whatever(undefined: $undefinedVar)
|
9
|
+
... on Cheese {
|
10
|
+
something(bool: $bool)
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
fragment outerCheeseFields on Cheese {
|
16
|
+
... innerCheeseFields
|
17
|
+
}
|
18
|
+
|
19
|
+
fragment innerCheeseFields on Cheese {
|
20
|
+
source(notDefined: $notDefinedVar)
|
21
|
+
}
|
22
|
+
')}
|
23
|
+
|
24
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreUsedAndDefined]) }
|
25
|
+
let(:errors) { validator.validate(document) }
|
26
|
+
|
27
|
+
it "finds variables which are used-but-not-defined or defined-but-not-used" do
|
28
|
+
expected = [
|
29
|
+
{
|
30
|
+
"message"=>"Variable $undefinedVar is used but not declared",
|
31
|
+
"locations"=>[{"line"=>5, "column"=>30}]
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"message"=>"Variable $notUsedVar is declared but not used",
|
35
|
+
"locations"=>[{"line"=>2, "column"=>5}]
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"message"=>"Variable $notDefinedVar is used but not declared",
|
39
|
+
"locations"=>[{"line"=>17, "column"=>27}]
|
40
|
+
},
|
41
|
+
]
|
42
|
+
assert_equal(expected, errors)
|
43
|
+
end
|
44
|
+
end
|
@@ -18,10 +18,10 @@ describe GraphQL::StaticValidation::TypeStack do
|
|
18
18
|
query getCheese {
|
19
19
|
cheese(id: 1) { id, ... edibleFields }
|
20
20
|
}
|
21
|
-
fragment edibleFields on Edible { fatContent }
|
21
|
+
fragment edibleFields on Edible { fatContent @skip(if: false)}
|
22
22
|
|}
|
23
23
|
let(:document) { GraphQL.parse(query_string) }
|
24
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema,
|
24
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [TypeCheckValidator]) }
|
25
25
|
|
26
26
|
it 'stores up types' do
|
27
27
|
validator.validate(document)
|
@@ -14,15 +14,54 @@ class DocumentErrorValidator
|
|
14
14
|
end
|
15
15
|
|
16
16
|
describe GraphQL::StaticValidation::Validator do
|
17
|
-
let(:document) { OpenStruct.new(name: "This is not a document", children: []) }
|
18
|
-
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: "This is not a schema",
|
19
|
-
|
20
|
-
it 'uses
|
21
|
-
errors = validator.validate(document)
|
17
|
+
let(:document) { OpenStruct.new(name: "This is not a document", children: [], parts: []) }
|
18
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: "This is not a schema", rules: [SchemaErrorValidator, DocumentErrorValidator]) }
|
19
|
+
let(:errors) { validator.validate(document) }
|
20
|
+
it 'uses rules' do
|
22
21
|
expected_errors = [
|
23
22
|
{"message" => "Something is wrong: This is not a schema", "locations" => [{"line" => 100, "column" => 4}]},
|
24
23
|
{"message" => "Something is wrong: This is not a document", "locations" => [{"line" => 1, "column" => 1}]}
|
25
24
|
]
|
26
25
|
assert_equal(expected_errors, errors)
|
27
26
|
end
|
27
|
+
|
28
|
+
describe 'validation order' do
|
29
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema) }
|
30
|
+
let(:document) { GraphQL.parse(query_string)}
|
31
|
+
|
32
|
+
describe 'fields & arguments' do
|
33
|
+
let(:query_string) { %|
|
34
|
+
query getCheese {
|
35
|
+
cheese(id: 1) {
|
36
|
+
source,
|
37
|
+
nonsenseField,
|
38
|
+
id(nonsenseArg: 1)
|
39
|
+
bogusField(bogusArg: true)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|}
|
43
|
+
|
44
|
+
it 'handles args on invalid fields' do
|
45
|
+
assert_equal(3, errors.length)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'infinite fragments' do
|
50
|
+
let(:query_string) { %|
|
51
|
+
query getCheese {
|
52
|
+
cheese(id: 1) {
|
53
|
+
... cheeseFields
|
54
|
+
}
|
55
|
+
}
|
56
|
+
fragment cheeseFields on Cheese {
|
57
|
+
id, ... cheeseFields
|
58
|
+
}
|
59
|
+
|}
|
60
|
+
|
61
|
+
it 'handles infinite fragment spreads' do
|
62
|
+
p errors
|
63
|
+
assert_equal(1, errors.length)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
28
67
|
end
|