@@ -21,7 +21,7 @@ import {
21
21
import {
22
22
GraphQLSchema ,
23
23
GraphQLObjectType ,
24
- GraphQLUnionType ,
24
+ GraphQLInterfaceType ,
25
25
GraphQLList ,
26
26
GraphQLNonNull ,
27
27
GraphQLInt ,
@@ -101,6 +101,21 @@ describe('Validate: Overlapping fields can be merged', () => {
101
101
] ) ;
102
102
} ) ;
103
103
104
+ it ( 'Same aliases allowed on non-overlapping fields' , ( ) => {
105
+ // This is valid since no object can be both a "Dog" and a "Cat", thus
106
+ // these fields can never overlap.
107
+ expectPassesRule ( OverlappingFieldsCanBeMerged , `
108
+ fragment sameAliasesWithDifferentFieldTargets on Pet {
109
+ ... on Dog {
110
+ name
111
+ }
112
+ ... on Cat {
113
+ name: nickname
114
+ }
115
+ }
116
+ ` ) ;
117
+ } ) ;
118
+
104
119
it ( 'Alias masking direct field access' , ( ) => {
105
120
expectFailsRule ( OverlappingFieldsCanBeMerged , `
106
121
fragment aliasMaskingDirectFieldAccess on Dog {
@@ -116,6 +131,36 @@ describe('Validate: Overlapping fields can be merged', () => {
116
131
] ) ;
117
132
} ) ;
118
133
134
+ it ( 'different args, second adds an argument' , ( ) => {
135
+ expectFailsRule ( OverlappingFieldsCanBeMerged , `
136
+ fragment conflictingArgs on Dog {
137
+ doesKnowCommand
138
+ doesKnowCommand(dogCommand: HEEL)
139
+ }
140
+ ` , [
141
+ { message : fieldsConflictMessage (
142
+ 'doesKnowCommand' ,
143
+ 'they have differing arguments'
144
+ ) ,
145
+ locations : [ { line : 3 , column : 9 } , { line : 4 , column : 9 } ] }
146
+ ] ) ;
147
+ } ) ;
148
+
149
+ it ( 'different args, second missing an argument' , ( ) => {
150
+ expectFailsRule ( OverlappingFieldsCanBeMerged , `
151
+ fragment conflictingArgs on Dog {
152
+ doesKnowCommand(dogCommand: SIT)
153
+ doesKnowCommand
154
+ }
155
+ ` , [
156
+ { message : fieldsConflictMessage (
157
+ 'doesKnowCommand' ,
158
+ 'they have differing arguments'
159
+ ) ,
160
+ locations : [ { line : 3 , column : 9 } , { line : 4 , column : 9 } ] }
161
+ ] ) ;
162
+ } ) ;
163
+
119
164
it ( 'conflicting args' , ( ) => {
120
165
expectFailsRule ( OverlappingFieldsCanBeMerged , `
121
166
fragment conflictingArgs on Dog {
@@ -131,6 +176,21 @@ describe('Validate: Overlapping fields can be merged', () => {
131
176
] ) ;
132
177
} ) ;
133
178
179
+ it ( 'allows different args where no conflict is possible' , ( ) => {
180
+ // This is valid since no object can be both a "Dog" and a "Cat", thus
181
+ // these fields can never overlap.
182
+ expectPassesRule ( OverlappingFieldsCanBeMerged , `
183
+ fragment conflictingArgs on Pet {
184
+ ... on Dog {
185
+ name(surname: true)
186
+ }
187
+ ... on Cat {
188
+ name
189
+ }
190
+ }
191
+ ` ) ;
192
+ } ) ;
193
+
134
194
it ( 'conflicting directives' , ( ) => {
135
195
expectFailsRule ( OverlappingFieldsCanBeMerged , `
136
196
fragment conflictingDirectiveArgs on Dog {
@@ -353,39 +413,67 @@ describe('Validate: Overlapping fields can be merged', () => {
353
413
354
414
describe ( 'return types must be unambiguous' , ( ) => {
355
415
416
+ var SomeBox = new GraphQLInterfaceType ( {
417
+ name : 'SomeBox' ,
418
+ resolveType : ( ) => StringBox ,
419
+ fields : {
420
+ unrelatedField : { type : GraphQLString }
421
+ }
422
+ } ) ;
423
+
424
+ /* eslint-disable no-unused-vars */
356
425
var StringBox = new GraphQLObjectType ( {
357
426
name : 'StringBox' ,
427
+ interfaces : [ SomeBox ] ,
358
428
fields : {
359
- scalar : { type : GraphQLString }
429
+ scalar : { type : GraphQLString } ,
430
+ unrelatedField : { type : GraphQLString } ,
360
431
}
361
432
} ) ;
362
433
363
434
var IntBox = new GraphQLObjectType ( {
364
435
name : 'IntBox' ,
436
+ interfaces : [ SomeBox ] ,
365
437
fields : {
366
- scalar : { type : GraphQLInt }
438
+ scalar : { type : GraphQLInt } ,
439
+ unrelatedField : { type : GraphQLString } ,
367
440
}
368
441
} ) ;
369
442
370
- var NonNullStringBox1 = new GraphQLObjectType ( {
443
+ var NonNullStringBox1 = new GraphQLInterfaceType ( {
371
444
name : 'NonNullStringBox1' ,
445
+ resolveType : ( ) => StringBox ,
372
446
fields : {
373
447
scalar : { type : new GraphQLNonNull ( GraphQLString ) }
374
448
}
375
449
} ) ;
376
450
377
- var NonNullStringBox2 = new GraphQLObjectType ( {
451
+ var NonNullStringBox1Impl = new GraphQLObjectType ( {
452
+ name : 'NonNullStringBox1Impl' ,
453
+ interfaces : [ SomeBox , NonNullStringBox1 ] ,
454
+ fields : {
455
+ scalar : { type : new GraphQLNonNull ( GraphQLString ) } ,
456
+ unrelatedField : { type : GraphQLString } ,
457
+ }
458
+ } ) ;
459
+
460
+ var NonNullStringBox2 = new GraphQLInterfaceType ( {
378
461
name : 'NonNullStringBox2' ,
462
+ resolveType : ( ) => StringBox ,
379
463
fields : {
380
464
scalar : { type : new GraphQLNonNull ( GraphQLString ) }
381
465
}
382
466
} ) ;
383
467
384
- var BoxUnion = new GraphQLUnionType ( {
385
- name : 'BoxUnion' ,
386
- resolveType : ( ) => StringBox ,
387
- types : [ StringBox , IntBox , NonNullStringBox1 , NonNullStringBox2 ]
468
+ var NonNullStringBox2Impl = new GraphQLObjectType ( {
469
+ name : 'NonNullStringBox2Impl' ,
470
+ interfaces : [ SomeBox , NonNullStringBox2 ] ,
471
+ fields : {
472
+ scalar : { type : new GraphQLNonNull ( GraphQLString ) } ,
473
+ unrelatedField : { type : GraphQLString } ,
474
+ }
388
475
} ) ;
476
+ /* eslint-enable no-unused-vars */
389
477
390
478
var Connection = new GraphQLObjectType ( {
391
479
name : 'Connection' ,
@@ -413,37 +501,57 @@ describe('Validate: Overlapping fields can be merged', () => {
413
501
query : new GraphQLObjectType ( {
414
502
name : 'QueryRoot' ,
415
503
fields : ( ) => ( {
416
- boxUnion : { type : BoxUnion } ,
504
+ someBox : { type : SomeBox } ,
417
505
connection : { type : Connection }
418
506
} )
419
507
} )
420
508
} ) ;
421
509
422
- it ( 'conflicting scalar return types' , ( ) => {
510
+ it ( 'conflicting return types which potentially overlap' , ( ) => {
511
+ // This is invalid since an object could potentially be both the Object
512
+ // type IntBox and the interface type NonNullStringBox1. While that
513
+ // condition does not exist in the current schema, the schema could
514
+ // expand in the future to allow this. Thus it is invalid.
423
515
expectFailsRuleWithSchema ( schema , OverlappingFieldsCanBeMerged , `
424
516
{
425
- boxUnion {
517
+ someBox {
426
518
...on IntBox {
427
519
scalar
428
520
}
429
- ...on StringBox {
521
+ ...on NonNullStringBox1 {
430
522
scalar
431
523
}
432
524
}
433
525
}
434
526
` , [
435
527
{ message : fieldsConflictMessage (
436
528
'scalar' ,
437
- 'they return differing types Int and String'
529
+ 'they return differing types Int and String! '
438
530
) ,
439
531
locations : [ { line : 5 , column : 15 } , { line : 8 , column : 15 } ] }
440
532
] ) ;
441
533
} ) ;
442
534
535
+ it ( 'allows differing return types which cannot overlap' , ( ) => {
536
+ // This is valid since an object cannot be both an IntBox and a StringBox.
537
+ expectPassesRuleWithSchema ( schema , OverlappingFieldsCanBeMerged , `
538
+ {
539
+ someBox {
540
+ ...on IntBox {
541
+ scalar
542
+ }
543
+ ...on StringBox {
544
+ scalar
545
+ }
546
+ }
547
+ }
548
+ ` ) ;
549
+ } ) ;
550
+
443
551
it ( 'same wrapped scalar return types' , ( ) => {
444
552
expectPassesRuleWithSchema ( schema , OverlappingFieldsCanBeMerged , `
445
553
{
446
- boxUnion {
554
+ someBox {
447
555
...on NonNullStringBox1 {
448
556
scalar
449
557
}
@@ -505,7 +613,7 @@ describe('Validate: Overlapping fields can be merged', () => {
505
613
it ( 'ignores unknown types' , ( ) => {
506
614
expectPassesRuleWithSchema ( schema , OverlappingFieldsCanBeMerged , `
507
615
{
508
- boxUnion {
616
+ someBox {
509
617
...on UnknownType {
510
618
scalar
511
619
}
0 commit comments