Skip to content

Commit d087317

Browse files
author
Robert Mosolgo
authored
Merge pull request #3440 from rmosolgo/fix-union-interface-field-merging
Fix fields-will-merge for fields that return unions and have spreads on mutually exclusive interfaces
2 parents 4eff70c + 260331a commit d087317

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

lib/graphql/static_validation/rules/fields_will_merge.rb

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,17 +373,26 @@ def compared_fragments_key(frag1, frag2, exclusive)
373373
# In this context, `parents` represends the "self scope" of the field,
374374
# what types may be found at this point in the query.
375375
def mutually_exclusive?(parents1, parents2)
376-
parents1.each do |type1|
377-
parents2.each do |type2|
378-
# If the types we're comparing are both different object types,
379-
# they have to be mutually exclusive.
380-
if type1 != type2 && type1.kind.object? && type2.kind.object?
381-
return true
376+
if parents1.empty? || parents2.empty?
377+
false
378+
elsif parents1.length == parents2.length
379+
parents1.length.times.any? do |i|
380+
type1 = parents1[i - 1]
381+
type2 = parents2[i - 1]
382+
if type1 == type2
383+
# If the types we're comparing are the same type,
384+
# then they aren't mutually exclusive
385+
false
386+
else
387+
# Check if these two scopes have _any_ types in common.
388+
possible_right_types = context.query.possible_types(type1)
389+
possible_left_types = context.query.possible_types(type2)
390+
(possible_right_types & possible_left_types).empty?
382391
end
383392
end
393+
else
394+
true
384395
end
385-
386-
false
387396
end
388397
end
389398
end

spec/graphql/static_validation/rules/fields_will_merge_spec.rb

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
cat: Cat
1212
pet: Pet
1313
toy: Toy
14+
animal: Animal
1415
}
1516
17+
union Animal = Dog \| Cat
18+
1619
type Mutation {
1720
registerPet(params: PetParams): Pet
1821
}
@@ -50,15 +53,23 @@
5053
toys: [Toy!]!
5154
}
5255
53-
type Dog implements Pet & Mammal {
56+
interface Canine {
57+
barkVolume: Int!
58+
}
59+
60+
interface Feline {
61+
meowVolume: Int!
62+
}
63+
64+
type Dog implements Pet & Mammal & Canine {
5465
name(surname: Boolean = false): String!
5566
nickname: String
5667
doesKnowCommand(dogCommand: PetCommand): Boolean!
5768
barkVolume: Int!
5869
toys: [Toy!]!
5970
}
6071
61-
type Cat implements Pet & Mammal {
72+
type Cat implements Pet & Mammal & Feline {
6273
name(surname: Boolean = false): String!
6374
nickname: String
6475
doesKnowCommand(catCommand: PetCommand): Boolean!
@@ -477,6 +488,25 @@
477488
end
478489
end
479490

491+
describe "same aliases on divergent abstract types" do
492+
let(:query_string) {%|
493+
{
494+
animal {
495+
... on Feline {
496+
volume: meowVolume
497+
}
498+
... on Canine {
499+
volume: barkVolume
500+
}
501+
}
502+
}
503+
|}
504+
505+
it "passes rule" do
506+
assert_equal [], errors
507+
end
508+
end
509+
480510
describe "same aliases allowed on different parent interfaces and different concrete types" do
481511
let(:query_string) {%|
482512
{

0 commit comments

Comments
 (0)