From 4630af7f605407ff28d1762ec73f55e121c3e903 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Tue, 23 Feb 2021 16:36:05 +0100 Subject: [PATCH 1/3] fix: null iterable field should be resolved directly (#4092) --- CHANGELOG.md | 1 + features/graphql/query.feature | 17 +++++++ .../Resolver/Factory/ItemResolverFactory.php | 2 +- tests/Behat/DoctrineContext.php | 25 +++++++++++ .../TestBundle/Document/WithJsonDummy.php | 43 ++++++++++++++++++ .../TestBundle/Entity/WithJsonDummy.php | 45 +++++++++++++++++++ .../Factory/ItemResolverFactoryTest.php | 9 ++++ 7 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 tests/Fixtures/TestBundle/Document/WithJsonDummy.php create mode 100644 tests/Fixtures/TestBundle/Entity/WithJsonDummy.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ce9cb96450..cdaebd63f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * OpenAPI: Fix error when schema is empty (#4051) * OpenAPI: Do not set scheme to oauth2 when generating securitySchemes (#4073) * OpenAPI: Fix missing `$ref` when no `type` is used in context (#4076) +* GraphQL: Fix "Resource class cannot be determined." error when a null iterable field is returned (#4092) ## 2.6.2 diff --git a/features/graphql/query.feature b/features/graphql/query.feature index 149d39eaef1..fc8441da537 100644 --- a/features/graphql/query.feature +++ b/features/graphql/query.feature @@ -59,6 +59,23 @@ Feature: GraphQL query support And the JSON node "data.dummy.jsonData.bar" should be equal to 5 And the JSON node "data.dummy.arrayData[2]" should be equal to baz + Scenario: Retrieve an item with an iterable null field + Given there are 2 dummy with null JSON objects + When I send the following GraphQL request: + """ + { + withJsonDummy(id: "/with_json_dummies/2") { + id + json + } + } + """ + Then the response status code should be 200 + And the response should be in JSON + And the header "Content-Type" should be equal to "application/json" + And the JSON node "data.withJsonDummy.id" should be equal to "/with_json_dummies/2" + And the JSON node "data.withJsonDummy.json" should be null + Scenario: Retrieve an item through a GraphQL query with variables When I have the following GraphQL request: """ diff --git a/src/GraphQl/Resolver/Factory/ItemResolverFactory.php b/src/GraphQl/Resolver/Factory/ItemResolverFactory.php index 1b257b94f69..f96794dd964 100644 --- a/src/GraphQl/Resolver/Factory/ItemResolverFactory.php +++ b/src/GraphQl/Resolver/Factory/ItemResolverFactory.php @@ -59,7 +59,7 @@ public function __invoke(?string $resourceClass = null, ?string $rootClass = nul { return function (?array $source, array $args, $context, ResolveInfo $info) use ($resourceClass, $rootClass, $operationName) { // Data already fetched and normalized (field or nested resource) - if (isset($source[$info->fieldName])) { + if ($source && \array_key_exists($info->fieldName, $source)) { return $source[$info->fieldName]; } diff --git a/tests/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php index a62255ed6b5..bbbc943c763 100644 --- a/tests/Behat/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -80,6 +80,7 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\ThirdLevel as ThirdLevelDocument; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\UrlEncodedId as UrlEncodedIdDocument; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\User as UserDocument; +use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\WithJsonDummy as WithJsonDummyDocument; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\AbsoluteUrlDummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\AbsoluteUrlRelationDummy; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Address; @@ -154,6 +155,7 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UrlEncodedId; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\User; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UuidIdentifierDummy; +use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\WithJsonDummy; use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; use Doctrine\ODM\MongoDB\DocumentManager; @@ -573,6 +575,21 @@ public function thereAreDummyObjectsWithJsonData(int $nb) $this->manager->flush(); } + /** + * @Given there are :nb dummy with null JSON objects + */ + public function thereAreDummyWithNullJsonObjects(int $nb) + { + for ($i = 1; $i <= $nb; ++$i) { + $dummy = $this->buildWithJsonDummy(); + $dummy->json = null; + + $this->manager->persist($dummy); + } + + $this->manager->flush(); + } + /** * @Given there are :nb dummy objects with relatedDummy and its thirdLevel * @Given there is :nb dummy object with relatedDummy and its thirdLevel @@ -2190,4 +2207,12 @@ private function buildCustomMultipleIdentifierDummy() { return $this->isOrm() ? new CustomMultipleIdentifierDummy() : new CustomMultipleIdentifierDummyDocument(); } + + /** + * @return WithJsonDummy|WithJsonDummyDocument + */ + private function buildWithJsonDummy() + { + return $this->isOrm() ? new WithJsonDummy() : new WithJsonDummyDocument(); + } } diff --git a/tests/Fixtures/TestBundle/Document/WithJsonDummy.php b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php new file mode 100644 index 00000000000..a0a82da40b8 --- /dev/null +++ b/tests/Fixtures/TestBundle/Document/WithJsonDummy.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Core\Tests\Fixtures\TestBundle\Document; + +use ApiPlatform\Core\Annotation\ApiResource; +use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; + +/** + * @ApiResource + * @ODM\Document + */ +class WithJsonDummy +{ + /** + * @var int + * + * @ODM\Id(strategy="INCREMENT", type="int", nullable=true) + */ + private $id; + + /** + * @var array|null + * + * @ODM\Field(type="hash", nullable=true) + */ + public $json; + + public function getId(): int + { + return $this->id; + } +} diff --git a/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php new file mode 100644 index 00000000000..a2769c87c1f --- /dev/null +++ b/tests/Fixtures/TestBundle/Entity/WithJsonDummy.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity; + +use ApiPlatform\Core\Annotation\ApiResource; +use Doctrine\ORM\Mapping as ORM; + +/** + * @ApiResource + * @ORM\Entity + */ +class WithJsonDummy +{ + /** + * @var int + * + * @ORM\Column(type="integer", nullable=true) + * @ORM\Id + * @ORM\GeneratedValue(strategy="AUTO") + */ + private $id; + + /** + * @var array|null + * + * @ORM\Column(type="json", nullable=true) + */ + public $json; + + public function getId(): int + { + return $this->id; + } +} diff --git a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php index 69cc1b31576..06d2c66f627 100644 --- a/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php +++ b/tests/GraphQl/Resolver/Factory/ItemResolverFactoryTest.php @@ -118,6 +118,15 @@ public function testResolveNested(): void $this->assertSame(['already_serialized'], ($this->itemResolverFactory)('resourceClass')($source, [], null, $info)); } + public function testResolveNestedNullValue(): void + { + $source = ['nestedNullValue' => null]; + $info = $this->prophesize(ResolveInfo::class)->reveal(); + $info->fieldName = 'nestedNullValue'; + + $this->assertNull(($this->itemResolverFactory)('resourceClass')($source, [], null, $info)); + } + public function testResolveBadReadStageItem(): void { $resourceClass = 'stdClass'; From 0037f60a98904f0e6d543602034c81b929a7e48e Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Mon, 1 Mar 2021 16:23:36 +0100 Subject: [PATCH 2/3] Add back PHPUnit tests with MongoDB (#4104) --- .gitattributes | 1 - .github/workflows/ci.yml | 8 +- phpunit.xml.dist | 2 +- phpunit_mongodb.xml | 41 ------ .../MongoDbOdm/Filter/SearchFilterTest.php | 120 ++++++++++++++++++ .../PropertyInfo/DoctrineExtractorTest.php | 4 - .../PropertyInfo/Fixtures/DoctrineDummy.php | 10 -- .../Fixtures/DoctrineGeneratedValue.php | 2 +- .../SubresourceDataProviderTest.php | 17 +-- 9 files changed, 131 insertions(+), 74 deletions(-) delete mode 100644 phpunit_mongodb.xml diff --git a/.gitattributes b/.gitattributes index 0939daedba5..1bc7f690e59 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,7 +8,6 @@ /features export-ignore /phpstan.neon.dist export-ignore /phpunit.xml.dist export-ignore -/phpunit_mongodb.xml export-ignore /tests export-ignore /update-js.sh export-ignore /yarn.lock export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index faccaa57ed5..3d6fa355767 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -485,7 +485,7 @@ jobs: run: vendor/bin/behat --out=std --format=progress --profile=default --no-interaction mongodb: - name: Behat (PHP ${{ matrix.php }}) (MongoDB) + name: PHPUnit + Behat (PHP ${{ matrix.php }}) (MongoDB) runs-on: ubuntu-latest timeout-minutes: 20 strategy: @@ -529,8 +529,8 @@ jobs: run: vendor/bin/simple-phpunit --version - name: Clear test app cache run: tests/Fixtures/app/console cache:clear --ansi - - name: Run PHPUnit - run: vendor/bin/simple-phpunit + - name: Run PHPUnit tests + run: vendor/bin/simple-phpunit --group mongodb - name: Run Behat tests run: vendor/bin/behat -vv --out=std --format=progress --profile=mongodb --no-interaction @@ -585,8 +585,6 @@ jobs: run: vendor/bin/simple-phpunit --version - name: Clear test app cache run: tests/Fixtures/app/console cache:clear --ansi - - name: Run PHPUnit tests - run: vendor/bin/simple-phpunit - name: Run Behat tests run: vendor/bin/behat --out=std --format=progress --profile=elasticsearch --no-interaction diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4518373e404..7b52597293e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,7 +16,7 @@ - + diff --git a/phpunit_mongodb.xml b/phpunit_mongodb.xml deleted file mode 100644 index 0ef9e7e4d5b..00000000000 --- a/phpunit_mongodb.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - tests - - - - - - . - - features - tests - vendor - src/Bridge/NelmioApiDoc - src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php - - - - - - - - diff --git a/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php b/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php index 0f1f163cc6c..b090f818409 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/Filter/SearchFilterTest.php @@ -395,6 +395,36 @@ public function provideApplyTestData(): array ], $filterFactory, ], + 'partial (multiple values)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('CaSE'), + new Regex('SENSitive'), + ], + ], + ], + ], + ], + $filterFactory, + ], + 'partial (multiple values; case insensitive)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('CaSE', 'i'), + new Regex('inSENSitive', 'i'), + ], + ], + ], + ], + ], + $filterFactory, + ], 'start' => [ [ [ @@ -423,6 +453,36 @@ public function provideApplyTestData(): array ], $filterFactory, ], + 'start (multiple values)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('^CaSE'), + new Regex('^SENSitive'), + ], + ], + ], + ], + ], + $filterFactory, + ], + 'start (multiple values; case insensitive)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('^CaSE', 'i'), + new Regex('^inSENSitive', 'i'), + ], + ], + ], + ], + ], + $filterFactory, + ], 'end' => [ [ [ @@ -451,6 +511,36 @@ public function provideApplyTestData(): array ], $filterFactory, ], + 'end (multiple values)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('CaSE$'), + new Regex('SENSitive$'), + ], + ], + ], + ], + ], + $filterFactory, + ], + 'end (multiple values; case insensitive)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('CaSE$', 'i'), + new Regex('inSENSitive$', 'i'), + ], + ], + ], + ], + ], + $filterFactory, + ], 'word_start' => [ [ [ @@ -479,6 +569,36 @@ public function provideApplyTestData(): array ], $filterFactory, ], + 'word_start (multiple values)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('(^CaSE.*|.*\sCaSE.*)'), + new Regex('(^SENSitive.*|.*\sSENSitive.*)'), + ], + ], + ], + ], + ], + $filterFactory, + ], + 'word_start (multiple values; case insensitive)' => [ + [ + [ + '$match' => [ + 'name' => [ + '$in' => [ + new Regex('(^CaSE.*|.*\sCaSE.*)', 'i'), + new Regex('(^inSENSitive.*|.*\sinSENSitive.*)', 'i'), + ], + ], + ], + ], + ], + $filterFactory, + ], 'invalid value for relation' => [ [], $filterFactory, diff --git a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php index 36505c4dc9c..20b864155ea 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/DoctrineExtractorTest.php @@ -54,10 +54,8 @@ public function testGetProperties(): void 'date', 'float', 'bool', - 'boolean', 'customFoo', 'int', - 'integer', 'string', 'key', 'hash', @@ -143,9 +141,7 @@ public function typesProvider(): array ['date', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime')]], ['float', [new Type(Type::BUILTIN_TYPE_FLOAT)]], ['bool', [new Type(Type::BUILTIN_TYPE_BOOL)]], - ['boolean', [new Type(Type::BUILTIN_TYPE_BOOL)]], ['int', [new Type(Type::BUILTIN_TYPE_INT)]], - ['integer', [new Type(Type::BUILTIN_TYPE_INT)]], ['string', [new Type(Type::BUILTIN_TYPE_STRING)]], ['key', [new Type(Type::BUILTIN_TYPE_INT)]], ['hash', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]], diff --git a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php index 64a34ed4f65..053bf0e7357 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineDummy.php @@ -101,11 +101,6 @@ class DoctrineDummy */ private $bool; - /** - * @Field(type="boolean") - */ - private $boolean; - /** * @Field(type="custom_foo") */ @@ -116,11 +111,6 @@ class DoctrineDummy */ private $int; - /** - * @Field(type="integer") - */ - private $integer; - /** * @Field(type="string") */ diff --git a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php index 46ece808957..e286195a2b3 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/PropertyInfo/Fixtures/DoctrineGeneratedValue.php @@ -26,7 +26,7 @@ class DoctrineGeneratedValue { /** - * @Id(strategy="INCREMENT", type="integer") + * @Id(strategy="INCREMENT", type="int") */ public $id; diff --git a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php index 0130565ffcc..879a630431c 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/SubresourceDataProviderTest.php @@ -167,7 +167,7 @@ public function testGetSubresource() $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $context = ['property' => 'relatedDummies', 'identifiers' => [['id', Dummy::class]], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; + $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); } @@ -256,7 +256,7 @@ public function testGetSubSubresourceItem() $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $context = ['property' => 'thirdLevel', 'identifiers' => [['id', Dummy::class], ['relatedDummies', RelatedDummy::class]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; + $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context)); } @@ -353,7 +353,7 @@ public function testGetSubSubresourceItemWithExecuteOptions() $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $context = ['property' => 'thirdLevel', 'identifiers' => [['id', Dummy::class], ['relatedDummies', RelatedDummy::class]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; + $context = ['property' => 'thirdLevel', 'identifiers' => ['id' => [Dummy::class, 'id'], 'relatedDummies' => [RelatedDummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; $this->assertEquals($result, $dataProvider->getSubresource(ThirdLevel::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 1]], $context, 'third_level_operation_name')); } @@ -405,7 +405,7 @@ public function testGetSubresourceOneToOneOwningRelation() $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $context = ['property' => 'ownedDummy', 'identifiers' => [['id', Dummy::class]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; + $context = ['property' => 'ownedDummy', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; $this->assertEquals($result, $dataProvider->getSubresource(RelatedOwningDummy::class, ['id' => ['id' => 1]], $context)); } @@ -458,7 +458,7 @@ public function testAggregationResultExtension() $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); - $context = ['property' => 'relatedDummies', 'identifiers' => [['id', Dummy::class]], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; + $context = ['property' => 'relatedDummies', 'identifiers' => ['id' => [Dummy::class, 'id']], 'collection' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; $this->assertEquals([], $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1]], $context)); } @@ -504,11 +504,6 @@ public function testGetSubresourceCollectionItem() $rAggregationBuilder = $this->prophesize(Builder::class); - $rMatch = $this->prophesize(AggregationMatch::class); - $rMatch->equals(2)->shouldBeCalled(); - $rMatch->field('id')->shouldBeCalled()->willReturn($rMatch); - $rAggregationBuilder->match()->shouldBeCalled()->willReturn($rMatch->reveal()); - $rClassMetadataProphecy = $this->prophesize(ClassMetadata::class); $rClassMetadataProphecy->hasAssociation('id')->shouldBeCalled()->willReturn(false); $rClassMetadataProphecy->isIdentifier('id')->shouldBeCalled()->willReturn(true); @@ -539,7 +534,7 @@ public function testGetSubresourceCollectionItem() $dataProvider = new SubresourceDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); - $context = ['property' => 'id', 'identifiers' => [['id', Dummy::class, true], ['relatedDummies', RelatedDummy::class, true]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; + $context = ['property' => 'id', 'identifiers' => ['id' => [Dummy::class, 'id', true], [RelatedDummy::class, 'relatedDummies', true]], 'collection' => false, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; $this->assertEquals($result, $dataProvider->getSubresource(RelatedDummy::class, ['id' => ['id' => 1], 'relatedDummies' => ['id' => 2]], $context)); } From aa61122cccd0072386f919751a96520285fe3892 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Mon, 1 Mar 2021 16:39:22 +0100 Subject: [PATCH 3/3] fix: unit tests for MongoDB --- .../MongoDbOdm/ItemDataProviderTest.php | 49 +++++++------------ 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php index b38d3cd1073..8bce94b8b21 100644 --- a/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php +++ b/tests/Bridge/Doctrine/MongoDbOdm/ItemDataProviderTest.php @@ -47,18 +47,6 @@ class ItemDataProviderTest extends TestCase { use ProphecyTrait; - private $resourceMetadataFactoryProphecy; - - /** - * {@inheritdoc} - */ - protected function setUp(): void - { - parent::setUp(); - - $this->resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - } - public function testGetItemSingleIdentifier() { $context = ['foo' => 'bar', 'fetch_data' => true, IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; @@ -77,17 +65,15 @@ public function testGetItemSingleIdentifier() $aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled(); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ + [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ 'id', ]); $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); } @@ -115,7 +101,8 @@ public function testGetItemWithExecuteOptions() ]); $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata( + $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactory->create(Dummy::class)->willReturn(new ResourceMetadata( 'Dummy', null, null, @@ -125,7 +112,7 @@ public function testGetItemWithExecuteOptions() $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); } @@ -148,19 +135,17 @@ public function testGetItemDoubleIdentifier() $aggregationBuilderProphecy->execute([])->willReturn($iterator->reveal())->shouldBeCalled(); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ + [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ 'ida', 'idb', ]); $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); - $this->resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $context = [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]; $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); $extensionProphecy->applyToItem($aggregationBuilder, Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)->shouldBeCalled(); - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertEquals($result, $dataProvider->getItem(Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', $context)); } @@ -172,7 +157,7 @@ public function testGetItemWrongCompositeIdentifier() { $this->expectException(PropertyNotFoundException::class); - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ + [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ 'ida', 'idb', ]); @@ -185,7 +170,7 @@ public function testGetItemWrongCompositeIdentifier() ], ]); - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory); + $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory); $dataProvider->getItem(Dummy::class, 'ida=1;', 'foo'); } @@ -199,7 +184,7 @@ public function testAggregationResultExtension() $aggregationBuilderProphecy->match()->willReturn($matchProphecy->reveal())->shouldBeCalled(); $aggregationBuilder = $aggregationBuilderProphecy->reveal(); - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ + [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ 'id', ]); $managerRegistry = $this->getManagerRegistry(Dummy::class, $aggregationBuilder); @@ -210,7 +195,7 @@ public function testAggregationResultExtension() $extensionProphecy->supportsResult(Dummy::class, 'foo', $context)->willReturn(true)->shouldBeCalled(); $extensionProphecy->getResult($aggregationBuilder, Dummy::class, 'foo', $context)->willReturn([])->shouldBeCalled(); - $dataProvider = new ItemDataProvider($managerRegistry, $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistry, $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->getItem(Dummy::class, ['id' => 1], 'foo', $context)); } @@ -222,11 +207,11 @@ public function testUnsupportedClass() $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ + [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ 'id', ]); - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertFalse($dataProvider->supports(Dummy::class, 'foo')); } @@ -245,11 +230,11 @@ public function testCannotCreateAggregationBuilder() $extensionProphecy = $this->prophesize(AggregationItemExtensionInterface::class); - [$propertyNameCollectionFactory, $propertyMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ + [$propertyNameCollectionFactory, $propertyMetadataFactory, $resourceMetadataFactory] = $this->getMetadataFactories(Dummy::class, [ 'id', ]); - (new ItemDataProvider($managerRegistryProphecy->reveal(), $this->resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo', null, [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]); + (new ItemDataProvider($managerRegistryProphecy->reveal(), $resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo', null, [IdentifierConverterInterface::HAS_IDENTIFIER_CONVERTER => true]); } /** @@ -259,6 +244,7 @@ private function getMetadataFactories(string $resourceClass, array $identifiers) { $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $nameCollection = ['foobar']; @@ -274,8 +260,9 @@ private function getMetadataFactories(string $resourceClass, array $identifiers) $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); + $resourceMetadataFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadata('dummy')); - return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; + return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()]; } /**