Skip to content

Commit 6360356

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 aa4f719 commit 6360356

16 files changed

+1420
-75
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
}
@@ -878,7 +878,7 @@ static function (InterfaceType $interface) use ($newInterface) : bool {
878878
}
879879

880880
$interfacesAddedToObjectTypes[] = [
881-
'type' => self::DANGEROUS_CHANGE_INTERFACE_ADDED_TO_OBJECT,
881+
'type' => self::DANGEROUS_CHANGE_IMPLEMENTED_INTERFACE_ADDED,
882882
'description' => sprintf(
883883
'%s added to interfaces implemented by %s.',
884884
$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: 165 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@
88
use GraphQL\Error\InvariantViolation;
99
use GraphQL\Executor\Executor;
1010
use GraphQL\GraphQL;
11+
use GraphQL\Language\AST\FieldDefinitionNode;
12+
use GraphQL\Language\AST\FieldNode;
13+
use GraphQL\Language\AST\NodeList;
1114
use GraphQL\Language\Parser;
1215
use GraphQL\Tests\Executor\TestClasses\Cat;
1316
use GraphQL\Tests\Executor\TestClasses\Dog;
1417
use GraphQL\Tests\Executor\TestClasses\Person;
1518
use GraphQL\Type\Definition\InterfaceType;
19+
use GraphQL\Type\Definition\ListOfType;
1620
use GraphQL\Type\Definition\ObjectType;
1721
use GraphQL\Type\Definition\ResolveInfo;
1822
use GraphQL\Type\Definition\Type;
@@ -46,12 +50,32 @@ public function setUp() : void
4650
],
4751
]);
4852

