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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graph_ql/{types → definition_helpers}/argument_definer.rb +0 -0
  3. data/lib/graph_ql/definition_helpers/definable.rb +18 -0
  4. data/lib/graph_ql/{types → definition_helpers}/field_definer.rb +0 -0
  5. data/lib/graph_ql/definition_helpers/forwardable.rb +10 -0
  6. data/lib/graph_ql/definition_helpers/non_null_with_bang.rb +9 -0
  7. data/lib/graph_ql/definition_helpers/string_named_hash.rb +12 -0
  8. data/lib/graph_ql/{types → definition_helpers}/type_definer.rb +1 -0
  9. data/lib/graph_ql/directive.rb +9 -5
  10. data/lib/graph_ql/directives/directive_chain.rb +1 -1
  11. data/lib/graph_ql/field.rb +1 -5
  12. data/lib/graph_ql/parser/transform.rb +1 -3
  13. data/lib/graph_ql/query.rb +14 -3
  14. data/lib/graph_ql/query/arguments.rb +6 -5
  15. data/lib/graph_ql/query/field_resolution_strategy.rb +3 -3
  16. data/lib/graph_ql/{types → scalars}/boolean_type.rb +0 -0
  17. data/lib/graph_ql/{types → scalars}/float_type.rb +1 -1
  18. data/lib/graph_ql/scalars/id_type.rb +6 -0
  19. data/lib/graph_ql/{types → scalars}/int_type.rb +0 -0
  20. data/lib/graph_ql/{types → scalars}/scalar_type.rb +0 -4
  21. data/lib/graph_ql/{types → scalars}/string_type.rb +0 -0
  22. data/lib/graph_ql/static_validation.rb +7 -10
  23. data/lib/graph_ql/static_validation/all_rules.rb +23 -0
  24. data/lib/graph_ql/static_validation/literal_validator.rb +0 -3
  25. data/lib/graph_ql/static_validation/{argument_literals_are_compatible.rb → rules/argument_literals_are_compatible.rb} +0 -0
  26. data/lib/graph_ql/static_validation/{arguments_are_defined.rb → rules/arguments_are_defined.rb} +5 -0
  27. data/lib/graph_ql/static_validation/{directives_are_defined.rb → rules/directives_are_defined.rb} +0 -0
  28. data/lib/graph_ql/static_validation/{fields_are_defined_on_type.rb → rules/fields_are_defined_on_type.rb} +0 -0
  29. data/lib/graph_ql/static_validation/{fields_have_appropriate_selections.rb → rules/fields_have_appropriate_selections.rb} +0 -0
  30. data/lib/graph_ql/static_validation/{fields_will_merge.rb → rules/fields_will_merge.rb} +13 -5
  31. data/lib/graph_ql/static_validation/rules/fragment_spreads_are_possible.rb +50 -0
  32. data/lib/graph_ql/static_validation/{fragment_types_exist.rb → rules/fragment_types_exist.rb} +0 -0
  33. data/lib/graph_ql/static_validation/rules/fragments_are_finite.rb +23 -0
  34. data/lib/graph_ql/static_validation/rules/fragments_are_on_composite_types.rb +27 -0
  35. data/lib/graph_ql/static_validation/{fragments_are_used.rb → rules/fragments_are_used.rb} +0 -0
  36. data/lib/graph_ql/static_validation/{required_arguments_are_present.rb → rules/required_arguments_are_present.rb} +0 -0
  37. data/lib/graph_ql/static_validation/rules/variable_default_values_are_correctly_typed.rb +24 -0
  38. data/lib/graph_ql/static_validation/rules/variable_usages_are_allowed.rb +47 -0
  39. data/lib/graph_ql/static_validation/rules/variables_are_input_types.rb +27 -0
  40. data/lib/graph_ql/static_validation/rules/variables_are_used_and_defined.rb +31 -0
  41. data/lib/graph_ql/static_validation/type_stack.rb +13 -1
  42. data/lib/graph_ql/static_validation/validator.rb +14 -18
  43. data/lib/graph_ql/type_kinds.rb +8 -4
  44. data/lib/graph_ql/{enum.rb → types/enum.rb} +7 -6
  45. data/lib/graph_ql/types/input_object_type.rb +3 -10
  46. data/lib/graph_ql/{interface.rb → types/interface.rb} +0 -4
  47. data/lib/graph_ql/types/list_type.rb +0 -4
  48. data/lib/graph_ql/types/non_null_type.rb +0 -4
  49. data/lib/graph_ql/types/object_type.rb +28 -13
  50. data/lib/graph_ql/{union.rb → types/union.rb} +0 -4
  51. data/lib/graph_ql/version.rb +1 -1
  52. data/lib/graphql.rb +9 -40
  53. data/readme.md +26 -20
  54. data/spec/graph_ql/directive_spec.rb +4 -4
  55. data/spec/graph_ql/introspection/directive_type_spec.rb +2 -2
  56. data/spec/graph_ql/introspection/schema_type_spec.rb +3 -2
  57. data/spec/graph_ql/introspection/type_type_spec.rb +7 -7
  58. data/spec/graph_ql/parser/parser_spec.rb +6 -2
  59. data/spec/graph_ql/query_spec.rb +26 -8
  60. data/spec/graph_ql/scalars/id_type_spec.rb +24 -0
  61. data/spec/graph_ql/schema/type_reducer_spec.rb +1 -0
  62. data/spec/graph_ql/schema/type_validator_spec.rb +1 -1
  63. data/spec/graph_ql/static_validation/{argument_literals_are_compatible_spec.rb → rules/argument_literals_are_compatible_spec.rb} +1 -1
  64. data/spec/graph_ql/static_validation/{arguments_are_defined_spec.rb → rules/arguments_are_defined_spec.rb} +1 -1
  65. data/spec/graph_ql/static_validation/{directives_are_defined_spec.rb → rules/directives_are_defined_spec.rb} +1 -1
  66. data/spec/graph_ql/static_validation/{fields_are_defined_on_type_spec.rb → rules/fields_are_defined_on_type_spec.rb} +1 -1
  67. data/spec/graph_ql/static_validation/{fields_have_appropriate_selections_spec.rb → rules/fields_have_appropriate_selections_spec.rb} +1 -1
  68. data/spec/graph_ql/static_validation/{fields_will_merge_spec.rb → rules/fields_will_merge_spec.rb} +1 -1
  69. data/spec/graph_ql/static_validation/rules/fragment_spreads_are_possible_spec.rb +46 -0
  70. data/spec/graph_ql/static_validation/{fragment_types_exist_spec.rb → rules/fragment_types_exist_spec.rb} +1 -1
  71. data/spec/graph_ql/static_validation/rules/fragments_are_finite_spec.rb +43 -0
  72. data/spec/graph_ql/static_validation/rules/fragments_are_on_composite_types_spec.rb +48 -0
  73. data/spec/graph_ql/static_validation/{fragments_are_used_spec.rb → rules/fragments_are_used_spec.rb} +1 -1
  74. data/spec/graph_ql/static_validation/{required_arguments_are_present_spec.rb → rules/required_arguments_are_present_spec.rb} +1 -1
  75. data/spec/graph_ql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +43 -0
  76. data/spec/graph_ql/static_validation/rules/variable_usages_are_allowed_spec.rb +45 -0
  77. data/spec/graph_ql/static_validation/rules/variables_are_input_types_spec.rb +36 -0
  78. data/spec/graph_ql/static_validation/rules/variables_are_used_and_defined_spec.rb +44 -0
  79. data/spec/graph_ql/static_validation/type_stack_spec.rb +2 -2
  80. data/spec/graph_ql/static_validation/validator_spec.rb +44 -5
  81. data/spec/graph_ql/types/enum_spec.rb +10 -0
  82. data/spec/graph_ql/{interface_spec.rb → types/interface_spec.rb} +1 -1
  83. data/spec/graph_ql/types/object_type_spec.rb +13 -0
  84. data/spec/graph_ql/{union_spec.rb → types/union_spec.rb} +0 -0
  85. data/spec/support/dummy_app.rb +7 -6
  86. data/spec/support/dummy_data.rb +3 -3
  87. metadata +74 -46
  88. data/lib/graph_ql/types/non_null_with_bang.rb +0 -5
  89. 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, validators: [GraphQL::StaticValidation::ArgumentsAreDefined]) }
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, validators: [GraphQL::StaticValidation::DirectivesAreDefined]) }
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, validators: [GraphQL::StaticValidation::FieldsAreDefinedOnType]) }
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, validators: [GraphQL::StaticValidation::FieldsHaveAppropriateSelections]) }
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
@@ -29,7 +29,7 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
29
29
  }
30
30
  ")}
31
31
 
32
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, validators: [GraphQL::StaticValidation::FieldsWillMerge]) }
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, validators: [GraphQL::StaticValidation::FragmentTypesExist]) }
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
@@ -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, validators: [GraphQL::StaticValidation::FragmentsAreUsed]) }
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, validators: [GraphQL::StaticValidation::RequiredArgumentsArePresent]) }
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
@@ -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, validators: [TypeCheckValidator]) }
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", validators: [SchemaErrorValidator, DocumentErrorValidator]) }
19
-
20
- it 'uses validators' do
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