graphql 0.18.15 → 0.19.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/graphql/define/assign_global_id_field.rb +1 -2
  3. data/lib/graphql/directive.rb +41 -7
  4. data/lib/graphql/directive/deprecated_directive.rb +11 -0
  5. data/lib/graphql/directive/include_directive.rb +2 -2
  6. data/lib/graphql/directive/skip_directive.rb +2 -2
  7. data/lib/graphql/input_object_type.rb +14 -0
  8. data/lib/graphql/internal_representation/node.rb +8 -4
  9. data/lib/graphql/introspection/arguments_field.rb +0 -1
  10. data/lib/graphql/introspection/directive_location_enum.rb +3 -2
  11. data/lib/graphql/introspection/directive_type.rb +12 -7
  12. data/lib/graphql/introspection/enum_value_type.rb +4 -2
  13. data/lib/graphql/introspection/enum_values_field.rb +0 -1
  14. data/lib/graphql/introspection/field_type.rb +8 -7
  15. data/lib/graphql/introspection/fields_field.rb +0 -1
  16. data/lib/graphql/introspection/input_fields_field.rb +0 -1
  17. data/lib/graphql/introspection/input_value_type.rb +8 -10
  18. data/lib/graphql/introspection/interfaces_field.rb +0 -1
  19. data/lib/graphql/introspection/of_type_field.rb +0 -1
  20. data/lib/graphql/introspection/possible_types_field.rb +0 -1
  21. data/lib/graphql/introspection/schema_type.rb +11 -9
  22. data/lib/graphql/introspection/type_kind_enum.rb +3 -3
  23. data/lib/graphql/introspection/type_type.rb +9 -6
  24. data/lib/graphql/language/generation.rb +4 -1
  25. data/lib/graphql/language/lexer.rb +353 -316
  26. data/lib/graphql/language/lexer.rl +8 -6
  27. data/lib/graphql/language/nodes.rb +12 -0
  28. data/lib/graphql/language/parser.rb +553 -501
  29. data/lib/graphql/language/parser.y +26 -16
  30. data/lib/graphql/language/parser_tests.rb +20 -1
  31. data/lib/graphql/list_type.rb +5 -1
  32. data/lib/graphql/non_null_type.rb +4 -0
  33. data/lib/graphql/object_type.rb +1 -1
  34. data/lib/graphql/query/literal_input.rb +1 -1
  35. data/lib/graphql/relay.rb +1 -1
  36. data/lib/graphql/relay/global_id_resolve.rb +3 -5
  37. data/lib/graphql/relay/node.rb +34 -0
  38. data/lib/graphql/scalar_type.rb +1 -1
  39. data/lib/graphql/schema.rb +43 -15
  40. data/lib/graphql/schema/loader.rb +2 -2
  41. data/lib/graphql/schema/printer.rb +50 -8
  42. data/lib/graphql/schema/unique_within_type.rb +28 -0
  43. data/lib/graphql/schema/validation.rb +10 -3
  44. data/lib/graphql/static_validation/rules/fields_will_merge.rb +9 -1
  45. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +8 -2
  46. data/lib/graphql/type_kinds.rb +12 -12
  47. data/lib/graphql/version.rb +1 -1
  48. data/readme.md +6 -5
  49. data/spec/graphql/argument_spec.rb +1 -1
  50. data/spec/graphql/execution_error_spec.rb +53 -0
  51. data/spec/graphql/introspection/directive_type_spec.rb +10 -0
  52. data/spec/graphql/introspection/input_value_type_spec.rb +23 -0
  53. data/spec/graphql/language/generation_spec.rb +4 -0
  54. data/spec/graphql/query/executor_spec.rb +2 -2
  55. data/spec/graphql/relay/mutation_spec.rb +1 -1
  56. data/spec/graphql/relay/node_spec.rb +87 -0
  57. data/spec/graphql/schema/catchall_middleware_spec.rb +1 -1
  58. data/spec/graphql/schema/loader_spec.rb +37 -4
  59. data/spec/graphql/schema/printer_spec.rb +30 -7
  60. data/spec/graphql/schema/unique_within_type_spec.rb +27 -0
  61. data/spec/graphql/schema/validation_spec.rb +7 -11
  62. data/spec/graphql/schema_spec.rb +32 -2
  63. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +14 -15
  64. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +10 -10
  65. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +1 -5
  66. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +3 -5
  67. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +7 -11
  68. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +1 -4
  69. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +10 -13
  70. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +3 -5
  71. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +2 -4
  72. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -6
  73. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -4
  74. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +7 -7
  75. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +1 -4
  76. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -4
  77. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +3 -6
  78. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -4
  79. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +12 -14
  80. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +7 -9
  81. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +20 -22
  82. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +27 -23
  83. data/spec/spec_helper.rb +1 -0
  84. data/spec/support/dairy_app.rb +2 -2
  85. data/spec/support/star_wars_schema.rb +15 -18
  86. data/spec/support/static_validation_helpers.rb +27 -0
  87. metadata +25 -5
  88. data/lib/graphql/relay/global_node_identification.rb +0 -138
  89. data/spec/graphql/relay/global_node_identification_spec.rb +0 -153
