graphql 0.2.0 → 0.3.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/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
|