Skip to content

Commit 53411a5

Browse files
committed
Implement tests for interfaces implementing interfaces
This ports the JavaScript tests for `RFC: Allow interfaces to implement other interfaces` to PHP. This should ensure that there is sufficient test coverage for the changes made to support interfaces implementing interfaces. Tests taken from https://github.com/graphql/graphql-js/pull/2084/files including any typoes in test description strings to aid in comparison.
1 parent 8ead4df commit 53411a5

16 files changed

+1404
-68
lines changed

src/Utils/BreakingChangesFinder.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ class BreakingChangesFinder
4242
public const BREAKING_CHANGE_ARG_CHANGED_KIND = 'ARG_CHANGED_KIND';
4343
public const BREAKING_CHANGE_REQUIRED_ARG_ADDED = 'REQUIRED_ARG_ADDED';
4444
public const BREAKING_CHANGE_REQUIRED_INPUT_FIELD_ADDED = 'REQUIRED_INPUT_FIELD_ADDED';
45-
public const BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT = 'INTERFACE_REMOVED_FROM_OBJECT';
45+
public const BREAKING_CHANGE_IMPLEMENTED_INTERFACE_REMOVED = 'IMPLEMENTED_INTERFACE_REMOVED';
4646
public const BREAKING_CHANGE_DIRECTIVE_REMOVED = 'DIRECTIVE_REMOVED';
4747
public const BREAKING_CHANGE_DIRECTIVE_ARG_REMOVED = 'DIRECTIVE_ARG_REMOVED';
4848
public const BREAKING_CHANGE_DIRECTIVE_LOCATION_REMOVED = 'DIRECTIVE_LOCATION_REMOVED';
4949
public const BREAKING_CHANGE_REQUIRED_DIRECTIVE_ARG_ADDED = 'REQUIRED_DIRECTIVE_ARG_ADDED';
5050
public const DANGEROUS_CHANGE_ARG_DEFAULT_VALUE_CHANGED = 'ARG_DEFAULT_VALUE_CHANGE';
5151
public const DANGEROUS_CHANGE_VALUE_ADDED_TO_ENUM = 'VALUE_ADDED_TO_ENUM';
52-
public const DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT = 'INTERFACE_ADDED_TO_OBJECT';
52+
public const DANGEROUS_CHANGE_IMPLEMENTED_INTERFACE_ADDED = 'IMPLEMENTED_INTERFACE_ADDED';
5353
public const DANGEROUS_CHANGE_TYPE_ADDED_TO_UNION = 'TYPE_ADDED_TO_UNION';
5454
public const DANGEROUS_CHANGE_OPTIONAL_INPUT_FIELD_ADDED = 'OPTIONAL_INPUT_FIELD_ADDED';
5555
public const DANGEROUS_CHANGE_OPTIONAL_ARG_ADDED = 'OPTIONAL_ARG_ADDED';
@@ -609,7 +609,7 @@ static function (InterfaceType $interface) use ($oldInterface) : bool {
609609
}
610610

611611
$breakingChanges[] = [
612-
'type' => self::BREAKING_CHANGE_INTERFACE_REMOVED_FROM_OBJECT,
612+
'type' => self::BREAKING_CHANGE_IMPLEMENTED_INTERFACE_REMOVED,
613613
'description' => sprintf('%s no longer implements interface %s.', $typeName, $oldInterface->name),
614614
];
615615
}
@@ -877,7 +877,7 @@ static function (InterfaceType $interface) use ($newInterface) : bool {
877877
}
878878

879879
$interfacesAddedToObjectTypes[] = [
880-
'type' => self::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
880+
'type' => self::DANGEROUS_CHANGE_IMPLEMENTED_INTERFACE_ADDED,
881881
'description' => sprintf(
882882
'%s added to interfaces implemented by %s.',
883883
$newInterface->name,

tests/Executor/TestClasses/Cat.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,21 @@ class Cat
1212
/** @var bool */
1313
public $meows;
1414

15+
/** @var Cat|null */
16+
public $mother;
17+
18+
/** @var Cat|null */
19+
public $father;
20+
21+
/** @var Cat[] */
22+
public $progeny;
23+
1524
public function __construct(string $name, bool $meows)
1625
{
17-
$this->name = $name;
18-
$this->meows = $meows;
26+
$this->name = $name;
27+
$this->meows = $meows;
28+
$this->mother = NULL;
29+
$this->father = NULL;
30+
$this->progeny = [];
1931
}
2032
}

tests/Executor/TestClasses/Dog.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,21 @@ class Dog
1212
/** @var bool */
1313
public $woofs;
1414

15+
/** @var Dog|null */
16+
public $mother;
17+
18+
/** @var Dog|null */
19+
public $father;
20+
21+
/** @var Dog[] */
22+
public $progeny;
23+
1524
public function __construct(string $name, bool $woofs)
1625
{
17-
$this->name = $name;
18-
$this->woofs = $woofs;
26+
$this->name = $name;
27+
$this->woofs = $woofs;
28+
$this->mother = NULL;
29+
$this->father = NULL;
30+
$this->progeny = [];
1931
}
2032
}