@@ -1,15 +1,17 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::FieldsWillMerge do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {"
5
- query getCheese($sourceVar: DairyAnimal!) {
7
+ query getCheese($sourceVar: [DairyAnimal!] = [YAK]) {
6
8
  cheese(id: 1) {
7
9
  id,
8
- nickname: name,
10
+ nickname: flavor,
9
11
  nickname: fatContent,
10
12
  fatContent
11
13
  differentLevel: fatContent
12
- similarCheese(source: $sourceVar)
14
+ similarCheese(source: $sourceVar) { __typename }
13
15
 
14
16
  similarCow: similarCheese(source: COW) {
15
17
  similarCowSource: source,
@@ -17,27 +19,22 @@ describe GraphQL::StaticValidation::FieldsWillMerge do
17
19
  }
18
20
  ...cheeseFields
19
21
  ... on Cheese {
20
- fatContent: name
21
- similarCheese(source: SHEEP)
22
+ fatContent: flavor
23
+ similarCheese(source: SHEEP) { __typename }
22
24
  }
23
25
  }
24
26
  }
25
27
  fragment cheeseFields on Cheese {
26
28
  fatContent,
27
29
  similarCow: similarCheese(source: COW) { similarCowSource: id, id }
28
- id @someFlag
30
+ id @skip(if: true)
29
31
  }
30
32
  "}
31
33
 
32
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FieldsWillMerge]) }
33
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
34
- let(:errors) { validator.validate(query)[:errors] }
35
- let(:error_messages) { errors.map { |e| e["message" ] }}
36
-
37
34
  it "finds field naming conflicts" do
38
35
  expected_errors = [
39
- "Field 'nickname' has a field conflict: name or fatContent?", # alias conflict in query
40
- "Field 'fatContent' has a field conflict: fatContent or name?", # alias/name conflict in query and fragment
36
+ "Field 'nickname' has a field conflict: flavor or fatContent?", # alias conflict in query
37
+ "Field 'fatContent' has a field conflict: fatContent or flavor?", # alias/name conflict in query and fragment
41
38
  "Field 'similarCheese' has an argument conflict: {\"source\":\"sourceVar\"} or {\"source\":\"SHEEP\"}?", # different arguments
42
39
  "Field 'similarCowSource' has a field conflict: source or id?", # nested conflict
43
40
  ]
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {%|
5
7
  query getCheese {
6
8
  cheese(id: 1) {
@@ -9,7 +11,7 @@ describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
9
11
  ... on Milk { fatContent }
10
12
  ... on AnimalProduct { source }
11
13
  ... on DairyProduct {
12
- fatContent
14
+ ... on Cheese { fatContent }
13
15
  ... on Edible { fatContent }
14
16
  }
15
17
  }
@@ -22,10 +24,6 @@ describe GraphQL::StaticValidation::FragmentSpreadsArePossible do
22
24
  }
23
25
  |}
