Skip to content

Commit 3137ed0

Browse files
authored
[GraphQL] Resource with no operation should be available through relations (#3532)
1 parent 52b771c commit 3137ed0

File tree

8 files changed

+57
-161
lines changed

8 files changed

+57
-161
lines changed

features/bootstrap/DoctrineContext.php

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeLabel;
7272
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositePrimitiveItem;
7373
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\CompositeRelation;
74-
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Container;
7574
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\ConvertedBoolean;
7675
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\ConvertedDate;
7776
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\ConvertedInteger;
@@ -107,7 +106,6 @@
107106
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Greeting;
108107
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\InternalUser;
109108
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\MaxDepthDummy;
110-
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Node;
111109
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Order;
112110
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Person;
113111
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\PersonToPet;
@@ -1051,25 +1049,6 @@ public function thereIsAnAnswerToTheQuestion(string $a, string $q)
10511049
$this->manager->clear();
10521050
}
10531051

1054-
/**
1055-
* @Given there are :nb nodes in a container :uuid
1056-
*/
1057-
public function thereAreNodesInAContainer(int $nb, string $uuid)
1058-
{
1059-
$container = new Container();
1060-
$container->setId($uuid);
1061-
$this->manager->persist($container);
1062-
1063-
for ($i = 0; $i < $nb; ++$i) {
1064-
$node = new Node();
1065-
$node->setContainer($container);
1066-
$node->setSerial($i);
1067-
$this->manager->persist($node);
1068-
}
1069-
1070-
$this->manager->flush();
1071-
}
1072-
10731052
/**
10741053
* @Then the password :password for user :user should be hashed
10751054
*/

features/graphql/introspection.feature

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ Feature: GraphQL introspection support
426426
And the JSON node "data.typeCreatePayloadData.fields[3].type.name" should be equal to "createDummyGroupNestedPayload"
427427
And the JSON node "data.typeCreateNestedPayload.fields[0].name" should be equal to "id"
428428

429-
Scenario: Retrieve an item through a GraphQL query
429+
Scenario: Retrieve a type name through a GraphQL query
430430
Given there are 4 dummy objects with relatedDummy
431431
When I send the following GraphQL request:
432432
"""
@@ -447,3 +447,28 @@ Feature: GraphQL introspection support
447447
And the JSON node "data.dummy.name" should be equal to "Dummy #3"
448448
And the JSON node "data.dummy.relatedDummy.name" should be equal to "RelatedDummy #3"
449449
And the JSON node "data.dummy.relatedDummy.__typename" should be equal to "RelatedDummy"
450+
451+
Scenario: Introspect a type available only through relations
452+
When I send the following GraphQL request:
453+
"""
454+
{
455+
typeNotAvailable: __type(name: "VoDummyInspectionConnection") {
456+
description
457+
}
458+
typeOwner: __type(name: "VoDummyCar") {
459+
description,
460+
fields {
461+
name
462+
type {
463+
name
464+
}
465+
}
466+
}
467+
}
468+
"""
469+
Then the response status code should be 200
470+
And the response should be in JSON
471+
And the header "Content-Type" should be equal to "application/json"
472+
And the JSON node "errors[0].debugMessage" should be equal to 'Type with id "VoDummyInspectionConnection" is not present in the types container'
473+
And the JSON node "data.typeNotAvailable" should be null
474+
And the JSON node "data.typeOwner.fields[3].type.name" should be equal to "VoDummyInspectionConnection"

src/GraphQl/Type/TypeConverter.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,12 @@ private function getResourceType(Type $type, bool $input, ?string $queryName, ?s
105105

106106
try {
107107
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
108-
if ([] === ($resourceMetadata->getGraphql() ?? [])) {
108+
if (null === $resourceMetadata->getGraphql()) {
109109
return null;
110110
}
111+
if ('Node' === $resourceMetadata->getShortName()) {
112+
throw new \UnexpectedValueException('A "Node" resource cannot be used with GraphQL because the type is already used by the Relay specification.');
113+
}
111114
} catch (ResourceClassNotFoundException $e) {
112115
// Skip objects that are not resources for now
113116
return null;

tests/Fixtures/TestBundle/Document/VoDummyInspection.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
use Symfony\Component\Serializer\Annotation\Groups;
2020

2121
/**
22-
* @ApiResource(attributes={
23-
* "normalization_context"={"groups"={"inspection_read"}},
24-
* "denormalization_context"={"groups"={"inspection_write"}}
25-
* })
22+
* @ApiResource(
23+
* attributes={
24+
* "normalization_context"={"groups"={"inspection_read"}},
25+
* "denormalization_context"={"groups"={"inspection_write"}}
26+
* },
27+
* graphql={}
28+
* )
2629
* @ODM\Document
2730
*/
2831
class VoDummyInspection

tests/Fixtures/TestBundle/Entity/Container.php

Lines changed: 0 additions & 68 deletions
This file was deleted.

tests/Fixtures/TestBundle/Entity/Node.php

Lines changed: 0 additions & 62 deletions
This file was deleted.

tests/Fixtures/TestBundle/Entity/VoDummyInspection.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
use Symfony\Component\Serializer\Annotation\Groups;
2020

2121
/**
22-
* @ApiResource(attributes={
23-
* "normalization_context"={"groups"={"inspection_read"}},
24-
* "denormalization_context"={"groups"={"inspection_write"}}
25-
* })
22+
* @ApiResource(
23+
* attributes={
24+
* "normalization_context"={"groups"={"inspection_read"}},
25+
* "denormalization_context"={"groups"={"inspection_write"}}
26+
* },
27+
* graphql={}
28+
* )
2629
* @ORM\Entity
2730
*/
2831
class VoDummyInspection

tests/GraphQl/Type/TypeConverterTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,19 @@ public function testConvertTypeNoGraphQlResourceMetadata(): void
9696
$this->assertNull($graphqlType);
9797
}
9898

99+
public function testConvertTypeNodeResource(): void
100+
{
101+
$type = new Type(Type::BUILTIN_TYPE_OBJECT, false, 'node');
102+
103+
$this->typeBuilderProphecy->isCollection($type)->shouldBeCalled()->willReturn(false);
104+
$this->resourceMetadataFactoryProphecy->create('node')->shouldBeCalled()->willReturn((new ResourceMetadata('Node'))->withGraphql(['test']));
105+
106+
$this->expectException(\UnexpectedValueException::class);
107+
$this->expectExceptionMessage('A "Node" resource cannot be used with GraphQL because the type is already used by the Relay specification.');
108+
109+
$this->typeConverter->convertType($type, false, null, null, 'resourceClass', 'rootClass', null, 0);
110+
}
111+
99112
public function testConvertTypeResourceClassNotFound(): void
100113
{
101114
$type = new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy');

0 commit comments

Comments
 (0)