tests/Executor/UnionInterfaceTest.php

Lines changed: 157 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,32 @@ public function setUp() : void
4646
],
4747
]);
4848

49+
$LifeType = new InterfaceType([
50+
'name' => 'Life',
51+
'fields' => [
52+
'progeny' => ['type' => Type::listOf($LifeType)],
53+
],
54+
]);
55+
56+
$MammalType = new InterfaceType([
57+
'name' => 'Mammal',
58+
'interfaces' => [$LifeType],
59+
'fields' => [
60+
'progeny' => ['type' => Type::listOf($MammalType)],
61+
'mother' => ['type' => $MammalType],
62+
'father' => ['type' => $MammalType],
63+
]
64+
]);
65+
4966
$DogType = new ObjectType([
5067
'name' => 'Dog',
51-
'interfaces' => [$NamedType],
68+
'interfaces' => [$MammalType, $LifeType, $NamedType],
5269
'fields' => [
53-
'name' => ['type' => Type::string()],
54-
'woofs' => ['type' => Type::boolean()],
70+
'name' => ['type' => Type::string()],
71+
'woofs' => ['type' => Type::boolean()],
72+
'progeny' => ['type' => Type::listOf($DogType)],
73+
'mother' => ['type' => $DogType],
74+
'father' => ['type' => $DogType],
5575
],
5676
'isTypeOf' => static function ($value) : bool {
5777
return $value instanceof Dog;
@@ -60,10 +80,13 @@ public function setUp() : void
6080

6181
$CatType = new ObjectType([
6282
'name' => 'Cat',
63-
'interfaces' => [$NamedType],
83+
'interfaces' => [$MammalType, $LifeType, $NamedType],
6484
'fields' => [
65-
'name' => ['type' => Type::string()],
66-
'meows' => ['type' => Type::boolean()],
85+
'name' => ['type' => Type::string()],
86+
'meows' => ['type' => Type::boolean()],
87+
'progeny' => ['type' => Type::listOf($CatType)],
88+
'mother' => ['type' => $CatType],
89+
'father' => ['type' => $CatType],
6790
],
6891
'isTypeOf' => static function ($value) : bool {
6992
return $value instanceof Cat;
@@ -87,11 +110,14 @@ public function setUp() : void
87110

88111
$PersonType = new ObjectType([
89112
'name' => 'Person',
90-
'interfaces' => [$NamedType],
113+
'interfaces' => [$NamedType, $MammalType, $LifeType],
91114
'fields' => [
92115
'name' => ['type' => Type::string()],
93116
'pets' => ['type' => Type::listOf($PetType)],
94117
'friends' => ['type' => Type::listOf($NamedType)],
118+
'progeny' => ['type' => Type::listOf($PersonType)],
119+
'mother' => ['type' => $PersonType],
120+
'father' => ['type' => $PersonType],
95121
],
96122
'isTypeOf' => static function ($value) : bool {
97123
return $value instanceof Person;
@@ -103,8 +129,14 @@ public function setUp() : void
103129
'types' => [$PetType],
104130
]);
105131

106-
$this->garfield = new Cat('Garfield', false);
107-
$this->odie = new Dog('Odie', true);
132+
$this->garfield = new Cat('Garfield', false);
133+
$this->garfield->mother = new Cat("Garfield's Mom", false);
134+
$this->garfield->mother->progeny = [$this->garfield];
135+
136+
$this->odie = new Dog('Odie', true);
137+
$this->odie->mother = new Dog("Odie's Mom", true);
138+
$this->odie->mother->progeny = [$this->odie];
139+
108140
$this->liz = new Person('Liz');
109141
$this->john = new Person('John', [$this->garfield, $this->odie], [$this->liz, $this->odie]);
110142
}
@@ -127,6 +159,15 @@ interfaces { name }
127159
enumValues { name }
128160
inputFields { name }
129161
}
162+
Mammal: __type(name: "Mammal") {
163+
kind
164+
name
165+
fields { name }
166+
interfaces { name }
167+
possibleTypes { name }
168+
enumValues { name }
169+
inputFields { name }
170+
}
130171
Pet: __type(name: "Pet") {
131172
kind
132173
name
@@ -156,6 +197,25 @@ enumValues { name }
156197
'enumValues' => null,
157198
'inputFields' => null,
158199
],
200+
'Mammal' => [
201+
'kind' => 'INTERFACE',
202+
'name' => 'Mammal',
203+
'fields' => [
204+
['name' => 'progeny'],
205+
['name' => 'mother'],
206+
['name' => 'father'],
207+
],
208+
'interfaces' => [
209+
['name' => 'Life']
210+
],
211+
'possibleTypes' => [
212+
['name' => 'Person'],
213+
['name' => 'Dog'],
214+
['name' => 'Cat'],
215+
],
216+
'enumValues' => null,
217+
'inputFields' => null,
218+
],
159219
'Pet' => [
160220
'kind' => 'UNION',
161221
'name' => 'Pet',
@@ -196,8 +256,16 @@ public function testExecutesUsingUnionTypes() : void
196256
'__typename' => 'Person',
197257
'name' => 'John',
198258
'pets' => [
199-
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
200-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
259+
[
260+
'__typename' => 'Cat',
261+
'name' => 'Garfield',
262+
'meows' => false
263+
],
264+
[
265+
'__typename' => 'Dog',
266+
'name' => 'Odie',
267+
'woofs' => true
268+
],
201269
],
202270
],
203271
];
@@ -233,8 +301,16 @@ public function testExecutesUnionTypesWithInlineFragments() : void
233301
'__typename' => 'Person',
234302
'name' => 'John',
235303
'pets' => [
236-
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
237-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
304+
[
305+
'__typename' => 'Cat',
306+
'name' => 'Garfield',
307+
'meows' => false
308+
],
309+
[
310+
'__typename' => 'Dog',
311+
'name' => 'Odie',
312+
'woofs' => true
313+
],
238314
],
239315

240316
],
@@ -293,6 +369,20 @@ public function testExecutesInterfaceTypesWithInlineFragments() : void
293369
... on Cat {
294370
meows
295371
}
372+
373+
... on Mammal {
374+
mother {
375+
__typename
376+
... on Dog {
377+
name
378+
barks
379+
}
380+
... on Cat {
381+
name
382+
meows
383+
}
384+
}
385+
}
296386
}
297387
}
298388
');
@@ -301,8 +391,21 @@ public function testExecutesInterfaceTypesWithInlineFragments() : void
301391
'__typename' => 'Person',
302392
'name' => 'John',
303393
'friends' => [
304-
['__typename' => 'Person', 'name' => 'Liz'],
305-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
394+
[
395+
'__typename' => 'Person',
396+
'name' => 'Liz',
397+
'mother' => null,
398+
],
399+
[
400+
'__typename' => 'Dog',
401+
'name' => 'Odie',
402+
'woofs' => true,
403+
'mother' => [
404+
'__typename' => 'Dog',
405+
'name' => "Odie's Mom",
406+
'barks' => true,
407+
],
408+
],
306409
],
307410
],
308411
];
@@ -319,7 +422,14 @@ public function testAllowsFragmentConditionsToBeAbstractTypes() : void
319422
{
320423
__typename
321424
name
322-
pets { ...PetFields }
425+
pets {
426+
...PetFields,
427+
...on Mammal {
428+
mother {
429+
...ProgenyFields
430+
}
431+
}
432+
}
323433
friends { ...FriendFields }
324434
}
325435
@@ -345,19 +455,46 @@ public function testAllowsFragmentConditionsToBeAbstractTypes() : void
345455
meows
346456
}
347457
}
458+
459+
fragment ProgenyFields on Life {
460+
progeny {
461+
__typename
462+
}
463+
}
348464
');
349465

350466
$expected = [
351467
'data' => [
352468
'__typename' => 'Person',
353469
'name' => 'John',
354470
'pets' => [
355-
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
356-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
471+
[
472+
'__typename' => 'Cat',
473+
'name' => 'Garfield',
474+
'meows' => false,
475+
'mother' => [
476+
'progeny' => ['__typename' => 'Cat'],
477+
],
478+
],
479+
[
480+
'__typename' => 'Dog',
481+
'name' => 'Odie',
482+
'woofs' => true,
483+
'mother' => [
484+
'progeny' => ['__typename' => 'Dog'],
485+
],
486+
],
357487
],
358488
'friends' => [
359-
['__typename' => 'Person', 'name' => 'Liz'],
360-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
489+
[
490+
'__typename' => 'Person',
491+
'name' => 'Liz'
492+
],
493+
[
494+
'__typename' => 'Dog',
495+
'name' => 'Odie',
496+
'woofs' => true
497+
],
361498
],
362499
],
363500
];

0 commit comments

Comments
 (0)