24
26
 
25
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentSpreadsArePossible]) }
26
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
27
- let(:errors) { validator.validate(query)[:errors] }
28
-
29
27
  it "doesnt allow spreads where they'll never apply" do
30
28
  # TODO: more negative, abstract examples here, add stuff to the schema
31
29
  expected = [
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::FragmentTypesExist do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {"
5
7
  query getCheese {
6
8
  cheese(id: 1) {
@@ -19,10 +21,6 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
19
21
  }
20
22
  "}
21
23
 
22
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentTypesExist]) }
23
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
24
- let(:errors) { validator.validate(query)[:errors] }
25
-
26
24
  it "finds non-existent types on fragments" do
27
25
  assert_equal(2, errors.length)
28
26
  inline_fragment_error = {
@@ -1,12 +1,14 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::FragmentsAreFinite do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {%|
5
7
  query getCheese {
6
8
  cheese(id: 1) {
7
9
  ... idField
8
10
  ... sourceField
9
- similarCheese {
11
+ similarCheese(source: SHEEP) {
10
12
  ... flavorField
11
13
  }
12
14
  }
@@ -19,7 +21,7 @@ describe GraphQL::StaticValidation::FragmentsAreFinite do
19
21
  }
20
22
  fragment flavorField on Cheese {
21
23
  flavor,
22
- similarCheese {
24
+ similarCheese(source: SHEEP) {
23
25
  ... on Cheese {
24
26
  ... sourceField
25
27
  }
@@ -30,10 +32,6 @@ describe GraphQL::StaticValidation::FragmentsAreFinite do
30
32
  }
31
33
  |}
32
34
 
33
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreFinite]) }
34
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
35
- let(:errors) { validator.validate(query)[:errors] }
36
-
37
35
  it "doesnt allow infinite loops" do
38
36
  expected = [
39
37
  {
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::FragmentTypesExist do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {"
5
7
  fragment on Cheese {
6
8
  id
@@ -8,10 +10,6 @@ describe GraphQL::StaticValidation::FragmentTypesExist do
8
10
  }
9
11
  "}
10
12
 
11
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreNamed]) }
12
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
13
- let(:errors) { validator.validate(query)[:errors] }
14
-
15
13
  it "finds non-existent types on fragments" do
16
14
  assert_equal(1, errors.length)
17
15
  fragment_def_error = {
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {%|
5
7
  query getCheese {
6
8
  cheese(id: 1) {
@@ -12,7 +14,9 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
12
14
  }
13
15
  ... intFields
14
16
  ... on DairyProduct {
15
- name
17
+ ... on Cheese {
18
+ flavor
19
+ }
16
20
  }
17
21
  ... on DairyProductInput {
18
22
  something
@@ -25,10 +29,6 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
25
29
  }
26
30
  |}
27
31
 
28
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreOnCompositeTypes]) }
29
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
30
- let(:errors) { validator.validate(query)[:errors] }
31
-
32
32
  it "requires Object/Union/Interface fragment types" do
33
33
  expected = [
34
34
  {
@@ -38,12 +38,12 @@ describe GraphQL::StaticValidation::FragmentsAreOnCompositeTypes do
38
38
  },
39
39
  {
40
40
  "message"=>"Invalid fragment on type DairyProductInput (must be Union, Interface or Object)",
41
- "locations"=>[{"line"=>14, "column"=>9}],
41
+ "locations"=>[{"line"=>16, "column"=>9}],
42
42
  "fields"=>["query getCheese", "cheese", "... on DairyProductInput"],
43
43
  },
44
44
  {
45
45
  "message"=>"Invalid fragment on type Int (must be Union, Interface or Object)",
46
- "locations"=>[{"line"=>20, "column"=>5}],
46
+ "locations"=>[{"line"=>22, "column"=>5}],
47
47
  "fields"=>["fragment intFields"],
48
48
  },
49
49
  ]
