Skip to content

Commit e0b9cfe

Browse files
committed
Handle missing variables like a validation error in query analysis
1 parent e17f185 commit e0b9cfe

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

lib/graphql/query.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ def result
7373
# If more than one operation is present, it must be named at runtime.
7474
# @return [GraphQL::Language::Nodes::OperationDefinition, nil]
7575
def selected_operation
76-
@selected_operation ||= find_operation(@operations, @operation_name)
76+
@selected_operation ||= begin
77+
perform_validation
78+
@selected_operation
79+
end
7780
end
7881

7982
# Determine the values for variables of this query, using default values
@@ -118,9 +121,18 @@ def arguments_for(irep_node, definition)
118121
private
119122

120123
def perform_validation
124+
@selected_operation = find_operation(@operations, @operation_name)
121125
validation_result = schema.static_validator.validate(self)
122126
@validation_errors = validation_result[:errors]
123127
@internal_representation = validation_result[:irep]
128+
if @validation_errors.none?
129+
# Accessing variables will raise errors if there are any :S
130+
variables
131+
end
132+
nil
133+
rescue GraphQL::Query::OperationNameMissingError, GraphQL::Query::VariableValidationError => err
134+
@validation_errors = [err.to_h]
135+
@internal_representation = nil
124136
nil
125137
end
126138

spec/graphql/analysis/analyze_query_spec.rb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ def call(memo, visit_type, irep_node)
2626
let(:type_collector) { TypeCollector.new }
2727
let(:analyzers) { [type_collector, node_counter] }
2828
let(:reduce_result) { GraphQL::Analysis.analyze_query(query, analyzers) }
29-
let(:query) { GraphQL::Query.new(DummySchema, query_string) }
29+
let(:variables) { {} }
30+
let(:query) { GraphQL::Query.new(DummySchema, query_string, variables: variables) }
3031
let(:query_string) {%|
3132
{
3233
cheese(id: 1) {
@@ -46,5 +47,33 @@ def call(memo, visit_type, irep_node)
4647
}
4748
assert_equal expected_node_counts, node_counts
4849
end
50+
51+
describe "when a variable is missing" do
52+
let(:query_string) {%|
53+
query something($cheeseId: Int!){
54+
cheese(id: $cheeseId) {
55+
id
56+
flavor
57+
}
58+
}
59+
|}
60+
let(:variable_accessor) { -> (memo, visit_type, irep_node) { query.variables["cheeseId"] } }
61+
62+
before do
63+
@previous_query_analyzers = DummySchema.query_analyzers.dup
64+
DummySchema.query_analyzers.clear
65+
DummySchema.query_analyzers << variable_accessor
66+
end
67+
68+
after do
69+
DummySchema.query_analyzers.clear
70+
DummySchema.query_analyzers.push(*@previous_query_analyzers)
71+
end
72+
73+
it "returns an error" do
74+
error = query.result["errors"].first
75+
assert_equal "Variable cheeseId of type Int! was provided invalid value", error["message"]
76+
end
77+
end
4978
end
5079
end

0 commit comments

Comments
 (0)