Skip to content

Commit fb65e75

Browse files
authored
Merge pull request #4429 from rmosolgo/fix-selections-on-scalars
Fix crash when selections and inline fragments are made on scalars
2 parents 34e8164 + eff7032 commit fb65e75

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,19 @@ def validate_field_selections(ast_node, resolved_type)
2626
msg = if resolved_type.nil?
2727
nil
2828
elsif resolved_type.kind.scalar? && ast_node.selections.any?
29-
if ast_node.selections.first.is_a?(GraphQL::Language::Nodes::InlineFragment)
30-
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.graphql_name} but has inline fragments [#{ast_node.selections.map(&:type).map(&:name).join(", ")}])"
31-
else
32-
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.graphql_name} but has selections [#{ast_node.selections.map(&:name).join(", ")}])"
29+
selection_strs = ast_node.selections.map do |n|
30+
case n
31+
when GraphQL::Language::Nodes::InlineFragment
32+
"\"... on #{n.type.name} { ... }\""
33+
when GraphQL::Language::Nodes::Field
34+
"\"#{n.name}\""
35+
when GraphQL::Language::Nodes::FragmentSpread
36+
"\"#{n.name}\""
37+
else
38+
raise "Invariant: unexpected selection node: #{n}"
39+
end
3340
end
41+
"Selections can't be made on scalars (%{node_name} returns #{resolved_type.graphql_name} but has selections [#{selection_strs.join(", ")}])"
3442
elsif resolved_type.kind.fields? && ast_node.selections.empty?
3543
"Field must have selections (%{node_name} returns #{resolved_type.graphql_name} but has no selections. Did you mean '#{ast_node.name} { ... }'?)"
3644
else

spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
assert_equal(4, errors.length)
1818

1919
illegal_selection_error = {
20-
"message"=>"Selections can't be made on scalars (field 'id' returns Int but has selections [something, someFields])",
20+
"message"=>"Selections can't be made on scalars (field 'id' returns Int but has selections [\"something\", \"someFields\"])",
2121
"locations"=>[{"line"=>6, "column"=>47}],
2222
"path"=>["query getCheese", "illegalSelectionCheese", "id"],
2323
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"field 'id'", "typeName"=>"Int"}
@@ -41,7 +41,7 @@
4141
assert_includes(errors, interfaces_selection_required_error, "finds interfaces without selections")
4242

4343
incorrect_fragment_error = {
44-
"message"=>"Selections can't be made on scalars (field 'flavor' returns String but has inline fragments [String])",
44+
"message"=>"Selections can't be made on scalars (field 'flavor' returns String but has selections [\"... on String { ... }\"])",
4545
"locations"=>[{"line"=>7, "column"=>48}],
4646
"path"=>["query getCheese", "incorrectFragmentSpread", "flavor"],
4747
"extensions"=>{"code"=>"selectionMismatch", "nodeName"=>"field 'flavor'", "typeName"=>"String"}
@@ -63,4 +63,28 @@
6363
assert_includes(errors, selections_required_error)
6464
end
6565
end
66+
67+
describe "selections and inline fragments on scalars" do
68+
let(:query_string) {"
69+
{
70+
cheese(id: 1) {
71+
fatContent {
72+
name
73+
... on User {
74+
id
75+
}
76+
... F
77+
}
78+
}
79+
}
80+
81+
fragment F on Cheese {
82+
id
83+
}
84+
"}
85+
it "returns an error" do
86+
expected_err = "Selections can't be made on scalars (field 'fatContent' returns Float but has selections [\"name\", \"... on User { ... }\", \"F\"])"
87+
assert_includes(errors.map { |e| e["message"] }, expected_err)
88+
end
89+
end
6690
end

0 commit comments

Comments
 (0)