@@ -1,6 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::FragmentsAreUsed do
4
+ include StaticValidationHelpers
4
5
  let(:query_string) {"
5
6
  query getCheese {
6
7
  name,
@@ -11,10 +12,6 @@ describe GraphQL::StaticValidation::FragmentsAreUsed do
11
12
  fragment unusedFields on Cheese { is, not, used }
12
13
  "}
13
14
 
14
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::FragmentsAreUsed]) }
15
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
16
- let(:errors) { validator.validate(query)[:errors] }
17
-
18
15
  it "adds errors for unused fragment definitions" do
19
16
  assert_includes(errors, {
20
17
  "message"=>"Fragment unusedFields was defined, but not used",
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::MutationRootExists do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {%|
5
7
  mutation addBagel {
6
8
  introduceShip(input: {shipName: "Bagel"}) {
@@ -23,10 +25,6 @@ describe GraphQL::StaticValidation::MutationRootExists do
23
25
  end
24
26
  }
25
27
 
26
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: schema, rules: [GraphQL::StaticValidation::MutationRootExists]) }
27
- let(:query) { GraphQL::Query.new(schema, query_string) }
28
- let(:errors) { validator.validate(query)[:errors] }
29
-
30
28
  it "errors when a mutation is performed on a schema without a mutation root" do
31
29
  assert_equal(1, errors.length)
32
30
  missing_mutation_root_error = {
@@ -1,23 +1,20 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::RequiredArgumentsArePresent do
4
+ include StaticValidationHelpers
4
5
  let(:query_string) {"
5
6
  query getCheese {
6
- cheese(id: 1) { source }
7
+ okCheese: cheese(id: 1) { ...cheeseFields }
7
8
  cheese { source }
8
9
  }
9
10
 
10
11
  fragment cheeseFields on Cheese {
11
- similarCheese(id: 1)
12
+ similarCheese() { __typename }
12
13
  flavor @include(if: true)
13
14
  id @skip
14
15
  }
15
16
  "}
16
17
 
17
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::RequiredArgumentsArePresent]) }
18
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
19
- let(:errors) { validator.validate(query)[:errors] }
20
-
21
18
  it "finds undefined arguments to fields and directives" do
22
19
  assert_equal(3, errors.length)
23
20
 
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::SubscriptionRootExists do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {%|
5
7
  subscription {
6
8
  test
@@ -18,10 +20,6 @@ describe GraphQL::StaticValidation::SubscriptionRootExists do
18
20
  end
19
21
  }
20
22
 
21
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: schema, rules: [GraphQL::StaticValidation::SubscriptionRootExists]) }
22
- let(:query) { GraphQL::Query.new(schema, query_string) }
23
- let(:errors) { validator.validate(query)[:errors] }
24
-
25
23
  it "errors when a subscription is performed on a schema without a subscription root" do
26
24
  assert_equal(1, errors.length)
27
25
  missing_subscription_root_error = {
@@ -1,45 +1,43 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {%|
5
7
  query getCheese(
6
8
  $id: Int = 1,
7
9
  $int: Int = 3.4e24, # can be coerced
8
10
  $str: String!,
9
- $badFloat: Float = true,
10
11
  $badInt: Int = "abc",
11
12
  $input: DairyProductInput = {source: YAK, fatContent: 1},
12
13
  $badInput: DairyProductInput = {source: YAK, fatContent: true},
13
14
  $nonNull: Int! = 1,
14
15
  ) {
15
- cheese(id: $id) { source }
16
+ cheese1: cheese(id: $id) { source }
17
+ cheese4: cheese(id: $int) { source }
18
+ cheese2: cheese(id: $badInt) { source }
19
+ cheese3: cheese(id: $nonNull) { source }
20
+ search1: searchDairy(product: [$input]) { __typename }
21
+ search2: searchDairy(product: [$badInput]) { __typename }
22
+ __type(name: $str) { name }
16
23
  }
17
24
  |}
18
25
 
19
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped]) }
20
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
21
- let(:errors) { validator.validate(query)[:errors] }
22
-
23
26
  it "finds default values that don't match their types" do