53+
$LifeType = new InterfaceType([
54+
'name' => 'Life',
55+
'fields' => [
56+
'progeny' => ['type' => new ListOfType(function () use (&$LifeType) { return $LifeType; })],
57+
],
58+
]);
59+
60+
$MammalType = new InterfaceType([
61+
'name' => 'Mammal',
62+
'interfaces' => [$LifeType],
63+
'fields' => [
64+
'progeny' => ['type' => new ListOfType(function () use (&$MammalType) { return $MammalType; })],
65+
'mother' => ['type' => &$MammalType],
66+
'father' => ['type' => &$MammalType],
67+
]
68+
]);
69+
4970
$DogType = new ObjectType([
5071
'name' => 'Dog',
51-
'interfaces' => [$NamedType],
72+
'interfaces' => [$MammalType, $LifeType, $NamedType],
5273
'fields' => [
53-
'name' => ['type' => Type::string()],
54-
'woofs' => ['type' => Type::boolean()],
74+
'name' => ['type' => Type::string()],
75+
'woofs' => ['type' => Type::boolean()],
76+
'progeny' => ['type' => new ListOfType(function () use (&$DogType) {return $DogType; })],
77+
'mother' => ['type' => &$DogType],
78+
'father' => ['type' => &$DogType],
5579
],
5680
'isTypeOf' => static function ($value) : bool {
5781
return $value instanceof Dog;
@@ -60,10 +84,13 @@ public function setUp() : void
6084

6185
$CatType = new ObjectType([
6286
'name' => 'Cat',
63-
'interfaces' => [$NamedType],
87+
'interfaces' => [$MammalType, $LifeType, $NamedType],
6488
'fields' => [
65-
'name' => ['type' => Type::string()],
66-
'meows' => ['type' => Type::boolean()],
89+
'name' => ['type' => Type::string()],
90+
'meows' => ['type' => Type::boolean()],
91+
'progeny' => ['type' => new ListOfType(function () use (&$CatType) { return $CatType; })],
92+
'mother' => ['type' => &$CatType],
93+
'father' => ['type' => &$CatType],
6794
],
6895
'isTypeOf' => static function ($value) : bool {
6996
return $value instanceof Cat;
@@ -87,11 +114,14 @@ public function setUp() : void
87114

88115
$PersonType = new ObjectType([
89116
'name' => 'Person',
90-
'interfaces' => [$NamedType],
117+
'interfaces' => [$NamedType, $MammalType, $LifeType],
91118
'fields' => [
92119
'name' => ['type' => Type::string()],
93120
'pets' => ['type' => Type::listOf($PetType)],
94121
'friends' => ['type' => Type::listOf($NamedType)],
122+
'progeny' => ['type' => new ListOfType(function () use (&$PersonType) { return $PersonType; })],
123+
'mother' => ['type' => &$PersonType],
124+
'father' => ['type' => &$PersonType],
95125
],
96126
'isTypeOf' => static function ($value) : bool {
97127
return $value instanceof Person;
@@ -103,8 +133,14 @@ public function setUp() : void
103133
'types' => [$PetType],
104134
]);
105135

106-
$this->garfield = new Cat('Garfield', false);
107-
$this->odie = new Dog('Odie', true);
136+
$this->garfield = new Cat('Garfield', false);
137+
$this->garfield->mother = new Cat("Garfield's Mom", false);
138+
$this->garfield->mother->progeny = [$this->garfield];
139+
140+
$this->odie = new Dog('Odie', true);
141+
$this->odie->mother = new Dog("Odie's Mom", true);
142+
$this->odie->mother->progeny = [$this->odie];
143+
108144
$this->liz = new Person('Liz');
109145
$this->john = new Person('John', [$this->garfield, $this->odie], [$this->liz, $this->odie]);
110146
}
@@ -127,6 +163,15 @@ interfaces { name }
127163
enumValues { name }
128164
inputFields { name }
129165
}
166+
Mammal: __type(name: "Mammal") {
167+
kind
168+
name
169+
fields { name }
170+
interfaces { name }
171+
possibleTypes { name }
172+
enumValues { name }
173+
inputFields { name }
174+
}
130175
Pet: __type(name: "Pet") {
131176
kind
132177
name
@@ -156,6 +201,25 @@ enumValues { name }
156201
'enumValues' => null,
157202
'inputFields' => null,
158203
],
204+
'Mammal' => [
205+
'kind' => 'INTERFACE',
206+
'name' => 'Mammal',
207+
'fields' => [
208+
['name' => 'progeny'],
209+
['name' => 'mother'],
210+
['name' => 'father'],
211+
],
212+
'interfaces' => [
213+
['name' => 'Life']
214+
],
215+
'possibleTypes' => [
216+
['name' => 'Person'],
217+
['name' => 'Dog'],
218+
['name' => 'Cat'],
219+
],
220+
'enumValues' => null,
221+
'inputFields' => null,
222+
],
159223
'Pet' => [
160224
'kind' => 'UNION',
161225
'name' => 'Pet',
@@ -196,8 +260,16 @@ public function testExecutesUsingUnionTypes() : void
196260
'__typename' => 'Person',
197261
'name' => 'John',
198262
'pets' => [
199-
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
200-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
263+
[
264+
'__typename' => 'Cat',
265+
'name' => 'Garfield',
266+
'meows' => false
267+
],
268+
[
269+
'__typename' => 'Dog',
270+
'name' => 'Odie',
271+
'woofs' => true
272+
],
201273
],
202274
],
203275
];
@@ -233,8 +305,16 @@ public function testExecutesUnionTypesWithInlineFragments() : void
233305
'__typename' => 'Person',
234306
'name' => 'John',
235307
'pets' => [
236-
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
237-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
308+
[
309+
'__typename' => 'Cat',
310+
'name' => 'Garfield',
311+
'meows' => false
312+
],
313+
[
314+
'__typename' => 'Dog',
315+
'name' => 'Odie',
316+
'woofs' => true
317+
],
238318
],
239319

240320
],
@@ -293,6 +373,20 @@ public function testExecutesInterfaceTypesWithInlineFragments() : void
293373
... on Cat {
294374
meows
295375
}
376+
377+
... on Mammal {
378+
mother {
379+
__typename
380+
... on Dog {
381+
name
382+
woofs
383+
}
384+
... on Cat {
385+
name
386+
meows
387+
}
388+
}
389+
}
296390
}
297391
}
298392
');
@@ -301,8 +395,21 @@ public function testExecutesInterfaceTypesWithInlineFragments() : void
301395
'__typename' => 'Person',
302396
'name' => 'John',
303397
'friends' => [
304-
['__typename' => 'Person', 'name' => 'Liz'],
305-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
398+
[
399+
'__typename' => 'Person',
400+
'name' => 'Liz',
401+
'mother' => null,
402+
],
403+
[
404+
'__typename' => 'Dog',
405+
'name' => 'Odie',
406+
'woofs' => true,
407+
'mother' => [
408+
'__typename' => 'Dog',
409+
'name' => "Odie's Mom",
410+
'woofs' => true,
411+
],
412+
],
306413
],
307414
],
308415
];
@@ -319,7 +426,14 @@ public function testAllowsFragmentConditionsToBeAbstractTypes() : void
319426
{
320427
__typename
321428
name
322-
pets { ...PetFields }
429+
pets {
430+
...PetFields,
431+
...on Mammal {
432+
mother {
433+
...ProgenyFields
434+
}
435+
}
436+
}
323437
friends { ...FriendFields }
324438
}
325439
@@ -345,19 +459,50 @@ public function testAllowsFragmentConditionsToBeAbstractTypes() : void
345459
meows
346460
}
347461
}
462+
463+
fragment ProgenyFields on Life {
464+
progeny {
465+
__typename
466+
}
467+
}
348468
');
349469

350470
$expected = [
351471
'data' => [
352472
'__typename' => 'Person',
353473
'name' => 'John',
354474
'pets' => [
355-
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
356-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
475+
[
476+
'__typename' => 'Cat',
477+
'name' => 'Garfield',
478+
'meows' => false,
479+
'mother' => [
480+
'progeny' => [
481+
['__typename' => 'Cat'],
482+
],
483+
],
484+
],
485+
[
486+
'__typename' => 'Dog',
487+
'name' => 'Odie',
488+
'woofs' => true,
489+
'mother' => [
490+
'progeny' => [
491+
['__typename' => 'Dog'],
492+
],
493+
],
494+
],
357495
],
358496
'friends' => [
359-
['__typename' => 'Person', 'name' => 'Liz'],
360-
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true],
497+
[
498+
'__typename' => 'Person',
499+
'name' => 'Liz'
500+
],
501+
[
502+
'__typename' => 'Dog',
503+
'name' => 'Odie',
504+
'woofs' => true
505+
],
361506
],
362507
],
363508
];

0 commit comments

Comments
 (0)