24
27
  expected = [
25
- {
26
- "message"=>"Default value for $badFloat doesn't match type Float",
27
- "locations"=>[{"line"=>6, "column"=>7}],
28
- "fields"=>["query getCheese"],
29
- },
30
28
  {
31
29
  "message"=>"Default value for $badInt doesn't match type Int",
32
- "locations"=>[{"line"=>7, "column"=>7}],
30
+ "locations"=>[{"line"=>6, "column"=>7}],
33
31
  "fields"=>["query getCheese"],
34
32
  },
35
33
  {
36
34
  "message"=>"Default value for $badInput doesn't match type DairyProductInput",
37
- "locations"=>[{"line"=>9, "column"=>7}],
35
+ "locations"=>[{"line"=>8, "column"=>7}],
38
36
  "fields"=>["query getCheese"],
39
37
  },
40
38
  {
41
39
  "message"=>"Non-null variable $nonNull can't have a default value",
42
- "locations"=>[{"line"=>10, "column"=>7}],
40
+ "locations"=>[{"line"=>9, "column"=>7}],
43
41
  "fields"=>["query getCheese"],
44
42
  }
45
43
  ]
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {'
5
7
  query getCheese(
6
8
  $goodInt: Int = 1,
@@ -17,11 +19,11 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
17
19
  badCheese: cheese(id: $badInt) { source }
18
20
  badStrCheese: cheese(id: $badStr) { source }
19
21
  cheese(id: 1) {
20
- similarCheese(source: $goodAnimals)
21
- other: similarCheese(source: $badAnimals)
22
- tooDeep: similarCheese(source: $deepAnimals)
23
- nullableCheese(source: $goodAnimals)
24
- deeplyNullableCheese(source: $deepAnimals)
22
+ similarCheese(source: $goodAnimals) { source }
23
+ other: similarCheese(source: $badAnimals) { source }
24
+ tooDeep: similarCheese(source: $deepAnimals) { source }
25
+ nullableCheese(source: $goodAnimals) { source }
26
+ deeplyNullableCheese(source: $deepAnimals) { source }
25
27
  }
26
28
 
27
29
  milk(id: 1) {
@@ -34,10 +36,6 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
34
36
  }
35
37
  '}
36
38
 
37
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariableUsagesAreAllowed]) }
38
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
39
- let(:errors) { validator.validate(query)[:errors] }
40
-
41
39
  it "finds variables used as arguments but don't match the argument's type" do
42
40
  assert_equal(4, errors.length)
43
41
  expected = [
@@ -1,6 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::VariablesAreInputTypes do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {'
5
7
  query getCheese(
6
8
  $id: Int = 1,
@@ -10,31 +12,27 @@ describe GraphQL::StaticValidation::VariablesAreInputTypes do
10
12
  $objects: [Cheese]!,
11
13
  ) {
12
14
  cheese(id: $id) { source }
15
+ __type(name: $str) { name }
13
16
  }
14
17
  '}
15
18
 
16
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreInputTypes]) }
17
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
18
- let(:errors) { validator.validate(query)[:errors] }
19
-
20
19
  it "finds variables whose types are invalid" do
21
- expected = [
22
- {
23
- "message"=>"AnimalProduct isn't a valid input type (on $interface)",
24
- "locations"=>[{"line"=>5, "column"=>7}],
25
- "fields"=>["query getCheese"],
26
- },
27
- {
28
- "message"=>"Milk isn't a valid input type (on $object)",
29
- "locations"=>[{"line"=>6, "column"=>7}],
30
- "fields"=>["query getCheese"],
31
- },
32
- {
33
- "message"=>"Cheese isn't a valid input type (on $objects)",
34
- "locations"=>[{"line"=>7, "column"=>7}],
35
- "fields"=>["query getCheese"],
36
- }
37
- ]
38
- assert_equal(expected, errors)
20
+ assert_includes(errors, {
21
+ "message"=>"AnimalProduct isn't a valid input type (on $interface)",
22
+ "locations"=>[{"line"=>5, "column"=>7}],
23
+ "fields"=>["query getCheese"],
24
+ })
25
+
26
+ assert_includes(errors, {
27
+ "message"=>"Milk isn't a valid input type (on $object)",
28
+ "locations"=>[{"line"=>6, "column"=>7}],
29
+ "fields"=>["query getCheese"],
30
+ })
31
+
32
+ assert_includes(errors, {
33
+ "message"=>"Cheese isn't a valid input type (on $objects)",
34
+ "locations"=>[{"line"=>7, "column"=>7}],
35
+ "fields"=>["query getCheese"],
36
+ })
39
37
  end
40
38
  end
@@ -1,38 +1,41 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe GraphQL::StaticValidation::VariablesAreUsedAndDefined do
4
+ include StaticValidationHelpers
5
+
4
6
  let(:query_string) {'
5
7
  query getCheese(
6
- $usedVar: Int,
7
- $usedInnerVar: String,
8
- $usedInlineFragmentVar: Boolean,
9
- $usedFragmentVar: Int,
10
- $notUsedVar: Float,
8
+ $usedVar: Int!,
9
+ $usedInnerVar: [DairyAnimal!]!,
10
+ $usedInlineFragmentVar: Int!,
11
+ $usedFragmentVar: Int!,
12
+ $notUsedVar: Int!,
11
13
  ) {
12
- cheese(id: $usedVar) {
13
- source(str: $usedInnerVar)
14
- whatever(undefined: $undefinedVar)
15
- ... on Cheese {
16
- something(bool: $usedInlineFragmentVar)
14
+ c1: cheese(id: $usedVar) {
15
+ __typename
16
+ }
17
+ ... on Query {
18
+ c2: cheese(id: $usedInlineFragmentVar) {
19
+ similarCheese(source: $usedInnerVar) { __typename }
17
20
  }
18
- ... outerCheeseFields
21
+
19
22
  }
23
+
24
+ c3: cheese(id: $undefinedVar) { __typename }
25
+
26
+ ... outerCheeseFields
20
27
  }
21
28
 
22
- fragment outerCheeseFields on Cheese {
29
+ fragment outerCheeseFields on Query {
23
30
  ... innerCheeseFields
24
31
  }
25
32
 
26
- fragment innerCheeseFields on Cheese {
27
- source(notDefined: $undefinedFragmentVar)
28
- someField(someArg: $usedFragmentVar)
33
+ fragment innerCheeseFields on Query {
34
+ c4: cheese(id: $undefinedFragmentVar) { __typename }
35
+ c5: cheese(id: $usedFragmentVar) { __typename }
29
36
  }
30
37
  '}
31
38
 
32
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [GraphQL::StaticValidation::VariablesAreUsedAndDefined]) }
33
- let(:query) { GraphQL::Query.new(DummySchema, query_string) }
34
- let(:errors) { validator.validate(query)[:errors] }
35
-
36
39
  it "finds variables which are used-but-not-defined or defined-but-not-used" do
37
40
  expected = [
38
41
  {
@@ -42,15 +45,16 @@ describe GraphQL::StaticValidation::VariablesAreUsedAndDefined do
42
45
  },
43
46
  {
44
47
  "message"=>"Variable $undefinedVar is used by getCheese but not declared",
45
- "locations"=>[{"line"=>11, "column"=>29}],
46
- "fields"=>["query getCheese", "cheese", "whatever", "undefined"],
48
+ "locations"=>[{"line"=>19, "column"=>22}],
49
+ "fields"=>["query getCheese", "c3", "id"],
47
50
  },
48
51
  {
49
52
  "message"=>"Variable $undefinedFragmentVar is used by innerCheeseFields but not declared",
50
- "locations"=>[{"line"=>24, "column"=>26}],
51
- "fields"=>["fragment innerCheeseFields", "source", "notDefined"],
53
+ "locations"=>[{"line"=>29, "column"=>22}],
54
+ "fields"=>["fragment innerCheeseFields", "c4", "id"],
52
55
  },
53
56
  ]
57
+
54
58
  assert_equal(expected, errors)
55
59
  end
56
60
  end