From 511e7b72f007eb8b412ff98fe49e95c76d95b9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 26 Oct 2020 17:58:35 +0100 Subject: [PATCH 01/27] ci: remove deprecated packages from composer.json --- composer.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index c459bf72afa..ef3838de558 100644 --- a/composer.json +++ b/composer.json @@ -42,13 +42,11 @@ "doctrine/mongodb-odm-bundle": "^4.0", "doctrine/orm": "^2.6.4", "elasticsearch/elasticsearch": "^6.0", - "friendsofsymfony/user-bundle": "2.2.x-dev#157b53bd7d6c347148a90e723981a43f9c897bf5", "guzzlehttp/guzzle": "^6.0", "jangregor/phpstan-prophecy": "^0.6", "justinrainbow/json-schema": "^5.2.1", - "nelmio/api-doc-bundle": "^2.13.4", - "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.0", - "phpdocumentor/type-resolver": "^0.3 || ^0.4 || ^1.0", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0", + "phpdocumentor/type-resolver": "^0.3 || ^0.4", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^0.12.4", "phpstan/phpstan-doctrine": "^0.12.7", From 8b8b7609dc2982e3b52e792984c4617acacd1398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 26 Oct 2020 18:39:22 +0100 Subject: [PATCH 02/27] fix: bump many deps versions --- composer.json | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index ef3838de558..a4bd9e20a70 100644 --- a/composer.json +++ b/composer.json @@ -31,29 +31,28 @@ "behat/mink": "^1.7", "friends-of-behat/mink-browserkit-driver": "^1.3.1", "friends-of-behat/mink-extension": "^2.2", - "behat/symfony2-extension": "^2.1.1", + "friends-of-behat/symfony-extension": "^2.1", "behatch/contexts": "dev-fix/symfony-33393", "doctrine/annotations": "^1.7", - "doctrine/common": "^2.11", + "doctrine/common": "^2.11 || ^3.0", "doctrine/data-fixtures": "^1.2.2", "doctrine/doctrine-bundle": "^1.8 || ^2.0", - "doctrine/doctrine-cache-bundle": "^1.3.5", "doctrine/mongodb-odm": "^2.0", "doctrine/mongodb-odm-bundle": "^4.0", - "doctrine/orm": "^2.6.4", - "elasticsearch/elasticsearch": "^6.0", - "guzzlehttp/guzzle": "^6.0", - "jangregor/phpstan-prophecy": "^0.6", + "doctrine/orm": "^2.6.4 || ^3.0", + "elasticsearch/elasticsearch": "^6.0 || ^7.0", + "guzzlehttp/guzzle": "^6.0 || ^7.0", + "jangregor/phpstan-prophecy": "^0.8", "justinrainbow/json-schema": "^5.2.1", - "phpdocumentor/reflection-docblock": "^3.0 || ^4.0", - "phpdocumentor/type-resolver": "^0.3 || ^0.4", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.0", + "phpdocumentor/type-resolver": "^0.3 || ^0.4 || ^1.4", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^0.12.4", "phpstan/phpstan-doctrine": "^0.12.7", "phpstan/phpstan-phpunit": "^0.12.4", "phpstan/phpstan-symfony": "^0.12.4", "psr/log": "^1.0", - "ramsey/uuid": "^3.7", + "ramsey/uuid": "^3.7 || ^4.0", "ramsey/uuid-doctrine": "^1.4", "symfony/asset": "^3.4 || ^4.0 || ^5.0", "symfony/browser-kit": "^4.3 || ^5.0", @@ -61,7 +60,7 @@ "symfony/config": "^3.4 || ^4.0 || ^5.0", "symfony/console": "^3.4 || ^4.0 || ^5.0", "symfony/css-selector": "^3.4 || ^4.0 || ^5.0", - "symfony/debug": "^3.4 || ^4.0", + "symfony/debug": "^3.4 || ^4.0 || ^5.0", "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0", "symfony/doctrine-bridge": "^3.4 || ^4.0 || ^5.0", "symfony/dom-crawler": "^3.4 || ^4.0 || ^5.0", @@ -82,7 +81,7 @@ "symfony/web-profiler-bundle": "^4.2 || ^5.0", "symfony/yaml": "^3.4 || ^4.0 || ^5.0", "teohhanhui/stubs-mongodb": "@dev", - "twig/twig": "^1.42.3 || ^2.12", + "twig/twig": "^1.42.3 || ^2.12 || ^3.0", "webonyx/graphql-php": "^14.0" }, "conflict": { From e24fd4fb5a3b57d1b62c9083d52a9124d7cc9d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 26 Oct 2020 18:55:17 +0100 Subject: [PATCH 03/27] tmp --- .../Bundle/DependencyInjection/Configuration.php | 6 +++++- .../Doctrine/EventListener/WriteListenerTest.php | 7 ++----- .../ApiPlatformExtensionTest.php | 7 +++++++ .../DependencyInjection/ConfigurationTest.php | 2 +- tests/Fixtures/app/AppKernel.php | 11 +++++++---- tests/Fixtures/app/config/config_common.yml | 1 - tests/Fixtures/app/config/config_test.yml | 15 ++++++++------- 7 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php index b07b99e2b51..45ace3866b1 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php @@ -107,7 +107,11 @@ public function getConfigTreeBuilder() ->booleanNode('force_eager')->defaultTrue()->info('Force join on every relation. If disabled, it will only join relations having the EAGER fetch mode.')->end() ->end() ->end() - ->booleanNode('enable_fos_user')->defaultValue(class_exists(FOSUserBundle::class))->info('Enable the FOSUserBundle integration.')->end() + ->booleanNode('enable_fos_user') + ->defaultValue(class_exists(FOSUserBundle::class)) + ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'FOSUser is not actively maintained anymore. Enabling the NelmioApiDocBundle integration has been deprecated in 2.5 and will be removed in 3.0.')) + ->info('Enable the FOSUserBundle integration.') + ->end() ->booleanNode('enable_nelmio_api_doc') ->defaultFalse() ->setDeprecated(...$this->buildDeprecationArgs('2.2', 'Enabling the NelmioApiDocBundle integration has been deprecated in 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.')) diff --git a/tests/Bridge/Doctrine/EventListener/WriteListenerTest.php b/tests/Bridge/Doctrine/EventListener/WriteListenerTest.php index 393724e5a72..3507d91e1be 100644 --- a/tests/Bridge/Doctrine/EventListener/WriteListenerTest.php +++ b/tests/Bridge/Doctrine/EventListener/WriteListenerTest.php @@ -72,12 +72,9 @@ public function testOnKernelViewWithControllerResultAndDeleteMethod() $request = new Request(); $request->setMethod('DELETE'); $request->attributes->set('_api_resource_class', 'Dummy'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->setControllerResult(null)->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->getControllerResult()->willReturn($dummy); - $writeListener->onKernelView($eventProphecy->reveal()); + $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, $dummy); + $writeListener->onKernelView($event); } /** diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 0e079a02f79..ea00098f9f5 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -244,8 +244,15 @@ public function testSetNameConverter() $this->extension->load($config, $containerBuilder); } + /** + * @group legacy + */ public function testEnableFosUser() { + if (!class_exists(NelmioApiDocBundle::class)) { + $this->markTestSkipped('FOSUserBundle is not installed'); + } + $containerBuilderProphecy = $this->getBaseContainerBuilderProphecy(); $containerBuilderProphecy->hasParameter('kernel.debug')->willReturn(true); $containerBuilderProphecy->getParameter('kernel.debug')->willReturn(false); diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ConfigurationTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ConfigurationTest.php index 92fef8a6ec6..e8c07bfb8b1 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ConfigurationTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ConfigurationTest.php @@ -107,7 +107,7 @@ private function runDefaultConfigTests(array $doctrineIntegrationsToLoad = ['orm 'serialize_payload_fields' => [], ], 'name_converter' => null, - 'enable_fos_user' => true, + 'enable_fos_user' => false, 'enable_nelmio_api_doc' => false, 'enable_swagger' => true, 'enable_swagger_ui' => true, diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index e5d2e9b52de..f9c968b0a39 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -67,7 +67,6 @@ public function registerBundles(): array new MercureBundle(), new ApiPlatformBundle(), new SecurityBundle(), - new FOSUserBundle(), new WebProfilerBundle(), ]; @@ -75,14 +74,18 @@ public function registerBundles(): array $bundles[] = new DoctrineMongoDBBundle(); } - if ('elasticsearch' !== $this->getEnvironment()) { - $bundles[] = new TestBundle(); + if (class_exists(FOSUserBundle::class)) { + $bundles[] = new FOSUserBundle(); } - if ($_SERVER['LEGACY'] ?? false) { + if (class_exists(NelmioApiDocBundle::class)) { $bundles[] = new NelmioApiDocBundle(); } + if ('elasticsearch' !== $this->getEnvironment()) { + $bundles[] = new TestBundle(); + } + return $bundles; } diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index e3f614ad159..dcf9d94b64e 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -57,7 +57,6 @@ api_platform: enabled: true nesting_separator: __ name_converter: 'app.name_converter' - enable_fos_user: true collection: order_parameter_name: 'order' order: 'ASC' diff --git a/tests/Fixtures/app/config/config_test.yml b/tests/Fixtures/app/config/config_test.yml index 663fc25bd0f..98b5f79a00d 100644 --- a/tests/Fixtures/app/config/config_test.yml +++ b/tests/Fixtures/app/config/config_test.yml @@ -8,13 +8,14 @@ api_platform: - '%kernel.project_dir%/../TestBundle/Model' - '%kernel.project_dir%/config/api_resources_orm.yaml' -fos_user: - db_driver: 'orm' - firewall_name: 'api' - user_class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\User' - from_email: - address: 'no-reply@les-tilleuls.coop' - sender_name: 'Kévin Dunglas' +# FIXME: move this in the Kernel +#fos_user: +# db_driver: 'orm' +# firewall_name: 'api' +# user_class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\User' +# from_email: +# address: 'no-reply@les-tilleuls.coop' +# sender_name: 'Kévin Dunglas' services: app.my_dummy_resource.search_filter: From c044c5fa0c7ff4f80b96cb0a02bca8600c93b6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 26 Oct 2020 21:49:06 +0100 Subject: [PATCH 04/27] fix some PHPUnit tests --- src/Util/ReflectionClassRecursiveIterator.php | 7 +- tests/Bridge/FosUser/EventListenerTest.php | 117 ------------------ .../ApiPlatformProviderTest.php | 8 ++ .../Parser/ApiPlatformParserTest.php | 7 ++ .../ApiPlatformExtensionTest.php | 46 ------- .../EventListener/ValidateListenerTest.php | 7 +- .../ValidationExceptionListenerTest.php | 3 + tests/Fixtures/TestBundle/Document/User.php | 31 +++-- tests/Fixtures/TestBundle/Entity/User.php | 29 +++-- tests/Fixtures/app/AppKernel.php | 24 ++-- tests/Fixtures/app/config/config_common.yml | 6 +- tests/Fixtures/app/config/config_test.yml | 9 -- tests/Mock/FosUser/MailerMock.php | 37 ------ .../EventListener/ValidateListenerTest.php | 8 +- 14 files changed, 85 insertions(+), 254 deletions(-) delete mode 100644 tests/Bridge/FosUser/EventListenerTest.php delete mode 100644 tests/Mock/FosUser/MailerMock.php diff --git a/src/Util/ReflectionClassRecursiveIterator.php b/src/Util/ReflectionClassRecursiveIterator.php index 1c35d72f609..fc27c1e8c39 100644 --- a/src/Util/ReflectionClassRecursiveIterator.php +++ b/src/Util/ReflectionClassRecursiveIterator.php @@ -45,7 +45,12 @@ public static function getReflectionClassesFromDirectories(array $directories): $sourceFile = realpath($sourceFile); } - require_once $sourceFile; + try { + require_once $sourceFile; + } catch (\Throwable $t) { + // invalid PHP file (example: missing parent class) + continue; + } $includedFiles[$sourceFile] = true; } diff --git a/tests/Bridge/FosUser/EventListenerTest.php b/tests/Bridge/FosUser/EventListenerTest.php deleted file mode 100644 index 1e24a888f21..00000000000 --- a/tests/Bridge/FosUser/EventListenerTest.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * 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\Bridge\FosUser; - -use ApiPlatform\Core\Bridge\FosUser\EventListener; -use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\User; -use ApiPlatform\Core\Tests\ProphecyTrait; -use FOS\UserBundle\Model\UserInterface; -use FOS\UserBundle\Model\UserManagerInterface; -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ViewEvent; - -/** - * @author Kévin Dunglas - */ -class EventListenerTest extends TestCase -{ - use ProphecyTrait; - - public function testDelete() - { - $user = $this->prophesize(UserInterface::class); - - $request = new Request([], [], ['_api_resource_class' => User::class, '_api_item_operation_name' => 'delete']); - $request->setMethod('DELETE'); - - $manager = $this->prophesize(UserManagerInterface::class); - $manager->deleteUser($user)->shouldBeCalled(); - - $event = $this->prophesize(ViewEvent::class); - $event->getControllerResult()->willReturn($user)->shouldBeCalled(); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->setControllerResult(null)->shouldBeCalled(); - - $listener = new EventListener($manager->reveal()); - $listener->onKernelView($event->reveal()); - } - - public function testUpdate() - { - $user = $this->prophesize(UserInterface::class); - - $request = new Request([], [], ['_api_resource_class' => User::class, '_api_item_operation_name' => 'put']); - $request->setMethod('PUT'); - - $manager = $this->prophesize(UserManagerInterface::class); - $manager->updateUser($user)->shouldBeCalled(); - - $event = $this->prophesize(ViewEvent::class); - $event->getControllerResult()->willReturn($user)->shouldBeCalled(); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->setControllerResult()->shouldNotBeCalled(); - - $listener = new EventListener($manager->reveal()); - $listener->onKernelView($event->reveal()); - } - - public function testNotApiRequest() - { - $request = new Request(); - - $manager = $this->prophesize(UserManagerInterface::class); - $manager->deleteUser()->shouldNotBeCalled(); - $manager->updateUser()->shouldNotBeCalled(); - - $event = $this->prophesize(ViewEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - - $listener = new EventListener($manager->reveal()); - $listener->onKernelView($event->reveal()); - } - - public function testNotUser() - { - $request = new Request([], [], ['_api_resource_class' => User::class, '_api_item_operation_name' => 'put']); - $request->setMethod('PUT'); - - $manager = $this->prophesize(UserManagerInterface::class); - $manager->deleteUser()->shouldNotBeCalled(); - $manager->updateUser()->shouldNotBeCalled(); - - $event = $this->prophesize(ViewEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getControllerResult()->willReturn(new \stdClass()); - - $listener = new EventListener($manager->reveal()); - $listener->onKernelView($event->reveal()); - } - - public function testSafeMethod() - { - $request = new Request([], [], ['_api_resource_class' => User::class, '_api_item_operation_name' => 'put']); - - $manager = $this->prophesize(UserManagerInterface::class); - $manager->deleteUser()->shouldNotBeCalled(); - $manager->updateUser()->shouldNotBeCalled(); - - $event = $this->prophesize(ViewEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getControllerResult()->willReturn(new User()); - - $listener = new EventListener($manager->reveal()); - $listener->onKernelView($event->reveal()); - } -} diff --git a/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php b/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php index e27c1c3b712..525a71e3e47 100644 --- a/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php +++ b/tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php @@ -28,6 +28,7 @@ use ApiPlatform\Core\Tests\ProphecyTrait; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Extractor\AnnotationsProviderInterface; +use Nelmio\ApiDocBundle\NelmioApiDocBundle; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Component\Routing\Route; @@ -42,6 +43,13 @@ class ApiPlatformProviderTest extends TestCase { use ProphecyTrait; + protected function setUp(): void + { + if (!class_exists(NelmioApiDocBundle::class)) { + $this->markTestSkipped('NelmioApiDocBundle is not installed.'); + } + } + /** * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Extractor\AnnotationsProvider\ApiPlatformProvider class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. */ diff --git a/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php b/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php index 3e041c8678e..0b35c0c68f6 100644 --- a/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php +++ b/tests/Bridge/NelmioApiDoc/Parser/ApiPlatformParserTest.php @@ -43,6 +43,13 @@ class ApiPlatformParserTest extends TestCase { use ProphecyTrait; + protected function setUp(): void + { + if (!class_exists(NelmioApiDocBundle::class)) { + $this->markTestSkipped('NelmioApiDocBundle is not installed.'); + } + } + /** * @expectedDeprecation The ApiPlatform\Core\Bridge\NelmioApiDoc\Parser\ApiPlatformParser class is deprecated since version 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform. */ diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index ea00098f9f5..2bdaf9066c4 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -83,7 +83,6 @@ use ApiPlatform\Core\Validator\ValidatorInterface; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\ORM\OptimisticLockException; -use FOS\UserBundle\FOSUserBundle; use Nelmio\ApiDocBundle\NelmioApiDocBundle; use PHPUnit\Framework\TestCase; use Prophecy\Argument; @@ -244,32 +243,6 @@ public function testSetNameConverter() $this->extension->load($config, $containerBuilder); } - /** - * @group legacy - */ - public function testEnableFosUser() - { - if (!class_exists(NelmioApiDocBundle::class)) { - $this->markTestSkipped('FOSUserBundle is not installed'); - } - - $containerBuilderProphecy = $this->getBaseContainerBuilderProphecy(); - $containerBuilderProphecy->hasParameter('kernel.debug')->willReturn(true); - $containerBuilderProphecy->getParameter('kernel.debug')->willReturn(false); - $containerBuilderProphecy->getParameter('kernel.bundles')->willReturn([ - 'DoctrineBundle' => DoctrineBundle::class, - 'FOSUserBundle' => FOSUserBundle::class, - ])->shouldBeCalled(); - $containerBuilderProphecy->setDefinition('api_platform.fos_user.event_listener', Argument::type(Definition::class))->shouldBeCalled(); - - $containerBuilder = $containerBuilderProphecy->reveal(); - - $config = self::DEFAULT_CONFIG; - $config['api_platform']['enable_fos_user'] = true; - - $this->extension->load($config, $containerBuilder); - } - public function testDisableProfiler() { $containerBuilderProphecy = $this->getBaseContainerBuilderProphecy(); @@ -299,25 +272,6 @@ public function testEnableProfilerWithDebug() $this->extension->load($config, $containerBuilder); } - public function testFosUserPriority() - { - $builder = new ContainerBuilder(); - - $loader = new XmlFileLoader($builder, new FileLocator(\dirname(__DIR__).'/../../../../src/Bridge/Symfony/Bundle/Resources/config')); - $loader->load('api.xml'); - $loader->load('fos_user.xml'); - - $fosListener = $builder->getDefinition('api_platform.fos_user.event_listener'); - $viewListener = $builder->getDefinition('api_platform.listener.view.serialize'); - - // Ensure FOSUser event listener priority is always greater than the view serialize listener - $this->assertGreaterThan( - $viewListener->getTag('kernel.event_listener')[0]['priority'], - $fosListener->getTag('kernel.event_listener')[0]['priority'], - 'api_platform.fos_user.event_listener priority needs to be greater than that of api_platform.listener.view.serialize' - ); - } - /** * @group legacy */ diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php index 8e79a7abf56..28b51dfc205 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidateListenerTest.php @@ -49,11 +49,10 @@ public function testNotAnApiPlatformRequest() $request = new Request(); $request->setMethod('POST'); - $event = $this->prophesize(ViewEvent::class); - $event->getRequest()->willReturn($request); - $listener = new ValidateListener($validator, $resourceMetadataFactory); - $listener->onKernelView($event->reveal()); + + $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, []); + $listener->onKernelView($event); } public function testValidatorIsCalled() diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php index 0d7248b994a..a7d39281078 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php @@ -21,6 +21,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Validator\ConstraintViolationList; @@ -44,6 +45,8 @@ public function testNotValidationException() $serializerProphecy = $this->prophesize(SerializerInterface::class); $listener = new ValidationExceptionListener($serializerProphecy->reveal(), ['hydra' => ['application/ld+json']]); + + $listener->onKernelException($eventProphecy->reveal()); } diff --git a/tests/Fixtures/TestBundle/Document/User.php b/tests/Fixtures/TestBundle/Document/User.php index ca3abe9a1a1..97e17a49ab4 100644 --- a/tests/Fixtures/TestBundle/Document/User.php +++ b/tests/Fixtures/TestBundle/Document/User.php @@ -19,8 +19,7 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Dto\RecoverPasswordOutput; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; -use FOS\UserBundle\Model\User as BaseUser; -use FOS\UserBundle\Model\UserInterface; +use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Serializer\Annotation\Groups; /** @@ -59,7 +58,7 @@ * @author Théo FIDRY * @author Kévin Dunglas */ -class User extends BaseUser +class User implements UserInterface { /** * @var int @@ -109,19 +108,25 @@ public function setFullname($fullname) return $this; } - /** - * @return string|null - */ - public function getFullname() + public function getUsername(): string { - return $this->fullname; + return (string) $this->email; } - /** - * {@inheritdoc} - */ - public function isUser(UserInterface $user = null) + public function getRoles(): array + { + return ['ROLE_USER']; + } + + public function getPassword() + { + } + + public function getSalt() + { + } + + public function eraseCredentials() { - return $user instanceof self && $user->id === $this->id; } } diff --git a/tests/Fixtures/TestBundle/Entity/User.php b/tests/Fixtures/TestBundle/Entity/User.php index 5a6b0261926..47a07a460b1 100644 --- a/tests/Fixtures/TestBundle/Entity/User.php +++ b/tests/Fixtures/TestBundle/Entity/User.php @@ -19,8 +19,7 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Dto\RecoverPasswordInput; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Dto\RecoverPasswordOutput; use Doctrine\ORM\Mapping as ORM; -use FOS\UserBundle\Model\User as BaseUser; -use FOS\UserBundle\Model\UserInterface; +use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Serializer\Annotation\Groups; /** @@ -60,7 +59,7 @@ * @author Théo FIDRY * @author Kévin Dunglas */ -class User extends BaseUser +class User implements UserInterface { /** * @var int @@ -120,11 +119,25 @@ public function getFullname() return $this->fullname; } - /** - * {@inheritdoc} - */ - public function isUser(UserInterface $user = null) + public function getUsername(): string + { + return (string) $this->email; + } + + public function getRoles(): array + { + return ['ROLE_USER']; + } + + public function getPassword() + { + } + + public function getSalt() + { + } + + public function eraseCredentials() { - return $user instanceof self && $user->id === $this->id; } } diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index f9c968b0a39..c7bdda69c95 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -19,7 +19,6 @@ use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle; use Doctrine\Common\Inflector\Inflector; use Doctrine\Inflector\InflectorFactory; -use FOS\UserBundle\FOSUserBundle; use Nelmio\ApiDocBundle\NelmioApiDocBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; @@ -31,6 +30,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface; use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Symfony\Component\Routing\RouteCollectionBuilder; use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder; use Symfony\Component\Security\Core\User\UserInterface; @@ -74,10 +74,6 @@ public function registerBundles(): array $bundles[] = new DoctrineMongoDBBundle(); } - if (class_exists(FOSUserBundle::class)) { - $bundles[] = new FOSUserBundle(); - } - if (class_exists(NelmioApiDocBundle::class)) { $bundles[] = new NelmioApiDocBundle(); } @@ -94,11 +90,14 @@ public function getProjectDir() return __DIR__; } - protected function configureRoutes(RouteCollectionBuilder $routes) + /** + * @param RoutingConfigurator|RouteCollectionBuilder $routes + */ + protected function configureRoutes($routes) { $routes->import(__DIR__."/config/routing_{$this->getEnvironment()}.yml"); - if ($_SERVER['LEGACY'] ?? false) { + if (class_exists(NelmioApiDocBundle::class)) { $routes->import('@NelmioApiDocBundle/Resources/config/routing.yml', '/nelmioapidoc'); } } @@ -120,7 +119,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'providers' => [ 'chain_provider' => [ 'chain' => [ - 'providers' => ['in_memory', 'fos_userbundle'], + 'providers' => ['in_memory', 'entity'], ], ], 'in_memory' => [ @@ -131,7 +130,12 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], ], ], - 'fos_userbundle' => ['id' => 'fos_user.user_provider.username_email'], + 'entity' => [ + 'entity' => [ + 'class' => User::class, + 'property' => 'email', + ], + ], ], 'firewalls' => [ 'dev' => [ @@ -171,7 +175,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load } $c->prependExtensionConfig('twig', $twigConfig); - if ($_SERVER['LEGACY'] ?? false) { + if (class_exists(NelmioApiDocBundle::class)) { $c->prependExtensionConfig('nelmio_api_doc', [ 'sandbox' => [ 'accept_type' => 'application/json', diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index dcf9d94b64e..830da1bbdb5 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -7,10 +7,11 @@ framework: test: ~ session: storage_id: 'session.storage.mock_file' - form: ~ # For FOSUser profiler: enabled: true collect: false + router: + utf8: true web_profiler: toolbar: true @@ -122,9 +123,6 @@ services: tags: - { name: 'serializer.normalizer' } - fos_user.mailer.default: - class: 'ApiPlatform\Core\Tests\Mock\FosUser\MailerMock' - app.name_converter: class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Serializer\NameConverter\CustomConverter' diff --git a/tests/Fixtures/app/config/config_test.yml b/tests/Fixtures/app/config/config_test.yml index 98b5f79a00d..8c97adbfd3c 100644 --- a/tests/Fixtures/app/config/config_test.yml +++ b/tests/Fixtures/app/config/config_test.yml @@ -8,15 +8,6 @@ api_platform: - '%kernel.project_dir%/../TestBundle/Model' - '%kernel.project_dir%/config/api_resources_orm.yaml' -# FIXME: move this in the Kernel -#fos_user: -# db_driver: 'orm' -# firewall_name: 'api' -# user_class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\User' -# from_email: -# address: 'no-reply@les-tilleuls.coop' -# sender_name: 'Kévin Dunglas' - services: app.my_dummy_resource.search_filter: parent: 'api_platform.doctrine.orm.search_filter' diff --git a/tests/Mock/FosUser/MailerMock.php b/tests/Mock/FosUser/MailerMock.php deleted file mode 100644 index d65e6fa1629..00000000000 --- a/tests/Mock/FosUser/MailerMock.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * 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\Mock\FosUser; - -use FOS\UserBundle\Mailer\MailerInterface; -use FOS\UserBundle\Model\UserInterface; - -/** - * @author Théo FIDRY - */ -class MailerMock implements MailerInterface -{ - /** - * Sends an email to a user to confirm the account creation. - */ - public function sendConfirmationEmailMessage(UserInterface $user) - { - } - - /** - * Sends an email to a user to confirm the password reset. - */ - public function sendResettingEmailMessage(UserInterface $user) - { - } -} diff --git a/tests/Validator/EventListener/ValidateListenerTest.php b/tests/Validator/EventListener/ValidateListenerTest.php index f34ce95abbc..73f4add7cc8 100644 --- a/tests/Validator/EventListener/ValidateListenerTest.php +++ b/tests/Validator/EventListener/ValidateListenerTest.php @@ -47,12 +47,10 @@ public function testNotAnApiPlatformRequest() $request = new Request(); $request->setMethod('POST'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn([]); - $eventProphecy->getRequest()->willReturn($request); - $listener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + + $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, []); + $listener->onKernelView($event); } public function testValidatorIsCalled() From 4feb95f8bf0a147ac9ce6be0cb4fe7b28f082a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 27 Oct 2020 09:57:46 +0100 Subject: [PATCH 05/27] fix some more tests --- src/EventListener/SerializeListener.php | 2 +- .../ValidationExceptionListenerTest.php | 50 ++++-------- tests/EventListener/ExceptionListenerTest.php | 33 +++----- tests/EventListener/RespondListenerTest.php | 81 ++++++++----------- tests/EventListener/SerializeListenerTest.php | 68 +++++++++------- 5 files changed, 103 insertions(+), 131 deletions(-) diff --git a/src/EventListener/SerializeListener.php b/src/EventListener/SerializeListener.php index b68cc1fef00..c7605d438dd 100644 --- a/src/EventListener/SerializeListener.php +++ b/src/EventListener/SerializeListener.php @@ -60,7 +60,7 @@ public function onKernelView(ViewEvent $event): void if ( $controllerResult instanceof Response || !(($attributes = RequestAttributesExtractor::extractAttributes($request))['respond'] ?? $request->attributes->getBoolean('_api_respond', false)) - || $attributes && $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) + || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) ) { return; } diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php index a7d39281078..ac870e129b9 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php @@ -34,20 +34,14 @@ class ValidationExceptionListenerTest extends TestCase public function testNotValidationException() { - $eventProphecy = $this->prophesize(ExceptionEvent::class); - if (method_exists(ExceptionEvent::class, 'getThrowable')) { - $eventProphecy->getThrowable()->willReturn(new \Exception())->shouldBeCalled(); - } else { - $eventProphecy->getException()->willReturn(new \Exception())->shouldBeCalled(); - } - $eventProphecy->setResponse()->shouldNotBeCalled(); + $listener = new ValidationExceptionListener( + $this->prophesize(SerializerInterface::class)->reveal(), + ['hydra' => ['application/ld+json']]) + ; - $serializerProphecy = $this->prophesize(SerializerInterface::class); - - $listener = new ValidationExceptionListener($serializerProphecy->reveal(), ['hydra' => ['application/ld+json']]); - - - $listener->onKernelException($eventProphecy->reveal()); + $event = new ExceptionEvent($this->prophesize(HttpKernelInterface::class)->reveal(), new Request(), HttpKernelInterface::MASTER_REQUEST, new \Exception()); + $listener->onKernelException($event); + $this->assertNull($event->getResponse()); } public function testValidationException() @@ -55,29 +49,19 @@ public function testValidationException() $exceptionJson = '{"foo": "bar"}'; $list = new ConstraintViolationList([]); - $eventProphecy = $this->prophesize(ExceptionEvent::class); - if (method_exists(ExceptionEvent::class, 'getThrowable')) { - $eventProphecy->getThrowable()->willReturn(new ValidationException($list))->shouldBeCalled(); - } else { - $eventProphecy->getException()->willReturn(new ValidationException($list))->shouldBeCalled(); - } - $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); - $eventProphecy->setResponse(Argument::allOf( - Argument::type(Response::class), - Argument::which('getContent', $exceptionJson), - Argument::which('getStatusCode', Response::HTTP_BAD_REQUEST), - Argument::that(function (Response $response): bool { - return - 'application/ld+json; charset=utf-8' === $response->headers->get('Content-Type') - && 'nosniff' === $response->headers->get('X-Content-Type-Options') - && 'deny' === $response->headers->get('X-Frame-Options'); - }) - ))->shouldBeCalled(); - $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->serialize($list, 'hydra')->willReturn($exceptionJson)->shouldBeCalled(); $listener = new ValidationExceptionListener($serializerProphecy->reveal(), ['hydra' => ['application/ld+json']]); - $listener->onKernelException($eventProphecy->reveal()); + $event = new ExceptionEvent($this->prophesize(HttpKernelInterface::class)->reveal(), new Request(), HttpKernelInterface::MASTER_REQUEST, new ValidationException($list)); + $listener->onKernelException($event); + + $response = $event->getResponse(); + $this->assertInstanceOf(Response::class, $response); + $this->assertSame($exceptionJson, $response->getContent()); + $this->assertSame(Response::HTTP_BAD_REQUEST, $response->getStatusCode()); + $this->assertSame('application/ld+json; charset=utf-8', $response->headers->get('Content-Type')); + $this->assertSame('nosniff', $response->headers->get('X-Content-Type-Options')); + $this->assertSame('deny', $response->headers->get('X-Frame-Options')); } } diff --git a/tests/EventListener/ExceptionListenerTest.php b/tests/EventListener/ExceptionListenerTest.php index 206fe80663e..9edfec97f14 100644 --- a/tests/EventListener/ExceptionListenerTest.php +++ b/tests/EventListener/ExceptionListenerTest.php @@ -38,18 +38,11 @@ public function testOnKernelException(Request $request) $kernel = $this->prophesize(HttpKernelInterface::class); $kernel->handle(Argument::type(Request::class), HttpKernelInterface::SUB_REQUEST, false)->willReturn(new Response())->shouldBeCalled(); - $eventProphecy = $this->prophesize(ExceptionEvent::class); - $eventProphecy->getRequest()->willReturn($request); - if (method_exists(ExceptionEvent::class, 'getThrowable')) { - $eventProphecy->getThrowable()->willReturn(new \Exception()); - } else { - $eventProphecy->getException()->willReturn(new \Exception()); - } - $eventProphecy->getKernel()->willReturn($kernel); - $eventProphecy->setResponse(Argument::type(Response::class))->shouldBeCalled(); - $listener = new ExceptionListener('foo:bar', null, false, class_exists(ErrorListener::class) ? $this->prophesize(ErrorListener::class)->reveal() : null); - $listener->onKernelException($eventProphecy->reveal()); + $event = new ExceptionEvent($kernel->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, new \Exception()); + $listener->onKernelException($event); + + $this->assertInstanceOf(Response::class, $event->getResponse()); } public function getRequest() @@ -62,12 +55,11 @@ public function getRequest() public function testDoNothingWhenNotAnApiCall() { - $eventProphecy = $this->prophesize(ExceptionEvent::class); - $eventProphecy->getRequest()->willReturn(new Request()); - $eventProphecy->setResponse(Argument::type(Response::class))->shouldNotBeCalled(); - $listener = new ExceptionListener('foo:bar', null, false, class_exists(ErrorListener::class) ? $this->prophesize(ErrorListener::class)->reveal() : null); - $listener->onKernelException($eventProphecy->reveal()); + $event = new ExceptionEvent($this->prophesize(HttpKernelInterface::class)->reveal(), new Request(), HttpKernelInterface::MASTER_REQUEST, new \Exception()); + $listener->onKernelException($event); + + $this->assertNull($event->getResponse()); } public function testDoNothingWhenHtmlRequested() @@ -75,11 +67,10 @@ public function testDoNothingWhenHtmlRequested() $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('html'); - $eventProphecy = $this->prophesize(ExceptionEvent::class); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setResponse(Argument::type(Response::class))->shouldNotBeCalled(); - $listener = new ExceptionListener('foo:bar', null, false, class_exists(ErrorListener::class) ? $this->prophesize(ErrorListener::class)->reveal() : null); - $listener->onKernelException($eventProphecy->reveal()); + $event = new ExceptionEvent($this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, new \Exception()); + $listener->onKernelException($event); + + $this->assertNull($event->getResponse()); } } diff --git a/tests/EventListener/RespondListenerTest.php b/tests/EventListener/RespondListenerTest.php index fd397873464..2c5488717ef 100644 --- a/tests/EventListener/RespondListenerTest.php +++ b/tests/EventListener/RespondListenerTest.php @@ -34,28 +34,25 @@ class RespondListenerTest extends TestCase public function testDoNotHandleResponse() { - $request = new Request(); - - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn(new Response()); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setResponse(Argument::any())->shouldNotBeCalled(); - $listener = new RespondListener(); - $listener->onKernelView($eventProphecy->reveal()); + $event = new ViewEvent($this->prophesize(HttpKernelInterface::class)->reveal(), new Request(), HttpKernelInterface::MASTER_REQUEST, null); + $listener->onKernelView($event); + + $this->assertNull($event->getResponse()); } public function testDoNotHandleWhenRespondFlagIsFalse() { - $request = new Request([], [], ['_api_respond' => false]); - - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn('foo'); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setResponse(Argument::any())->shouldNotBeCalled(); - $listener = new RespondListener(); - $listener->onKernelView($eventProphecy->reveal()); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_respond' => false]), + HttpKernelInterface::MASTER_REQUEST, + 'foo' + ); + $listener->onKernelView($event); + + $this->assertNull($event->getResponse()); } public function testCreate200Response() @@ -63,9 +60,8 @@ public function testCreate200Response() $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('xml'); - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); $event = new ViewEvent( - $kernelProphecy->reveal(), + $this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, 'foo' @@ -85,13 +81,11 @@ public function testCreate200Response() public function testPost200WithoutLocation() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); $request->setMethod('POST'); $event = new ViewEvent( - $kernelProphecy->reveal(), + $this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, 'bar' @@ -109,13 +103,11 @@ public function testPost200WithoutLocation() public function testPost301WithLocation() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); $request->setMethod('POST'); $event = new ViewEvent( - $kernelProphecy->reveal(), + $this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, 'bar' @@ -134,14 +126,12 @@ public function testPost301WithLocation() public function testCreate201Response() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); $request->setMethod('POST'); $request->setRequestFormat('xml'); $event = new ViewEvent( - $kernelProphecy->reveal(), + $this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, 'foo' @@ -164,14 +154,12 @@ public function testCreate201Response() public function testCreate204Response() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('xml'); $request->setMethod('DELETE'); $event = new ViewEvent( - $kernelProphecy->reveal(), + $this->prophesize(HttpKernelInterface::class)->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, 'foo' @@ -191,13 +179,9 @@ public function testCreate204Response() public function testSetSunsetHeader() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]); - $event = new ViewEvent( - $kernelProphecy->reveal(), - $request, + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]), HttpKernelInterface::MASTER_REQUEST, 'bar' ); @@ -215,13 +199,9 @@ public function testSetSunsetHeader() public function testSetCustomStatus() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]); - $event = new ViewEvent( - $kernelProphecy->reveal(), - $request, + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]), HttpKernelInterface::MASTER_REQUEST, 'bar' ); @@ -236,14 +216,17 @@ public function testSetCustomStatus() public function testHandleResponse() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]); + $listener = new RespondListener(); + $response = new Response(); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn($response); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setResponse($response)->shouldBeCalled(); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]), + HttpKernelInterface::MASTER_REQUEST, + $response + ); + $listener->onKernelView($event); - $listener = new RespondListener(); - $listener->onKernelView($eventProphecy->reveal()); + $this->assertSame($response, $event->getResponse()); } } diff --git a/tests/EventListener/SerializeListenerTest.php b/tests/EventListener/SerializeListenerTest.php index 05cb16f14aa..e0c4ad37fe4 100644 --- a/tests/EventListener/SerializeListenerTest.php +++ b/tests/EventListener/SerializeListenerTest.php @@ -25,6 +25,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ViewEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\SerializerInterface; @@ -40,17 +41,19 @@ public function testDoNotSerializeWhenControllerResultIsResponse() $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->serialize(Argument::cetera())->shouldNotBeCalled(); - $request = new Request(); - - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn(new Response()); - $eventProphecy->getRequest()->willReturn($request); - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::cetera()); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request(), + HttpKernelInterface::MASTER_REQUEST, + null + ); + $listener->onKernelView($event); + + $this->assertNull($event->getResponse()); } public function testDoNotSerializeWhenRespondFlagIsFalse() @@ -60,18 +63,22 @@ public function testDoNotSerializeWhenRespondFlagIsFalse() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); + $dummy = new Dummy(); $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post', '_api_respond' => false]); $request->setMethod('POST'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn($dummy); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setControllerResult(Argument::any())->shouldNotBeCalled(); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $dummy + ); + $listener->onKernelView($event); - $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $this->assertNull($event->getResponse()); } public function testDoNotSerializeWhenDisabledInOperationAttribute() @@ -90,18 +97,21 @@ public function testDoNotSerializeWhenDisabledInOperationAttribute() $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); - $dummy = new Dummy(); + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); + $dummy = new Dummy(); $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); $request->setMethod('POST'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn($dummy); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setControllerResult(Argument::any())->shouldNotBeCalled(); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $dummy + ); + $listener->onKernelView($event); - $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $this->assertNull($event->getResponse()); } public function testSerializeCollectionOperation() @@ -128,16 +138,20 @@ public function testSerializeCollectionOperation() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn(new \stdClass())->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $eventProphecy->setControllerResult('bar')->shouldBeCalled(); - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); - $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new \stdClass() + ); + + $listener->onKernelView($event); + + $this->assertSame('bar', $event->getControllerResult()); } public function testSerializeCollectionOperationWithOutputClassDisabled() From af8e3f97662eb20c34c71619601a4c0e038470b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 27 Oct 2020 23:31:09 +0100 Subject: [PATCH 06/27] PHPUnit tests are now green --- CONTRIBUTING.md | 23 --- behat.yml.dist | 10 +- src/EventListener/SerializeListener.php | 2 +- tests/EventListener/SerializeListenerTest.php | 78 ++++++---- tests/Fixtures/app/AppKernel.php | 2 + tests/GraphQl/Action/EntrypointActionTest.php | 2 + .../Action/GraphQlPlaygroundActionTest.php | 2 + tests/GraphQl/Action/GraphiQlActionTest.php | 2 + .../EventListener/AddHeadersListenerTest.php | 144 ++++++++++-------- .../EventListener/AddTagsListenerTest.php | 103 +++++++------ .../AddLinkHeaderListenerTest.php | 22 ++- .../AddLinkHeaderListenerTest.php | 38 +++-- .../EventListener/ValidateListenerTest.php | 35 +++-- 13 files changed, 256 insertions(+), 207 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb2f1ec3a54..cc6e77496e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,7 +67,6 @@ When you send a PR, just make sure that: * You make the PR on the same branch you based your changes on. If you see commits that you did not make in your PR, you're doing it wrong. * Also don't forget to add a comment when you update a PR with a ping to [the maintainers](https://github.com/orgs/api-platform/people), so he/she will get a notification. -* Squash your commits into one commit (see the next chapter). All Pull Requests must include [this header](.github/PULL_REQUEST_TEMPLATE.md). @@ -105,28 +104,6 @@ If you want to launch Behat tests for MongoDB, the command is: To get more details about an error, replace `--format=progress` by `-vvv`. -## Squash your Commits - -If you have 3 commits, start with: - - git rebase -i HEAD~3 - -An editor will be opened with your 3 commits, all prefixed by `pick`. - -Replace all `pick` prefixes by `fixup` (or `f`) **except the first commit** of the list. - -Save and quit the editor. - -After that, all your commits will be squashed into the first one and the commit message will be the first one. - -If you would like to rename your commit message, type: - - git commit --amend - -Now force push to update your PR: - - git push --force-with-lease - # License and Copyright Attribution When you open a Pull Request to the API Platform project, you agree to license your code under the [MIT license](LICENSE) diff --git a/behat.yml.dist b/behat.yml.dist index 781a5c47882..4f98e135d3b 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -21,18 +21,18 @@ default: filters: tags: '~@postgres&&~@mongodb&&~@elasticsearch&&~@legacy' extensions: - 'Behat\Symfony2Extension': + 'FriendsOfBehat\SymfonyExtension': + bootstrap: 'tests/Fixtures/app/bootstrap.php' kernel: - env: 'test' - debug: 'true' + environment: 'test' + debug: true path: 'tests/Fixtures/app/AppKernel.php' - bootstrap: 'tests/Fixtures/app/bootstrap.php' 'Behat\MinkExtension': base_url: 'http://example.com/' files_path: 'features/files' sessions: default: - symfony2: ~ + symfony: ~ 'Behatch\Extension': ~ postgres: diff --git a/src/EventListener/SerializeListener.php b/src/EventListener/SerializeListener.php index c7605d438dd..b3abea328b2 100644 --- a/src/EventListener/SerializeListener.php +++ b/src/EventListener/SerializeListener.php @@ -60,7 +60,7 @@ public function onKernelView(ViewEvent $event): void if ( $controllerResult instanceof Response || !(($attributes = RequestAttributesExtractor::extractAttributes($request))['respond'] ?? $request->attributes->getBoolean('_api_respond', false)) - || $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY) + || ($attributes && $this->isOperationAttributeDisabled($attributes, self::OPERATION_ATTRIBUTE_KEY)) ) { return; } diff --git a/tests/EventListener/SerializeListenerTest.php b/tests/EventListener/SerializeListenerTest.php index e0c4ad37fe4..a0eee535f19 100644 --- a/tests/EventListener/SerializeListenerTest.php +++ b/tests/EventListener/SerializeListenerTest.php @@ -44,13 +44,14 @@ public function testDoNotSerializeWhenControllerResultIsResponse() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::cetera()); - $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); $event = new ViewEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), new Request(), HttpKernelInterface::MASTER_REQUEST, null ); + + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); $listener->onKernelView($event); $this->assertNull($event->getResponse()); @@ -63,8 +64,6 @@ public function testDoNotSerializeWhenRespondFlagIsFalse() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $dummy = new Dummy(); $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post', '_api_respond' => false]); @@ -76,6 +75,8 @@ public function testDoNotSerializeWhenRespondFlagIsFalse() HttpKernelInterface::MASTER_REQUEST, $dummy ); + + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); $listener->onKernelView($event); $this->assertNull($event->getResponse()); @@ -97,8 +98,6 @@ public function testDoNotSerializeWhenDisabledInOperationAttribute() $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn($resourceMetadata); - $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $dummy = new Dummy(); $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); $request->setMethod('POST'); @@ -109,6 +108,8 @@ public function testDoNotSerializeWhenDisabledInOperationAttribute() HttpKernelInterface::MASTER_REQUEST, $dummy ); + + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); $listener->onKernelView($event); $this->assertNull($event->getResponse()); @@ -135,13 +136,12 @@ public function testSerializeCollectionOperation() ->willReturn('bar') ->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $request->setRequestFormat('xml'); - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); - $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); + + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request->setRequestFormat('xml'); $event = new ViewEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), $request, @@ -149,6 +149,7 @@ public function testSerializeCollectionOperation() new \stdClass() ); + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); $listener->onKernelView($event); $this->assertSame('bar', $event->getControllerResult()); @@ -159,19 +160,23 @@ public function testSerializeCollectionOperationWithOutputClassDisabled() $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'collection_operation_name' => 'post', 'output' => ['class' => null]]; $serializerProphecy = $this->prophesize(SerializerInterface::class); + $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); + $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_api_output_class' => false]); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn(new \stdClass()); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setControllerResult(null)->shouldBeCalled(); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new \stdClass() + ); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->onKernelView($event); + + $this->assertNull($event->getControllerResult()); } public function testSerializeItemOperation() @@ -194,19 +199,22 @@ public function testSerializeItemOperation() ->willReturn('bar') ->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); - $request->setRequestFormat('xml'); - - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn(new \stdClass())->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $eventProphecy->setControllerResult('bar')->shouldBeCalled(); - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); + $request->setRequestFormat('xml'); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new \stdClass() + ); + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->onKernelView($event); + + $this->assertSame('bar', $event->getControllerResult()); } public function testEncode() @@ -216,17 +224,21 @@ public function testEncode() $serializerProphecy->encode(Argument::any(), 'xml')->willReturn('bar')->shouldBeCalled(); $serializerProphecy->serialize(Argument::cetera())->shouldNotBeCalled(); + $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); + $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn([])->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $eventProphecy->setControllerResult('bar')->shouldBeCalled(); - - $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + [] + ); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->onKernelView($event); + + $this->assertSame('bar', $event->getControllerResult()); } } diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index c7bdda69c95..9a102b984f4 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -19,6 +19,7 @@ use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle; use Doctrine\Common\Inflector\Inflector; use Doctrine\Inflector\InflectorFactory; +use FriendsOfBehat\SymfonyExtension\Bundle\FriendsOfBehatSymfonyExtensionBundle; use Nelmio\ApiDocBundle\NelmioApiDocBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; @@ -68,6 +69,7 @@ public function registerBundles(): array new ApiPlatformBundle(), new SecurityBundle(), new WebProfilerBundle(), + new FriendsOfBehatSymfonyExtensionBundle(), ]; if (class_exists(DoctrineMongoDBBundle::class)) { diff --git a/tests/GraphQl/Action/EntrypointActionTest.php b/tests/GraphQl/Action/EntrypointActionTest.php index eb687bab3a2..049d42578b3 100644 --- a/tests/GraphQl/Action/EntrypointActionTest.php +++ b/tests/GraphQl/Action/EntrypointActionTest.php @@ -238,6 +238,8 @@ private function getEntrypointAction(array $variables = ['graphqlVariable']): En $executorProphecy->executeQuery(Argument::is($schema->reveal()), 'graphqlQuery', null, null, $variables, 'graphqlOperationName')->willReturn($executionResultProphecy->reveal()); $twigProphecy = $this->prophesize(TwigEnvironment::class); + $twigProphecy->render(Argument::cetera())->willReturn(''); + $routerProphecy = $this->prophesize(RouterInterface::class); $graphiQlAction = new GraphiQlAction($twigProphecy->reveal(), $routerProphecy->reveal(), true); diff --git a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php index 9d5ce6923c2..ecd0d16eb32 100644 --- a/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php +++ b/tests/GraphQl/Action/GraphQlPlaygroundActionTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\GraphQl\Action\GraphQlPlaygroundAction; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; +use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; @@ -50,6 +51,7 @@ public function testDisabledAction(): void private function getGraphQlPlaygroundAction(bool $enabled): GraphQlPlaygroundAction { $twigProphecy = $this->prophesize(TwigEnvironment::class); + $twigProphecy->render(Argument::cetera())->willReturn(''); $routerProphecy = $this->prophesize(RouterInterface::class); return new GraphQlPlaygroundAction($twigProphecy->reveal(), $routerProphecy->reveal(), $enabled, ''); diff --git a/tests/GraphQl/Action/GraphiQlActionTest.php b/tests/GraphQl/Action/GraphiQlActionTest.php index f3df3780e92..f20c7978247 100644 --- a/tests/GraphQl/Action/GraphiQlActionTest.php +++ b/tests/GraphQl/Action/GraphiQlActionTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\GraphQl\Action\GraphiQlAction; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; +use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; @@ -50,6 +51,7 @@ public function testDisabledAction(): void private function getGraphiQlAction(bool $enabled): GraphiQlAction { $twigProphecy = $this->prophesize(TwigEnvironment::class); + $twigProphecy->render(Argument::cetera())->willReturn(''); $routerProphecy = $this->prophesize(RouterInterface::class); return new GraphiQlAction($twigProphecy->reveal(), $routerProphecy->reveal(), $enabled, ''); diff --git a/tests/HttpCache/EventListener/AddHeadersListenerTest.php b/tests/HttpCache/EventListener/AddHeadersListenerTest.php index 19f889bcc8a..3a55f9556b5 100644 --- a/tests/HttpCache/EventListener/AddHeadersListenerTest.php +++ b/tests/HttpCache/EventListener/AddHeadersListenerTest.php @@ -22,6 +22,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** * @author Kévin Dunglas @@ -34,15 +35,16 @@ public function testDoNotSetHeaderWhenMethodNotCacheable() { $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $request->setMethod('PUT'); - $response = new Response(); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldNotBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddHeadersListener(true); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertNull($response->getEtag()); } @@ -50,63 +52,66 @@ public function testDoNotSetHeaderWhenMethodNotCacheable() public function testDoNotSetHeaderOnUnsuccessfulResponse() { $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); - $response = new Response('{}', Response::HTTP_BAD_REQUEST); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddHeadersListener(true); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertNull($response->getEtag()); } public function testDoNotSetHeaderWhenNotAnApiOperation() { - $request = new Request(); $response = new Response(); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldNotBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request(), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddHeadersListener(true); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertNull($response->getEtag()); } public function testDoNotSetHeaderWhenNoContent() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response(); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); - + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddHeadersListener(true); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertNull($response->getEtag()); } public function testAddHeaders() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('"9893532233caff98cd083a116b013c0b"', $response->getEtag()); $this->assertSame('max-age=100, public, s-maxage=200', $response->headers->get('Cache-Control')); @@ -115,22 +120,24 @@ public function testAddHeaders() public function testDoNotSetHeaderWhenAlreadySet() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]); $response->setEtag('etag'); $response->setMaxAge(300); // This also calls setPublic $response->setSharedMaxAge(400); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('"etag"', $response->getEtag()); $this->assertSame('max-age=300, public, s-maxage=400', $response->headers->get('Cache-Control')); @@ -139,19 +146,20 @@ public function testDoNotSetHeaderWhenAlreadySet() public function testSetHeadersFromResourceMetadata() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $metadata = new ResourceMetadata(null, null, null, null, null, ['cache_headers' => ['max_age' => 123, 'shared_max_age' => 456, 'vary' => ['Vary-1', 'Vary-2']]]); $factory = $this->prophesize(ResourceMetadataFactoryInterface::class); $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('max-age=123, public, s-maxage=456', $response->headers->get('Cache-Control')); $this->assertSame(['Vary-1', 'Vary-2'], $response->getVary()); @@ -159,12 +167,13 @@ public function testSetHeadersFromResourceMetadata() public function testSetHeadersFromResourceMetadataMarkedAsPrivate() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response('some content', 200); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $metadata = new ResourceMetadata(null, null, null, null, null, [ 'cache_headers' => [ @@ -177,7 +186,7 @@ public function testSetHeadersFromResourceMetadataMarkedAsPrivate() $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('max-age=123, private', $response->headers->get('Cache-Control')); @@ -187,12 +196,13 @@ public function testSetHeadersFromResourceMetadataMarkedAsPrivate() public function testSetHeadersFromResourceMetadataMarkedAsPublic() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response('some content', 200); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $metadata = new ResourceMetadata(null, null, null, null, null, [ 'cache_headers' => [ @@ -205,19 +215,20 @@ public function testSetHeadersFromResourceMetadataMarkedAsPublic() $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('max-age=123, public, s-maxage=456', $response->headers->get('Cache-Control')); } public function testSetHeadersFromResourceMetadataWithNoPrivacy() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response('some content', 200); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $metadata = new ResourceMetadata(null, null, null, null, null, [ 'cache_headers' => [ @@ -229,19 +240,20 @@ public function testSetHeadersFromResourceMetadataWithNoPrivacy() $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('max-age=123, public, s-maxage=456', $response->headers->get('Cache-Control')); } public function testSetHeadersFromResourceMetadataWithNoPrivacyDefaultsPrivate() { - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); $response = new Response('some content', 200); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $metadata = new ResourceMetadata(null, null, null, null, null, [ 'cache_headers' => [ @@ -253,7 +265,7 @@ public function testSetHeadersFromResourceMetadataWithNoPrivacyDefaultsPrivate() $factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled(); $listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], false, $factory->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('max-age=123, private', $response->headers->get('Cache-Control')); diff --git a/tests/HttpCache/EventListener/AddTagsListenerTest.php b/tests/HttpCache/EventListener/AddTagsListenerTest.php index 4bfa77c9c9e..38c7298eb5a 100644 --- a/tests/HttpCache/EventListener/AddTagsListenerTest.php +++ b/tests/HttpCache/EventListener/AddTagsListenerTest.php @@ -21,6 +21,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** * @author Kévin Dunglas @@ -40,12 +41,15 @@ public function testDoNotSetHeaderWhenMethodNotCacheable() $response->setPublic(); $response->setEtag('foo'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertFalse($response->headers->has('Cache-Tags')); } @@ -55,15 +59,16 @@ public function testDoNotSetHeaderWhenResponseNotCacheable() $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); - $response = new Response(); - - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertFalse($response->headers->has('Cache-Tags')); } @@ -72,18 +77,19 @@ public function testDoNotSetHeaderWhenNotAnApiOperation() { $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $request = new Request([], [], ['_resources' => ['/foo', '/bar']]); - $response = new Response(); $response->setPublic(); $response->setEtag('foo'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_resources' => ['/foo', '/bar']]), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertFalse($response->headers->has('Cache-Tags')); } @@ -92,18 +98,19 @@ public function testDoNotSetHeaderWhenEmptyTagList() { $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $request = new Request([], [], ['_resources' => [], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); - $response = new Response(); $response->setPublic(); $response->setEtag('foo'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_resources' => [], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertFalse($response->headers->has('Cache-Tags')); } @@ -112,18 +119,19 @@ public function testAddTags() { $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); - $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']); - $response = new Response(); $response->setPublic(); $response->setEtag('foo'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('/foo,/bar', $response->headers->get('Cache-Tags')); } @@ -133,18 +141,19 @@ public function testAddCollectionIri() $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/dummies')->shouldBeCalled(); - $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); - $response = new Response(); $response->setPublic(); $response->setEtag('foo'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('/foo,/bar,/dummies', $response->headers->get('Cache-Tags')); } @@ -154,18 +163,19 @@ public function testAddCollectionIriWhenCollectionIsEmpty() $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/dummies')->shouldBeCalled(); - $request = new Request([], [], ['_resources' => [], '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); - $response = new Response(); $response->setPublic(); $response->setEtag('foo'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_resources' => [], '_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('/dummies', $response->headers->get('Cache-Tags')); } @@ -175,18 +185,19 @@ public function testAddSubResourceCollectionIri() $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); $iriConverterProphecy->getIriFromResourceClass(Dummy::class)->willReturn('/dummies')->shouldBeCalled(); - $request = new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_subresource_operation_name' => 'api_dummies_relatedDummies_get_subresource', '_api_subresource_context' => ['collection' => true]]); - $response = new Response(); $response->setPublic(); $response->setEtag('foo'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); - $event->getResponse()->willReturn($response)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + new Request([], [], ['_resources' => ['/foo', '/bar'], '_api_resource_class' => Dummy::class, '_api_subresource_operation_name' => 'api_dummies_relatedDummies_get_subresource', '_api_subresource_context' => ['collection' => true]]), + HttpKernelInterface::MASTER_REQUEST, + $response + ); $listener = new AddTagsListener($iriConverterProphecy->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame('/foo,/bar,/dummies', $response->headers->get('Cache-Tags')); } diff --git a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php index a55d3c116b8..45a070d6d79 100644 --- a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php @@ -20,7 +20,9 @@ use Fig\Link\Link; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\WebLink\HttpHeaderSerializer; /** @@ -38,11 +40,15 @@ public function testAddLinkHeader(string $expected, Request $request) $urlGenerator = $this->prophesize(UrlGeneratorInterface::class); $urlGenerator->generate('api_doc', ['_format' => 'jsonld'], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/docs')->shouldBeCalled(); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); $listener = new AddLinkHeaderListener($urlGenerator->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertSame($expected, (new HttpHeaderSerializer())->serialize($request->attributes->get('_links')->getLinks())); } @@ -60,12 +66,16 @@ public function testSkipWhenPreflightRequest(): void $request->setMethod('OPTIONS'); $request->headers->set('Access-Control-Request-Method', 'POST'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); $urlGenerator = $this->prophesize(UrlGeneratorInterface::class); $listener = new AddLinkHeaderListener($urlGenerator->reveal()); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertFalse($request->attributes->has('_links')); } diff --git a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php index 7392b1f5666..2044689f4ec 100644 --- a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php @@ -22,7 +22,9 @@ use Fig\Link\Link; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\WebLink\HttpHeaderSerializer; /** @@ -40,12 +42,15 @@ public function testAddLinkHeader(string $expected, Request $request) $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => true])); - $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); - - $eventProphecy = $this->prophesize(ResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); - $listener->onKernelResponse($eventProphecy->reveal()); + $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); + $listener->onKernelResponse($event); $this->assertSame($expected, (new HttpHeaderSerializer())->serialize($request->attributes->get('_links')->getLinks())); } @@ -66,12 +71,15 @@ public function testDoNotAddHeader(Request $request) $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata()); - $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); - - $eventProphecy = $this->prophesize(ResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); - $listener->onKernelResponse($eventProphecy->reveal()); + $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); + $listener->onKernelResponse($event); $this->assertNull($request->attributes->get('_links')); } @@ -90,12 +98,16 @@ public function testSkipWhenPreflightRequest(): void $request->setMethod('OPTIONS'); $request->headers->set('Access-Control-Request-Method', 'POST'); - $event = $this->prophesize(ResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $event = new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); $resourceMetadataFactory = $this->prophesize(ResourceMetadataFactoryInterface::class); $listener = new AddLinkHeaderListener($resourceMetadataFactory->reveal(), 'http://example.com/.well-known/mercure'); - $listener->onKernelResponse($event->reveal()); + $listener->onKernelResponse($event); $this->assertFalse($request->attributes->has('_links')); } diff --git a/tests/Validator/EventListener/ValidateListenerTest.php b/tests/Validator/EventListener/ValidateListenerTest.php index 73f4add7cc8..dcb6b4e25b3 100644 --- a/tests/Validator/EventListener/ValidateListenerTest.php +++ b/tests/Validator/EventListener/ValidateListenerTest.php @@ -80,14 +80,15 @@ public function testDoNotValidateWhenControllerResultIsResponse() $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post', '_api_receive' => false]); $request->setMethod('POST'); - $response = new Response(); - - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn($response); - $eventProphecy->getRequest()->willReturn($request); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $dummy + ); $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($eventProphecy->reveal()); + $validationViewListener->onKernelView($event); } public function testDoNotValidateWhenReceiveFlagIsFalse() @@ -102,12 +103,15 @@ public function testDoNotValidateWhenReceiveFlagIsFalse() $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post', '_api_receive' => false]); $request->setMethod('POST'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn($dummy); - $eventProphecy->getRequest()->willReturn($request); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $dummy + ); $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($eventProphecy->reveal()); + $validationViewListener->onKernelView($event); } public function testDoNotValidateWhenDisabledInOperationAttribute() @@ -129,12 +133,15 @@ public function testDoNotValidateWhenDisabledInOperationAttribute() $request = new Request([], [], ['data' => $dummy, '_api_resource_class' => DummyEntity::class, '_api_collection_operation_name' => 'post']); $request->setMethod('POST'); - $eventProphecy = $this->prophesize(ViewEvent::class); - $eventProphecy->getControllerResult()->willReturn($dummy); - $eventProphecy->getRequest()->willReturn($request); + $event = new ViewEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MASTER_REQUEST, + $dummy + ); $validationViewListener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); - $validationViewListener->onKernelView($eventProphecy->reveal()); + $validationViewListener->onKernelView($event); } public function testThrowsValidationExceptionWithViolationsFound() From c18439adac471f0f502236b0de4bafff5178b9f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 28 Oct 2020 08:23:50 +0100 Subject: [PATCH 07/27] fix: Behat setup --- behat.yml.dist | 154 +++++++----------- features/authorization/deny.feature | 1 + .../Behat}/CommandContext.php | 11 +- .../Behat}/CoverageContext.php | 2 + .../Behat}/DoctrineContext.php | 4 +- .../Behat}/ElasticsearchContext.php | 2 + .../Behat}/GraphqlContext.php | 2 + .../Behat}/HttpCacheContext.php | 9 +- .../Behat}/HydraContext.php | 8 +- .../Behat}/JsonApiContext.php | 4 +- .../bootstrap => tests/Behat}/JsonContext.php | 3 + .../Behat}/JsonHalContext.php | 2 + .../Behat/OpenApiContext.php | 4 +- tests/Fixtures/app/config/config_behat.yml | 13 ++ .../app/config/config_elasticsearch.yml | 5 + tests/Fixtures/app/config/config_test.yml | 1 + 16 files changed, 121 insertions(+), 104 deletions(-) rename {features/bootstrap => tests/Behat}/CommandContext.php (91%) rename {features/bootstrap => tests/Behat}/CoverageContext.php (97%) rename {features/bootstrap => tests/Behat}/DoctrineContext.php (99%) rename {features/bootstrap => tests/Behat}/ElasticsearchContext.php (98%) rename {features/bootstrap => tests/Behat}/GraphqlContext.php (99%) rename {features/bootstrap => tests/Behat}/HttpCacheContext.php (84%) rename {features/bootstrap => tests/Behat}/HydraContext.php (97%) rename {features/bootstrap => tests/Behat}/JsonApiContext.php (98%) rename {features/bootstrap => tests/Behat}/JsonContext.php (96%) rename {features/bootstrap => tests/Behat}/JsonHalContext.php (98%) rename features/bootstrap/SwaggerContext.php => tests/Behat/OpenApiContext.php (98%) create mode 100644 tests/Fixtures/app/config/config_behat.yml diff --git a/behat.yml.dist b/behat.yml.dist index 4f98e135d3b..8a0677ad94a 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -2,22 +2,17 @@ default: suites: default: contexts: - - 'CommandContext' - - 'DoctrineContext': - doctrine: '@doctrine' - passwordEncoder: '@security.password_encoder' - - 'GraphqlContext' - - 'JsonContext' - - 'HydraContext' - - 'SwaggerContext' - - 'HttpCacheContext' - - 'JsonApiContext': - doctrine: '@doctrine' - jsonApiSchemaFile: '%paths.base%/tests/Fixtures/JsonSchema/jsonapi.json' - - 'JsonHalContext': - schemaFile: '%paths.base%/tests/Fixtures/JsonHal/jsonhal.json' + - 'ApiPlatform\Core\Tests\Behat\CommandContext' + - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Core\Tests\Behat\HydraContext' + - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'Behat\MinkExtension\Context\MinkContext' - - 'Behatch\Context\RestContext' + - 'behatch:context:rest' filters: tags: '~@postgres&&~@mongodb&&~@elasticsearch&&~@legacy' extensions: @@ -26,6 +21,7 @@ default: kernel: environment: 'test' debug: true + class: AppKernel path: 'tests/Fixtures/app/AppKernel.php' 'Behat\MinkExtension': base_url: 'http://example.com/' @@ -40,22 +36,17 @@ postgres: default: false postgres: &postgres-suite contexts: - - 'CommandContext' - - 'DoctrineContext': - doctrine: '@doctrine' - passwordEncoder: '@security.password_encoder' - - 'GraphqlContext' - - 'JsonContext' - - 'HydraContext' - - 'SwaggerContext' - - 'HttpCacheContext' - - 'JsonApiContext': - doctrine: '@doctrine' - jsonApiSchemaFile: '%paths.base%/tests/Fixtures/JsonSchema/jsonapi.json' - - 'JsonHalContext': - schemaFile: '%paths.base%/tests/Fixtures/JsonHal/jsonhal.json' + - 'ApiPlatform\Core\Tests\Behat\CommandContext' + - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Core\Tests\Behat\HydraContext' + - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'Behat\MinkExtension\Context\MinkContext' - - 'Behatch\Context\RestContext' + - 'behatch:context:rest' filters: tags: '~@sqlite&&~@mongodb&&~@elasticsearch&&~@legacy' @@ -64,22 +55,17 @@ mongodb: default: false mongodb: &mongodb-suite contexts: - - 'CommandContext' - - 'DoctrineContext': - doctrine: '@doctrine_mongodb' - passwordEncoder: '@security.password_encoder' - - 'GraphqlContext' - - 'JsonContext' - - 'HydraContext' - - 'SwaggerContext' - - 'HttpCacheContext' - - 'JsonApiContext': - doctrine: '@doctrine_mongodb' - jsonApiSchemaFile: '%paths.base%/tests/Fixtures/JsonSchema/jsonapi.json' - - 'JsonHalContext': - schemaFile: '%paths.base%/tests/Fixtures/JsonHal/jsonhal.json' + - 'ApiPlatform\Core\Tests\Behat\CommandContext' + - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Core\Tests\Behat\HydraContext' + - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' - 'Behat\MinkExtension\Context\MinkContext' - - 'Behatch\Context\RestContext' + - 'behatch:context:rest' filters: tags: '~@sqlite&&~@elasticsearch&&~@!mongodb&&~@legacy' @@ -90,14 +76,11 @@ elasticsearch: paths: - '%paths.base%/features/elasticsearch' contexts: - - 'CommandContext' - - 'ElasticsearchContext': - client: '@test.api_platform.elasticsearch.client' - elasticsearchMappingsPath: '%paths.base%/tests/Fixtures/Elasticsearch/Mappings/' - elasticsearchFixturesPath: '%paths.base%/tests/Fixtures/Elasticsearch/Fixtures/' - - 'JsonContext' - - 'Behatch\Context\RestContext' + - 'ApiPlatform\Core\Tests\Behat\CommandContext' + - 'ApiPlatform\Core\Tests\Behat\ElasticsearchContext' + - 'ApiPlatform\Core\Tests\Behat\JsonContext' - 'Behat\MinkExtension\Context\MinkContext' + - 'behatch:context:rest' filters: tags: '@elasticsearch&&~@legacy' @@ -105,23 +88,18 @@ default-coverage: suites: default: &default-coverage-suite contexts: - - 'CommandContext' - - 'DoctrineContext': - doctrine: '@doctrine' - passwordEncoder: '@security.password_encoder' - - 'GraphqlContext' - - 'JsonContext' - - 'HydraContext' - - 'SwaggerContext' - - 'HttpCacheContext' - - 'JsonApiContext': - doctrine: '@doctrine' - jsonApiSchemaFile: '%paths.base%/tests/Fixtures/JsonSchema/jsonapi.json' - - 'JsonHalContext': - schemaFile: '%paths.base%/tests/Fixtures/JsonHal/jsonhal.json' - - 'CoverageContext' + - 'ApiPlatform\Core\Tests\Behat\CommandContext' + - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Core\Tests\Behat\HydraContext' + - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'Behat\MinkExtension\Context\MinkContext' - - 'Behatch\Context\RestContext' + - 'behatch:context:rest' mongodb-coverage: suites: @@ -129,23 +107,18 @@ mongodb-coverage: mongodb: &mongodb-coverage-suite <<: *mongodb-suite contexts: - - 'CommandContext' - - 'DoctrineContext': - doctrine: '@doctrine_mongodb' - passwordEncoder: '@security.password_encoder' - - 'GraphqlContext' - - 'JsonContext' - - 'HydraContext' - - 'SwaggerContext' - - 'HttpCacheContext' - - 'JsonApiContext': - doctrine: '@doctrine_mongodb' - jsonApiSchemaFile: '%paths.base%/tests/Fixtures/JsonSchema/jsonapi.json' - - 'JsonHalContext': - schemaFile: '%paths.base%/tests/Fixtures/JsonHal/jsonhal.json' - - 'CoverageContext' + - 'ApiPlatform\Core\Tests\Behat\CommandContext' + - 'ApiPlatform\Core\Tests\Behat\DoctrineContext' + - 'ApiPlatform\Core\Tests\Behat\GraphqlContext' + - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Core\Tests\Behat\HydraContext' + - 'ApiPlatform\Core\Tests\Behat\OpenApiContext' + - 'ApiPlatform\Core\Tests\Behat\HttpCacheContext' + - 'ApiPlatform\Core\Tests\Behat\JsonApiContext' + - 'ApiPlatform\Core\Tests\Behat\JsonHalContext' + - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'Behat\MinkExtension\Context\MinkContext' - - 'Behatch\Context\RestContext' + - 'behatch:context:rest' elasticsearch-coverage: suites: @@ -153,15 +126,12 @@ elasticsearch-coverage: elasticsearch: &elasticsearch-coverage-suite <<: *elasticsearch-suite contexts: - - 'CommandContext' - - 'ElasticsearchContext': - client: '@test.api_platform.elasticsearch.client' - elasticsearchMappingsPath: '%paths.base%/tests/Fixtures/Elasticsearch/Mappings/' - elasticsearchFixturesPath: '%paths.base%/tests/Fixtures/Elasticsearch/Fixtures/' - - 'JsonContext' - - 'CoverageContext' - - 'Behatch\Context\RestContext' + - 'ApiPlatform\Core\Tests\Behat\CommandContext' + - 'ApiPlatform\Core\Tests\Behat\ElasticsearchContext' + - 'ApiPlatform\Core\Tests\Behat\JsonContext' + - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'Behat\MinkExtension\Context\MinkContext' + - 'behatch:context:rest' default-legacy: suites: diff --git a/features/authorization/deny.feature b/features/authorization/deny.feature index 404a8c45438..774c1c6bd04 100644 --- a/features/authorization/deny.feature +++ b/features/authorization/deny.feature @@ -13,6 +13,7 @@ Feature: Authorization checking When I add "Accept" header equal to "application/ld+json" And I add "Authorization" header equal to "Basic ZHVuZ2xhczprZXZpbg==" And I send a "GET" request to "/secured_dummies" + #And print last response Then the response status code should be 200 And the response should be in JSON diff --git a/features/bootstrap/CommandContext.php b/tests/Behat/CommandContext.php similarity index 91% rename from features/bootstrap/CommandContext.php rename to tests/Behat/CommandContext.php index 5d0e7624f88..e100260cd6a 100644 --- a/features/bootstrap/CommandContext.php +++ b/tests/Behat/CommandContext.php @@ -11,9 +11,11 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + +use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; use Behat\Gherkin\Node\TableNode; -use Behat\Symfony2Extension\Context\KernelAwareContext; use PHPUnit\Framework\Assert; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Command\Command; @@ -25,7 +27,7 @@ * * @author Alan Poulain */ -final class CommandContext implements KernelAwareContext +final class CommandContext implements Context { /** * @var KernelInterface @@ -42,6 +44,11 @@ final class CommandContext implements KernelAwareContext */ private $commandTester; + public function __construct(KernelInterface $kernel) + { + $this->kernel = $kernel; + } + /** * @When I run the command :command */ diff --git a/features/bootstrap/CoverageContext.php b/tests/Behat/CoverageContext.php similarity index 97% rename from features/bootstrap/CoverageContext.php rename to tests/Behat/CoverageContext.php index da47854ffcd..05bf6589dee 100644 --- a/features/bootstrap/CoverageContext.php +++ b/tests/Behat/CoverageContext.php @@ -11,6 +11,8 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use SebastianBergmann\CodeCoverage\CodeCoverage; diff --git a/features/bootstrap/DoctrineContext.php b/tests/Behat/DoctrineContext.php similarity index 99% rename from features/bootstrap/DoctrineContext.php rename to tests/Behat/DoctrineContext.php index 5bd8487d67b..b0471631942 100644 --- a/features/bootstrap/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -11,6 +11,8 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Address as AddressDocument; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\Answer as AnswerDocument; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CompositeItem as CompositeItemDocument; @@ -131,7 +133,7 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UuidIdentifierDummy; use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; -use Doctrine\Common\Persistence\ManagerRegistry; +use Doctrine\Persistence\ManagerRegistry; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\SchemaTool; diff --git a/features/bootstrap/ElasticsearchContext.php b/tests/Behat/ElasticsearchContext.php similarity index 98% rename from features/bootstrap/ElasticsearchContext.php rename to tests/Behat/ElasticsearchContext.php index be613807263..d8ebecca8ac 100644 --- a/features/bootstrap/ElasticsearchContext.php +++ b/tests/Behat/ElasticsearchContext.php @@ -11,6 +11,8 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use ApiPlatform\Core\Bridge\Elasticsearch\Metadata\Document\DocumentMetadata; use Behat\Behat\Context\Context; use Elasticsearch\Client; diff --git a/features/bootstrap/GraphqlContext.php b/tests/Behat/GraphqlContext.php similarity index 99% rename from features/bootstrap/GraphqlContext.php rename to tests/Behat/GraphqlContext.php index 3541f25005a..50581ef4c84 100644 --- a/features/bootstrap/GraphqlContext.php +++ b/tests/Behat/GraphqlContext.php @@ -11,6 +11,8 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; use Behat\Behat\Hook\Scope\BeforeScenarioScope; diff --git a/features/bootstrap/HttpCacheContext.php b/tests/Behat/HttpCacheContext.php similarity index 84% rename from features/bootstrap/HttpCacheContext.php rename to tests/Behat/HttpCacheContext.php index b4d4452b552..286334317ae 100644 --- a/features/bootstrap/HttpCacheContext.php +++ b/tests/Behat/HttpCacheContext.php @@ -11,22 +11,23 @@ declare(strict_types=1); -use Behat\Symfony2Extension\Context\KernelAwareContext; +namespace ApiPlatform\Core\Tests\Behat; + +use Behat\Behat\Context\Context; use PHPUnit\Framework\ExpectationFailedException; use Symfony\Component\HttpKernel\KernelInterface; /** * @author Kévin Dunglas */ -final class HttpCacheContext implements KernelAwareContext +final class HttpCacheContext implements Context { /** * @var KernelInterface */ private $kernel; - public function setKernel(KernelInterface $kernel) - { + public function __construct(KernelInterface $kernel) { $this->kernel = $kernel; } diff --git a/features/bootstrap/HydraContext.php b/tests/Behat/HydraContext.php similarity index 97% rename from features/bootstrap/HydraContext.php rename to tests/Behat/HydraContext.php index 7f0c0868a66..92b42dcae60 100644 --- a/features/bootstrap/HydraContext.php +++ b/tests/Behat/HydraContext.php @@ -11,13 +11,15 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behatch\Context\RestContext; use PHPUnit\Framework\Assert; use PHPUnit\Framework\ExpectationFailedException; -use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; final class HydraContext implements Context { @@ -27,9 +29,9 @@ final class HydraContext implements Context private $restContext; private $propertyAccessor; - public function __construct() + public function __construct(PropertyAccessorInterface $propertyAccessor) { - $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); + $this->propertyAccessor = $propertyAccessor; } /** diff --git a/features/bootstrap/JsonApiContext.php b/tests/Behat/JsonApiContext.php similarity index 98% rename from features/bootstrap/JsonApiContext.php rename to tests/Behat/JsonApiContext.php index ff89b039704..e55fed01ac9 100644 --- a/features/bootstrap/JsonApiContext.php +++ b/tests/Behat/JsonApiContext.php @@ -11,6 +11,8 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\CircularReference as CircularReferenceDocument; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\DummyFriend as DummyFriendDocument; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\RelatedDummy as RelatedDummyDocument; @@ -23,7 +25,7 @@ use Behatch\Context\RestContext; use Behatch\Json\Json; use Behatch\Json\JsonInspector; -use Doctrine\Common\Persistence\ManagerRegistry; +use Doctrine\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManagerInterface; use JsonSchema\Validator; use PHPUnit\Framework\ExpectationFailedException; diff --git a/features/bootstrap/JsonContext.php b/tests/Behat/JsonContext.php similarity index 96% rename from features/bootstrap/JsonContext.php rename to tests/Behat/JsonContext.php index 93b6c9c1927..5bf40be2b5d 100644 --- a/features/bootstrap/JsonContext.php +++ b/tests/Behat/JsonContext.php @@ -11,7 +11,10 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase; +use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\Gherkin\Node\PyStringNode; use Behatch\Context\JsonContext as BaseJsonContext; use Behatch\HttpCall\HttpCallResultPool; diff --git a/features/bootstrap/JsonHalContext.php b/tests/Behat/JsonHalContext.php similarity index 98% rename from features/bootstrap/JsonHalContext.php rename to tests/Behat/JsonHalContext.php index 3026069d8d2..0d43ebb4d22 100644 --- a/features/bootstrap/JsonHalContext.php +++ b/tests/Behat/JsonHalContext.php @@ -11,6 +11,8 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; use Behat\Behat\Hook\Scope\BeforeScenarioScope; diff --git a/features/bootstrap/SwaggerContext.php b/tests/Behat/OpenApiContext.php similarity index 98% rename from features/bootstrap/SwaggerContext.php rename to tests/Behat/OpenApiContext.php index 61c333788c6..5117e629661 100644 --- a/features/bootstrap/SwaggerContext.php +++ b/tests/Behat/OpenApiContext.php @@ -11,6 +11,8 @@ declare(strict_types=1); +namespace ApiPlatform\Core\Tests\Behat; + use Behat\Behat\Context\Context; use Behat\Behat\Context\Environment\InitializedContextEnvironment; use Behat\Behat\Hook\Scope\BeforeScenarioScope; @@ -18,7 +20,7 @@ use PHPUnit\Framework\Assert; use PHPUnit\Framework\ExpectationFailedException; -final class SwaggerContext implements Context +final class OpenApiContext implements Context { /** * @var RestContext diff --git a/tests/Fixtures/app/config/config_behat.yml b/tests/Fixtures/app/config/config_behat.yml new file mode 100644 index 00000000000..48a3db5309d --- /dev/null +++ b/tests/Fixtures/app/config/config_behat.yml @@ -0,0 +1,13 @@ +services: + _defaults: + autowire: true + autoconfigure: true + + ApiPlatform\Core\Tests\Behat\CommandContext: ~ + ApiPlatform\Core\Tests\Behat\DoctrineContext: ~ + ApiPlatform\Core\Tests\Behat\HttpCacheContext: ~ + ApiPlatform\Core\Tests\Behat\HydraContext: ~ + ApiPlatform\Core\Tests\Behat\JsonApiContext: + $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' + ApiPlatform\Core\Tests\Behat\JsonHalContext: + $schemaFile: '%kernel.project_dir%/../JsonHal/jsonhal.json' diff --git a/tests/Fixtures/app/config/config_elasticsearch.yml b/tests/Fixtures/app/config/config_elasticsearch.yml index abb0610ccf3..16c2a25bad1 100644 --- a/tests/Fixtures/app/config/config_elasticsearch.yml +++ b/tests/Fixtures/app/config/config_elasticsearch.yml @@ -14,3 +14,8 @@ services: test.api_platform.elasticsearch.client: parent: api_platform.elasticsearch.client public: true + + ApiPlatform\Core\Tests\Behat\ElasticsearchContext: + $client: '@test.api_platform.elasticsearch.client' + $elasticsearchMappingsPath: '%kernel.project_dir%/../Elasticsearch/Mappings/' + $elasticsearchFixturesPath: '%kernel.project_dir%/../Elasticsearch/Fixtures/' diff --git a/tests/Fixtures/app/config/config_test.yml b/tests/Fixtures/app/config/config_test.yml index 8c97adbfd3c..153696ef270 100644 --- a/tests/Fixtures/app/config/config_test.yml +++ b/tests/Fixtures/app/config/config_test.yml @@ -1,5 +1,6 @@ imports: - { resource: config_common.yml } + - { resource: config_behat.yml } api_platform: doctrine_mongodb_odm: false From 0d375201e5238674c49d9f501995aaed64453f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 28 Oct 2020 16:24:35 +0100 Subject: [PATCH 08/27] disable an assertion breaking the test suite --- tests/Fixtures/TestBundle/Entity/Dummy.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index bcc1593bea7..e9d66dba83b 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -98,7 +98,8 @@ class Dummy * @var \DateTime A dummy date * * @ORM\Column(type="datetime", nullable=true) - * @Assert\DateTime + * @fixme wtf? + * @ Assert\DateTime */ public $dummyDate; From ccc4fe70b9f5e9fb079f85de30c5088849125fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 28 Oct 2020 19:07:13 +0100 Subject: [PATCH 09/27] fix some more Behat steps --- tests/Behat/HydraContext.php | 8 ++++---- tests/Behat/OpenApiContext.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/Behat/HydraContext.php b/tests/Behat/HydraContext.php index 92b42dcae60..48f5a507592 100644 --- a/tests/Behat/HydraContext.php +++ b/tests/Behat/HydraContext.php @@ -224,7 +224,7 @@ public function assertPropertyIsNotRequired(string $propertyName, string $classN * * @throws \InvalidArgumentException */ - private function getPropertyInfo(string $propertyName, string $className): stdClass + private function getPropertyInfo(string $propertyName, string $className): \stdClass { foreach ($this->getProperties($className) as $property) { if ($property->{'hydra:title'} === $propertyName) { @@ -240,7 +240,7 @@ private function getPropertyInfo(string $propertyName, string $className): stdCl * * @throws \InvalidArgumentException */ - private function getOperation(string $method, string $className): stdClass + private function getOperation(string $method, string $className): \stdClass { foreach ($this->getOperations($className) as $operation) { if ($operation->{'hydra:method'} === $method) { @@ -272,7 +272,7 @@ private function getProperties(string $className): array * * @throws \InvalidArgumentException */ - private function getClassInfo(string $className): stdClass + private function getClassInfo(string $className): \stdClass { $json = $this->getLastJsonResponse(); @@ -292,7 +292,7 @@ private function getClassInfo(string $className): stdClass * * @throws \RuntimeException */ - private function getLastJsonResponse(): stdClass + private function getLastJsonResponse(): \stdClass { if (null === $decoded = json_decode($this->restContext->getMink()->getSession()->getDriver()->getContent())) { throw new \RuntimeException('JSON response seems to be invalid'); diff --git a/tests/Behat/OpenApiContext.php b/tests/Behat/OpenApiContext.php index 5117e629661..204d959281d 100644 --- a/tests/Behat/OpenApiContext.php +++ b/tests/Behat/OpenApiContext.php @@ -151,7 +151,7 @@ public function assertPropertyIsRequiredForOpenAPi(string $propertyName, string * * @throws \InvalidArgumentException */ - private function getPropertyInfo(string $propertyName, string $className, int $specVersion = 2): stdClass + private function getPropertyInfo(string $propertyName, string $className, int $specVersion = 2): \stdClass { foreach ($this->getProperties($className, $specVersion) as $classPropertyName => $property) { if ($classPropertyName === $propertyName) { @@ -165,7 +165,7 @@ private function getPropertyInfo(string $propertyName, string $className, int $s /** * Gets all operations of a given class. */ - private function getProperties(string $className, int $specVersion = 2): stdClass + private function getProperties(string $className, int $specVersion = 2): \stdClass { return $this->getClassInfo($className, $specVersion)->{'properties'} ?? new \stdClass(); } @@ -175,7 +175,7 @@ private function getProperties(string $className, int $specVersion = 2): stdClas * * @throws \InvalidArgumentException */ - private function getClassInfo(string $className, int $specVersion = 2): stdClass + private function getClassInfo(string $className, int $specVersion = 2): \stdClass { $nodes = 2 === $specVersion ? $this->getLastJsonResponse()->{'definitions'} : $this->getLastJsonResponse()->{'components'}->{'schemas'}; foreach ($nodes as $classTitle => $classData) { @@ -192,7 +192,7 @@ private function getClassInfo(string $className, int $specVersion = 2): stdClass * * @throws \RuntimeException */ - private function getLastJsonResponse(): stdClass + private function getLastJsonResponse(): \stdClass { if (null === ($decoded = json_decode($this->restContext->getMink()->getSession()->getDriver()->getContent()))) { throw new \RuntimeException('JSON response seems to be invalid'); From 77af84118d1ce3c669db5bb327f0d6b58502bf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 28 Oct 2020 23:55:21 +0100 Subject: [PATCH 10/27] fix more Behat scenarios --- tests/Behat/CommandContext.php | 3 -- tests/Behat/HttpCacheContext.php | 5 +-- tests/Fixtures/TestBundle/Entity/User.php | 41 ++++++++++++++++++----- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/tests/Behat/CommandContext.php b/tests/Behat/CommandContext.php index e100260cd6a..c1417b51443 100644 --- a/tests/Behat/CommandContext.php +++ b/tests/Behat/CommandContext.php @@ -29,9 +29,6 @@ */ final class CommandContext implements Context { - /** - * @var KernelInterface - */ private $kernel; /** diff --git a/tests/Behat/HttpCacheContext.php b/tests/Behat/HttpCacheContext.php index 286334317ae..19113c005e7 100644 --- a/tests/Behat/HttpCacheContext.php +++ b/tests/Behat/HttpCacheContext.php @@ -22,9 +22,6 @@ */ final class HttpCacheContext implements Context { - /** - * @var KernelInterface - */ private $kernel; public function __construct(KernelInterface $kernel) { @@ -36,7 +33,7 @@ public function __construct(KernelInterface $kernel) { */ public function irisShouldBePurged(string $iris) { - $purger = $this->kernel->getContainer()->get('test.api_platform.http_cache.purger'); + $purger = $this->kernel->getContainer()->get('behat.driver.service_container')->get('test.api_platform.http_cache.purger'); $purgedIris = implode(',', $purger->getIris()); $purger->clear(); diff --git a/tests/Fixtures/TestBundle/Entity/User.php b/tests/Fixtures/TestBundle/Entity/User.php index 47a07a460b1..833b9b91018 100644 --- a/tests/Fixtures/TestBundle/Entity/User.php +++ b/tests/Fixtures/TestBundle/Entity/User.php @@ -68,36 +68,61 @@ class User implements UserInterface * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ - protected $id; + private $id; /** - * @var string + * @var string|null * * @Groups({"user"}) */ - protected $email; + private $email; /** - * @var string + * @var string|null * * @ORM\Column(type="string", length=255, nullable=true) * @Groups({"user"}) */ - protected $fullname; + private $fullname; /** - * @var string + * @var string|null * * @Groups({"user-write"}) */ - protected $plainPassword; + private $plainPassword; /** * @var string * * @Groups({"user"}) */ - protected $username; + private $username; + + public function getId(): int + { + return $this->id; + } + + public function getEmail(): string + { + return $this->email; + } + + public function setEmail(string $email): void + { + $this->email = $email; + } + + public function getPlainPassword(): ?string + { + return $this->plainPassword; + } + + public function setPlainPassword(string $plainPassword): void + { + $this->plainPassword = $plainPassword; + } /** * @param string|null $fullname From 9f7d86f14db462a72b04c91b12c3ba9613564ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 10:50:53 +0100 Subject: [PATCH 11/27] fix more Behat steps --- .../Metadata/Property/ValidatorPropertyMetadataFactory.php | 1 + tests/Fixtures/TestBundle/Entity/Dummy.php | 1 + tests/Fixtures/app/config/config_common.yml | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php b/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php index 5568720c592..c51422d1ebf 100644 --- a/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php +++ b/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php @@ -30,6 +30,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Time; +use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Constraints\Uuid; use Symfony\Component\Validator\Mapping\ClassMetadataInterface as ValidatorClassMetadataInterface; diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index e9d66dba83b..8be0ecb5a33 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -100,6 +100,7 @@ class Dummy * @ORM\Column(type="datetime", nullable=true) * @fixme wtf? * @ Assert\DateTime + * @ApiProperty(iri="http://schema.org/DateTime") */ public $dummyDate; diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index 830da1bbdb5..c011f1e3faf 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -140,6 +140,8 @@ services: ApiPlatform\Core\Tests\Fixtures\TestBundle\Controller\: resource: '../../TestBundle/Controller' + autowire: true + autoconfigure: true tags: ['controller.service_arguments'] app.config_dummy_resource.action: From b4737cab466ebed5bfa011bf3204a3aa1e334724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 11:10:57 +0100 Subject: [PATCH 12/27] fix more tests --- phpstan.neon.dist | 5 ++++- .../CachePoolClearerCacheWarmer.php | 4 +++- .../ValidationExceptionListener.php | 2 +- .../ValidatorPropertyMetadataFactory.php | 1 - src/EventListener/ExceptionListener.php | 3 +++ tests/Behat/DoctrineContext.php | 18 +++++++++--------- tests/Behat/ElasticsearchContext.php | 2 +- tests/Behat/GraphqlContext.php | 2 +- tests/Behat/HttpCacheContext.php | 3 ++- tests/Behat/HydraContext.php | 4 ++-- tests/Behat/JsonApiContext.php | 2 +- tests/Behat/JsonContext.php | 5 ++--- tests/Behat/OpenApiContext.php | 4 ++-- .../ApiPlatformExtensionTest.php | 2 -- .../ValidationExceptionListenerTest.php | 4 +--- tests/EventListener/RespondListenerTest.php | 1 - tests/EventListener/SerializeListenerTest.php | 2 -- tests/Fixtures/app/AppKernel.php | 2 +- .../EventListener/ValidateListenerTest.php | 1 - 19 files changed, 33 insertions(+), 34 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index aefdb545835..48f65ca3d9f 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -6,7 +6,7 @@ parameters: - tests/Fixtures/app/console inferPrivatePropertyTypeFromConstructor: true symfony: - container_xml_path: tests/Fixtures/app/var/cache/test/appAppKernelTestDebugContainer.xml + container_xml_path: tests/Fixtures/app/var/cache/test/AppKernelTestDebugContainer.xml constant_hassers: false bootstrapFiles: - vendor/bin/.phpunit/phpunit/vendor/autoload.php @@ -27,6 +27,9 @@ parameters: PHPUnit\Framework\Constraint\Constraint: - fail ignoreErrors: + # Deprecated integratations + - '#FOS\\UserBundle#' + - '#Nelmio\\ApiDocBundle#' # Real problems, hard to fix - '#Parameter \#2 \$dqlPart of method Doctrine\\ORM\\QueryBuilder::add\(\) expects array\|object, string given\.#' - diff --git a/src/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php b/src/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php index 6cb59ecb51d..497e5821aa1 100644 --- a/src/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php +++ b/src/Bridge/Symfony/Bundle/CacheWarmer/CachePoolClearerCacheWarmer.php @@ -37,13 +37,15 @@ public function __construct(Psr6CacheClearer $poolClearer, array $pools = []) /** * {@inheritdoc} */ - public function warmUp($cacheDirectory): void + public function warmUp($cacheDirectory) { foreach ($this->pools as $pool) { if ($this->poolClearer->hasPool($pool)) { $this->poolClearer->clearPool($pool); } } + + return []; } /** diff --git a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php index 7d9e45cd348..b50b56c7ce9 100644 --- a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php @@ -40,7 +40,7 @@ public function __construct(SerializerInterface $serializer, array $errorFormats */ public function onKernelException(ExceptionEvent $event): void { - $exception = method_exists($event, 'getThrowable') ? $event->getThrowable() : $event->getException(); + $exception = method_exists($event, 'getException') ? $event->getException() : $event->getThrowable(); if (!$exception instanceof ValidationException) { return; } diff --git a/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php b/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php index c51422d1ebf..5568720c592 100644 --- a/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php +++ b/src/Bridge/Symfony/Validator/Metadata/Property/ValidatorPropertyMetadataFactory.php @@ -30,7 +30,6 @@ use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Time; -use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Constraints\Url; use Symfony\Component\Validator\Constraints\Uuid; use Symfony\Component\Validator\Mapping\ClassMetadataInterface as ValidatorClassMetadataInterface; diff --git a/src/EventListener/ExceptionListener.php b/src/EventListener/ExceptionListener.php index d58d2bf52c7..f7c40ca11fd 100644 --- a/src/EventListener/ExceptionListener.php +++ b/src/EventListener/ExceptionListener.php @@ -27,6 +27,9 @@ */ final class ExceptionListener { + /** + * @var ErrorListener + */ private $exceptionListener; public function __construct($controller, LoggerInterface $logger = null, $debug = false, ErrorListener $errorListener = null) diff --git a/tests/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php index b0471631942..4119fd39079 100644 --- a/tests/Behat/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -133,10 +133,10 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\UuidIdentifierDummy; use Behat\Behat\Context\Context; use Behat\Gherkin\Node\PyStringNode; -use Doctrine\Persistence\ManagerRegistry; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\SchemaTool; +use Doctrine\Persistence\ManagerRegistry; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; /** @@ -619,9 +619,9 @@ public function thereAreDummyObjectsWithDummyDateAndDummyBoolean(int $nb, string { $descriptions = ['Smart dummy.', 'Not so smart dummy.']; - if (in_array($bool, ['true', '1', 1], true)) { + if (\in_array($bool, ['true', '1', 1], true)) { $bool = true; - } elseif (in_array($bool, ['false', '0', 0], true)) { + } elseif (\in_array($bool, ['false', '0', 0], true)) { $bool = false; } else { $expected = ['true', 'false', '1', '0']; @@ -789,9 +789,9 @@ public function thereAreDummyObjectsWithDummyPrice(int $nb) */ public function thereAreDummyObjectsWithDummyBoolean(int $nb, string $bool) { - if (in_array($bool, ['true', '1', 1], true)) { + if (\in_array($bool, ['true', '1', 1], true)) { $bool = true; - } elseif (in_array($bool, ['false', '0', 0], true)) { + } elseif (\in_array($bool, ['false', '0', 0], true)) { $bool = false; } else { $expected = ['true', 'false', '1', '0']; @@ -817,9 +817,9 @@ public function thereAreDummyObjectsWithDummyBoolean(int $nb, string $bool) */ public function thereAreDummyObjectsWithEmbeddedDummyBoolean(int $nb, string $bool) { - if (in_array($bool, ['true', '1', 1], true)) { + if (\in_array($bool, ['true', '1', 1], true)) { $bool = true; - } elseif (in_array($bool, ['false', '0', 0], true)) { + } elseif (\in_array($bool, ['false', '0', 0], true)) { $bool = false; } else { $expected = ['true', 'false', '1', '0']; @@ -844,9 +844,9 @@ public function thereAreDummyObjectsWithEmbeddedDummyBoolean(int $nb, string $bo */ public function thereAreDummyObjectsWithRelationEmbeddedDummyBoolean(int $nb, string $bool) { - if (in_array($bool, ['true', '1', 1], true)) { + if (\in_array($bool, ['true', '1', 1], true)) { $bool = true; - } elseif (in_array($bool, ['false', '0', 0], true)) { + } elseif (\in_array($bool, ['false', '0', 0], true)) { $bool = false; } else { $expected = ['true', 'false', '1', '0']; diff --git a/tests/Behat/ElasticsearchContext.php b/tests/Behat/ElasticsearchContext.php index d8ebecca8ac..d3f4e8f1384 100644 --- a/tests/Behat/ElasticsearchContext.php +++ b/tests/Behat/ElasticsearchContext.php @@ -128,7 +128,7 @@ private function loadFixtures(): void $bulk[] = $document; - if (0 === (count($bulk) % 50)) { + if (0 === (\count($bulk) % 50)) { $this->client->bulk(['body' => $bulk]); $bulk = []; } diff --git a/tests/Behat/GraphqlContext.php b/tests/Behat/GraphqlContext.php index 50581ef4c84..6cc1d3feb14 100644 --- a/tests/Behat/GraphqlContext.php +++ b/tests/Behat/GraphqlContext.php @@ -112,7 +112,7 @@ public function iHaveTheFollowingFilesForAGraphqlRequest(TableNode $table) throw new \InvalidArgumentException('You must provide a "name" and "file" column in your table node.'); } - $files[$row['name']] = $this->restContext->getMinkParameter('files_path').DIRECTORY_SEPARATOR.$row['file']; + $files[$row['name']] = $this->restContext->getMinkParameter('files_path').\DIRECTORY_SEPARATOR.$row['file']; } $this->graphqlRequest['files'] = $files; diff --git a/tests/Behat/HttpCacheContext.php b/tests/Behat/HttpCacheContext.php index 19113c005e7..26e49e83e20 100644 --- a/tests/Behat/HttpCacheContext.php +++ b/tests/Behat/HttpCacheContext.php @@ -24,7 +24,8 @@ final class HttpCacheContext implements Context { private $kernel; - public function __construct(KernelInterface $kernel) { + public function __construct(KernelInterface $kernel) + { $this->kernel = $kernel; } diff --git a/tests/Behat/HydraContext.php b/tests/Behat/HydraContext.php index 48f5a507592..ef8177a1b92 100644 --- a/tests/Behat/HydraContext.php +++ b/tests/Behat/HydraContext.php @@ -144,7 +144,7 @@ public function assertOperationNodeValueContains(string $nodeName, string $opera */ public function assertNbOperationsExist(int $nb, string $className) { - Assert::assertEquals($nb, count($this->getOperations($className))); + Assert::assertEquals($nb, \count($this->getOperations($className))); } /** @@ -152,7 +152,7 @@ public function assertNbOperationsExist(int $nb, string $className) */ public function assertNbPropertiesExist(int $nb, string $className) { - Assert::assertEquals($nb, count($this->getProperties($className))); + Assert::assertEquals($nb, \count($this->getProperties($className))); } /** diff --git a/tests/Behat/JsonApiContext.php b/tests/Behat/JsonApiContext.php index e55fed01ac9..3d26fd627e9 100644 --- a/tests/Behat/JsonApiContext.php +++ b/tests/Behat/JsonApiContext.php @@ -25,8 +25,8 @@ use Behatch\Context\RestContext; use Behatch\Json\Json; use Behatch\Json\JsonInspector; -use Doctrine\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManagerInterface; +use Doctrine\Persistence\ManagerRegistry; use JsonSchema\Validator; use PHPUnit\Framework\ExpectationFailedException; diff --git a/tests/Behat/JsonContext.php b/tests/Behat/JsonContext.php index 5bf40be2b5d..58bcb24ede6 100644 --- a/tests/Behat/JsonContext.php +++ b/tests/Behat/JsonContext.php @@ -14,7 +14,6 @@ namespace ApiPlatform\Core\Tests\Behat; use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase; -use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\Gherkin\Node\PyStringNode; use Behatch\Context\JsonContext as BaseJsonContext; use Behatch\HttpCall\HttpCallResultPool; @@ -64,14 +63,14 @@ public function theJsonIsASupersetOf(PyStringNode $content) private function sortArrays($obj) { - $isObject = is_object($obj); + $isObject = \is_object($obj); foreach ($obj as $key => $value) { if (null === $value || is_scalar($value)) { continue; } - if (is_array($value)) { + if (\is_array($value)) { sort($value); } diff --git a/tests/Behat/OpenApiContext.php b/tests/Behat/OpenApiContext.php index 204d959281d..00e65fd62ec 100644 --- a/tests/Behat/OpenApiContext.php +++ b/tests/Behat/OpenApiContext.php @@ -131,7 +131,7 @@ public function assertPropertyExistForTheOpenApiClass(string $propertyName, stri */ public function assertPropertyIsRequiredForSwagger(string $propertyName, string $className) { - if (!in_array($propertyName, $this->getClassInfo($className)->required, true)) { + if (!\in_array($propertyName, $this->getClassInfo($className)->required, true)) { throw new ExpectationFailedException(sprintf('Property "%s" of class "%s" should be required', $propertyName, $className)); } } @@ -141,7 +141,7 @@ public function assertPropertyIsRequiredForSwagger(string $propertyName, string */ public function assertPropertyIsRequiredForOpenAPi(string $propertyName, string $className) { - if (!in_array($propertyName, $this->getClassInfo($className, 3)->required, true)) { + if (!\in_array($propertyName, $this->getClassInfo($className, 3)->required, true)) { throw new ExpectationFailedException(sprintf('Property "%s" of class "%s" should be required', $propertyName, $className)); } } diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 2bdaf9066c4..14084e54a45 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -89,7 +89,6 @@ use Prophecy\Exception\Doubler\MethodNotFoundException; use Symfony\Bundle\SecurityBundle\SecurityBundle; use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\Alias; @@ -100,7 +99,6 @@ use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Response; diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php index ac870e129b9..7151e553f36 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php @@ -17,7 +17,6 @@ use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ExceptionEvent; @@ -36,8 +35,7 @@ public function testNotValidationException() { $listener = new ValidationExceptionListener( $this->prophesize(SerializerInterface::class)->reveal(), - ['hydra' => ['application/ld+json']]) - ; + ['hydra' => ['application/ld+json']]); $event = new ExceptionEvent($this->prophesize(HttpKernelInterface::class)->reveal(), new Request(), HttpKernelInterface::MASTER_REQUEST, new \Exception()); $listener->onKernelException($event); diff --git a/tests/EventListener/RespondListenerTest.php b/tests/EventListener/RespondListenerTest.php index 2c5488717ef..3f800caefb1 100644 --- a/tests/EventListener/RespondListenerTest.php +++ b/tests/EventListener/RespondListenerTest.php @@ -19,7 +19,6 @@ use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ViewEvent; diff --git a/tests/EventListener/SerializeListenerTest.php b/tests/EventListener/SerializeListenerTest.php index a0eee535f19..c5329baf2fb 100644 --- a/tests/EventListener/SerializeListenerTest.php +++ b/tests/EventListener/SerializeListenerTest.php @@ -23,7 +23,6 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Serializer\Encoder\EncoderInterface; @@ -139,7 +138,6 @@ public function testSerializeCollectionOperation() $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->setRequestFormat('xml'); $event = new ViewEvent( diff --git a/tests/Fixtures/app/AppKernel.php b/tests/Fixtures/app/AppKernel.php index 9a102b984f4..dc387c557cb 100644 --- a/tests/Fixtures/app/AppKernel.php +++ b/tests/Fixtures/app/AppKernel.php @@ -134,7 +134,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], 'entity' => [ 'entity' => [ - 'class' => User::class, + 'class' => User::class, 'property' => 'email', ], ], diff --git a/tests/Validator/EventListener/ValidateListenerTest.php b/tests/Validator/EventListener/ValidateListenerTest.php index dcb6b4e25b3..b5cdaa9046b 100644 --- a/tests/Validator/EventListener/ValidateListenerTest.php +++ b/tests/Validator/EventListener/ValidateListenerTest.php @@ -23,7 +23,6 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; From 7ab113bfc6d26ea6d430cfbd3144fb171fa37b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 15:14:19 +0100 Subject: [PATCH 13/27] Update features/authorization/deny.feature --- features/authorization/deny.feature | 1 - 1 file changed, 1 deletion(-) diff --git a/features/authorization/deny.feature b/features/authorization/deny.feature index 774c1c6bd04..404a8c45438 100644 --- a/features/authorization/deny.feature +++ b/features/authorization/deny.feature @@ -13,7 +13,6 @@ Feature: Authorization checking When I add "Accept" header equal to "application/ld+json" And I add "Authorization" header equal to "Basic ZHVuZ2xhczprZXZpbg==" And I send a "GET" request to "/secured_dummies" - #And print last response Then the response status code should be 200 And the response should be in JSON From 2de69b565e7d9ef41cd47d5aac85cda8c8bb1576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 15:14:27 +0100 Subject: [PATCH 14/27] Update phpstan.neon.dist --- phpstan.neon.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 48f65ca3d9f..b79e7ab1f71 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -27,7 +27,7 @@ parameters: PHPUnit\Framework\Constraint\Constraint: - fail ignoreErrors: - # Deprecated integratations + # Deprecated integrations - '#FOS\\UserBundle#' - '#Nelmio\\ApiDocBundle#' # Real problems, hard to fix From 10479c75d01c543a053354c639cc235c7567bee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 15:14:33 +0100 Subject: [PATCH 15/27] Update src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php Co-authored-by: Joseph Bielawski --- src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php index 45ace3866b1..94136ebb1c5 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php @@ -109,7 +109,7 @@ public function getConfigTreeBuilder() ->end() ->booleanNode('enable_fos_user') ->defaultValue(class_exists(FOSUserBundle::class)) - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'FOSUser is not actively maintained anymore. Enabling the NelmioApiDocBundle integration has been deprecated in 2.5 and will be removed in 3.0.')) + ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'FOSUser is not actively maintained anymore. Enabling the FOSUserBundle integration has been deprecated in 2.5 and will be removed in 3.0.')) ->info('Enable the FOSUserBundle integration.') ->end() ->booleanNode('enable_nelmio_api_doc') From 1cd4c963fada146bd1e2dcfaa36dad4fde692d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 17:51:13 +0100 Subject: [PATCH 16/27] fix: PHPStan --- phpstan.neon.dist | 16 +++++++--------- .../DependencyInjection/Configuration.php | 2 +- .../ValidationExceptionListener.php | 2 +- src/EventListener/ExceptionListener.php | 2 +- src/Security/ResourceAccessChecker.php | 8 ++++---- tests/Action/ExceptionActionTest.php | 9 ++++----- tests/Behat/DoctrineContext.php | 19 +++++++++++++------ tests/Behat/GraphqlContext.php | 16 +++++++++++----- tests/Behat/HydraContext.php | 10 ++++++++-- tests/Behat/JsonApiContext.php | 10 ++++++++-- tests/Behat/JsonContext.php | 2 +- tests/Behat/JsonHalContext.php | 10 ++++++++-- tests/Behat/OpenApiContext.php | 16 +++++++++++++--- .../ApiPlatformExtensionTest.php | 6 +++++- tests/Fixtures/TestBundle/Document/User.php | 2 ++ tests/Fixtures/TestBundle/Entity/Dummy.php | 2 -- tests/Fixtures/TestBundle/Entity/User.php | 2 ++ .../Serializer/ObjectNormalizerTest.php | 8 ++++---- 18 files changed, 93 insertions(+), 49 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b79e7ab1f71..b64479518ef 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -14,7 +14,14 @@ parameters: - src/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php - tests/Fixtures/app/AppKernel.php excludes_analyse: + # Symfony cache - tests/Fixtures/app/var/cache + # Deprecated integrations (will be removed in API Platform 3) + - src/Bridge/NelmioApiDoc/* + - tests/Bridge/NelmioApiDoc/* + - src/Bridge/FosUser/* + # BC layer + - tests/Fixtures/TestBundle/BrowserKit/Client.php # The Symfony Configuration API isn't good enough to be analysed - src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php # Phpstan runs on phpunit > 9, a signature changed in this file @@ -27,9 +34,6 @@ parameters: PHPUnit\Framework\Constraint\Constraint: - fail ignoreErrors: - # Deprecated integrations - - '#FOS\\UserBundle#' - - '#Nelmio\\ApiDocBundle#' # Real problems, hard to fix - '#Parameter \#2 \$dqlPart of method Doctrine\\ORM\\QueryBuilder::add\(\) expects array\|object, string given\.#' - @@ -55,10 +59,6 @@ parameters: - message: '#Call to an undefined method Negotiation\\AcceptHeader::getType\(\)\.#' path: src/EventListener/AddFormatListener.php - # https://github.com/symfony/symfony/issues/31814#issuecomment-498749590 - - - message: '#Call to an undefined method Symfony\\Component\\Security\\Core\\Role\\RoleHierarchyInterface::getReachableRoles\(\)\.#' - path: src/Security/ResourceAccessChecker.php - '#Parameter \#1 \$vars of class GraphQL\\Language\\AST\\(IntValue|ObjectField|ObjectValue|BooleanValue|ListValue|StringValue)Node constructor expects array, array given\.#' - '#Parameter \#1 \$defaultContext of class Symfony\\Component\\Serializer\\Encoder\\Json(De|En)code constructor expects array, (int|true) given\.#' - '#Parameter \#(2|3) \$(resourceMetadataFactory|pagination) of class ApiPlatform\\Core\\Bridge\\Doctrine\\Orm\\Extension\\PaginationExtension constructor expects (ApiPlatform\\Core\\Metadata\\Resource\\Factory\\ResourceMetadataFactoryInterface\|Symfony\\Component\\HttpFoundation\\RequestStack|ApiPlatform\\Core\\DataProvider\\Pagination\|ApiPlatform\\Core\\Metadata\\Resource\\Factory\\ResourceMetadataFactoryInterface), stdClass given\.#' @@ -66,7 +66,6 @@ parameters: message: '#Parameter \#[0-9] \$filterLocator of class .+ constructor expects ApiPlatform\\Core\\Api\\FilterCollection|Psr\\Container\\ContainerInterface, ArrayObject given\.#' paths: - tests/Bridge/Doctrine/Orm/Extension/FilterExtensionTest.php - - tests/Bridge/NelmioApiDoc/Extractor/AnnotationsProvider/ApiPlatformProviderTest.php - tests/Hydra/Serializer/CollectionFiltersNormalizerTest.php - tests/Swagger/Serializer/DocumentationNormalizerV2Test.php - tests/Swagger/Serializer/DocumentationNormalizerV3Test.php @@ -124,7 +123,6 @@ parameters: - message: "#Call to function method_exists\\(\\) with ApiPlatform\\\\Core\\\\JsonApi\\\\Serializer\\\\ItemNormalizer and 'setCircularReferenc…' will always evaluate to false\\.#" path: tests/JsonApi/Serializer/ItemNormalizerTest.php - # Waiting to be fixed by https://github.com/Roave/BetterReflection/issues/663 - message: '#Call to private method getNestedFieldPath\(\) of class ApiPlatform\\Core\\Bridge\\Elasticsearch\\DataProvider\\Filter\\AbstractFilter\.#' diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php index 94136ebb1c5..b9c3b38812f 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php @@ -109,7 +109,7 @@ public function getConfigTreeBuilder() ->end() ->booleanNode('enable_fos_user') ->defaultValue(class_exists(FOSUserBundle::class)) - ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'FOSUser is not actively maintained anymore. Enabling the FOSUserBundle integration has been deprecated in 2.5 and will be removed in 3.0.')) + ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'FOSUserBundle is not actively maintained anymore. Enabling the FOSUserBundle integration has been deprecated in 2.5 and will be removed in 3.0.')) ->info('Enable the FOSUserBundle integration.') ->end() ->booleanNode('enable_nelmio_api_doc') diff --git a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php index b50b56c7ce9..5f72211c5e5 100644 --- a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php @@ -40,7 +40,7 @@ public function __construct(SerializerInterface $serializer, array $errorFormats */ public function onKernelException(ExceptionEvent $event): void { - $exception = method_exists($event, 'getException') ? $event->getException() : $event->getThrowable(); + $exception = method_exists($event, 'getThrowable') ? $event->getThrowable() : $event->getException(); // @phpstan-ignore-line if (!$exception instanceof ValidationException) { return; } diff --git a/src/EventListener/ExceptionListener.php b/src/EventListener/ExceptionListener.php index f7c40ca11fd..e089ff370ba 100644 --- a/src/EventListener/ExceptionListener.php +++ b/src/EventListener/ExceptionListener.php @@ -34,7 +34,7 @@ final class ExceptionListener public function __construct($controller, LoggerInterface $logger = null, $debug = false, ErrorListener $errorListener = null) { - $this->exceptionListener = $errorListener ? new ErrorListener($controller, $logger, $debug) : new LegacyExceptionListener($controller, $logger, $debug); + $this->exceptionListener = $errorListener ? new ErrorListener($controller, $logger, $debug) : new LegacyExceptionListener($controller, $logger, $debug); // @phpstan-ignore-line } public function onKernelException(ExceptionEvent $event): void diff --git a/src/Security/ResourceAccessChecker.php b/src/Security/ResourceAccessChecker.php index c516de8f56a..6b308141307 100644 --- a/src/Security/ResourceAccessChecker.php +++ b/src/Security/ResourceAccessChecker.php @@ -81,15 +81,15 @@ private function getVariables(TokenInterface $token): array private function getEffectiveRoles(TokenInterface $token): array { if (null === $this->roleHierarchy) { - return method_exists($token, 'getRoleNames') ? $token->getRoleNames() : array_map('strval', $token->getRoles()); + return method_exists($token, 'getRoleNames') ? $token->getRoleNames() : array_map('strval', $token->getRoles()); // @phpstan-ignore-line } if (method_exists($this->roleHierarchy, 'getReachableRoleNames')) { return $this->roleHierarchy->getReachableRoleNames($token->getRoleNames()); } - return array_map(function (Role $role): string { - return $role->getRole(); - }, $this->roleHierarchy->getReachableRoles($token->getRoles())); + return array_map(function (Role $role): string { // @phpstan-ignore-line + return $role->getRole(); // @phpstan-ignore-line + }, $this->roleHierarchy->getReachableRoles($token->getRoles())); // @phpstan-ignore-line } } diff --git a/tests/Action/ExceptionActionTest.php b/tests/Action/ExceptionActionTest.php index 794b2b8ff9b..6d7a7164958 100644 --- a/tests/Action/ExceptionActionTest.php +++ b/tests/Action/ExceptionActionTest.php @@ -17,7 +17,8 @@ use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\Tests\ProphecyTrait; use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; +use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Serializer\Exception\ExceptionInterface; @@ -39,8 +40,7 @@ public function testActionWithCatchableException() if (!is_a(ExceptionInterface::class, \Throwable::class, true)) { $serializerException->willExtend(\Exception::class); } - $flattenException = FlattenException::create($serializerException->reveal()); - + $flattenException = class_exists(FlattenException::class) ? FlattenException::create($serializerException->reveal()) : LegacyFlattenException::create($serializerException->reveal()); /** @phpstan-ignore-line */ $serializer = $this->prophesize(SerializerInterface::class); $serializer->serialize($flattenException, 'jsonproblem', ['statusCode' => Response::HTTP_BAD_REQUEST])->willReturn(); @@ -64,8 +64,7 @@ public function testActionWithUncatchableException() $serializerException->willExtend(\Exception::class); } - $flattenException = FlattenException::create($serializerException->reveal()); - + $flattenException = class_exists(FlattenException::class) ? FlattenException::create($serializerException->reveal()) : LegacyFlattenException::create($serializerException->reveal()); /** @phpstan-ignore-line */ $serializer = $this->prophesize(SerializerInterface::class); $serializer->serialize($flattenException, 'jsonproblem', ['statusCode' => $flattenException->getStatusCode()])->willReturn(); diff --git a/tests/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php index 4119fd39079..d0bafa2ed69 100644 --- a/tests/Behat/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -137,6 +137,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\ManagerRegistry; +use Doctrine\Persistence\ObjectManager; use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; /** @@ -145,7 +146,7 @@ final class DoctrineContext implements Context { /** - * @var EntityManagerInterface|DocumentManager + * @var ObjectManager */ private $manager; private $doctrine; @@ -176,10 +177,16 @@ public function __construct(ManagerRegistry $doctrine, UserPasswordEncoderInterf */ public function createDatabase() { - $this->isOrm() && $this->schemaTool->dropSchema($this->classes); - $this->isOdm() && $this->schemaManager->dropDatabases(); + if ($this->isOrm()) { + $this->schemaTool->dropSchema($this->classes); + $this->schemaTool->createSchema($this->classes); + } + + if ($this->isOdm()) { + $this->schemaManager->dropDatabases(); + } + $this->doctrine->getManager()->clear(); - $this->isOrm() && $this->schemaTool->createSchema($this->classes); } /** @@ -460,7 +467,7 @@ public function thereAreDummyDtoNoOutputObjects(int $nb) for ($i = 1; $i <= $nb; ++$i) { $dummyDto = $this->buildDummyDtoNoOutput(); $dummyDto->lorem = 'DummyDtoNoOutput foo #'.$i; - $dummyDto->ipsum = $i / 3; + $dummyDto->ipsum = (string) ($i / 3); $this->manager->persist($dummyDto); } @@ -1356,7 +1363,7 @@ public function thereAreNbDummyDtoCustom($nb) for ($i = 0; $i < $nb; ++$i) { $dto = $this->isOrm() ? new DummyDtoCustom() : new DummyDtoCustomDocument(); $dto->lorem = 'test'; - $dto->ipsum = (string) $i + 1; + $dto->ipsum = (string) ($i + 1); $this->manager->persist($dto); } diff --git a/tests/Behat/GraphqlContext.php b/tests/Behat/GraphqlContext.php index 6cc1d3feb14..813bcd9f94f 100644 --- a/tests/Behat/GraphqlContext.php +++ b/tests/Behat/GraphqlContext.php @@ -59,9 +59,15 @@ public function __construct(Request $request) */ public function gatherContexts(BeforeScenarioScope $scope) { - /** @var InitializedContextEnvironment $environment */ + /** + * @var InitializedContextEnvironment $environment + */ $environment = $scope->getEnvironment(); - $this->restContext = $environment->getContext(RestContext::class); + /** + * @var RestContext $restContext + */ + $restContext = $environment->getContext(RestContext::class); + $this->restContext = $restContext; } /** @@ -135,8 +141,8 @@ public function iSendTheFollowingGraphqlMultipartRequestOperations(PyStringNode $params['operations'] = $string->getRaw(); $params['map'] = $this->graphqlRequest['map']; - $this->request->setHttpHeader('Content-type', 'multipart/form-data'); - $this->request->send('POST', '/graphql', $params, $this->graphqlRequest['files']); + $this->request->setHttpHeader('Content-type', 'multipart/form-data'); // @phpstan-ignore-line + $this->request->send('POST', '/graphql', $params, $this->graphqlRequest['files']); // @phpstan-ignore-line } /** @@ -153,7 +159,7 @@ public function ISendTheQueryToIntrospectTheSchema() */ public function theGraphQLFieldIsDeprecatedForTheReason(string $fieldName, string $reason) { - foreach (json_decode($this->request->getContent(), true)['data']['__type']['fields'] as $field) { + foreach (json_decode($this->request->getContent(), true)['data']['__type']['fields'] as $field) { // @phpstan-ignore-line if ($fieldName === $field['name'] && $field['isDeprecated'] && $reason === $field['deprecationReason']) { return; } diff --git a/tests/Behat/HydraContext.php b/tests/Behat/HydraContext.php index ef8177a1b92..9ac151d6148 100644 --- a/tests/Behat/HydraContext.php +++ b/tests/Behat/HydraContext.php @@ -41,9 +41,15 @@ public function __construct(PropertyAccessorInterface $propertyAccessor) */ public function gatherContexts(BeforeScenarioScope $scope) { - /** @var InitializedContextEnvironment $environment */ + /** + * @var InitializedContextEnvironment $environment + */ $environment = $scope->getEnvironment(); - $this->restContext = $environment->getContext(RestContext::class); + /** + * @var RestContext $restContext + */ + $restContext = $environment->getContext(RestContext::class); + $this->restContext = $restContext; } /** diff --git a/tests/Behat/JsonApiContext.php b/tests/Behat/JsonApiContext.php index 3d26fd627e9..805e74525a7 100644 --- a/tests/Behat/JsonApiContext.php +++ b/tests/Behat/JsonApiContext.php @@ -60,9 +60,15 @@ public function __construct(ManagerRegistry $doctrine, string $jsonApiSchemaFile */ public function gatherContexts(BeforeScenarioScope $scope) { - /** @var InitializedContextEnvironment $environment */ + /** + * @var InitializedContextEnvironment $environment + */ $environment = $scope->getEnvironment(); - $this->restContext = $environment->getContext(RestContext::class); + /** + * @var RestContext $restContext + */ + $restContext = $environment->getContext(RestContext::class); + $this->restContext = $restContext; } /** diff --git a/tests/Behat/JsonContext.php b/tests/Behat/JsonContext.php index 58bcb24ede6..aca91dcf4c9 100644 --- a/tests/Behat/JsonContext.php +++ b/tests/Behat/JsonContext.php @@ -58,7 +58,7 @@ public function theJsonIsASupersetOf(PyStringNode $content) $subset = json_decode($content->getRaw(), true); // Compatibility with PHPUnit 7 - method_exists(Assert::class, 'assertArraySubset') ? Assert::assertArraySubset($subset, $array) : ApiTestCase::assertArraySubset($subset, $array); + method_exists(Assert::class, 'assertArraySubset') ? Assert::assertArraySubset($subset, $array) : ApiTestCase::assertArraySubset($subset, $array); // @phpstan-ignore-line } private function sortArrays($obj) diff --git a/tests/Behat/JsonHalContext.php b/tests/Behat/JsonHalContext.php index 0d43ebb4d22..48a2c325490 100644 --- a/tests/Behat/JsonHalContext.php +++ b/tests/Behat/JsonHalContext.php @@ -47,9 +47,15 @@ public function __construct(string $schemaFile) */ public function gatherContexts(BeforeScenarioScope $scope) { - /** @var InitializedContextEnvironment $environment */ + /** + * @var InitializedContextEnvironment $environment + */ $environment = $scope->getEnvironment(); - $this->restContext = $environment->getContext(RestContext::class); + /** + * @var RestContext $restContext + */ + $restContext = $environment->getContext(RestContext::class); + $this->restContext = $restContext; } /** diff --git a/tests/Behat/OpenApiContext.php b/tests/Behat/OpenApiContext.php index 00e65fd62ec..59d9035b5a4 100644 --- a/tests/Behat/OpenApiContext.php +++ b/tests/Behat/OpenApiContext.php @@ -34,9 +34,15 @@ final class OpenApiContext implements Context */ public function gatherContexts(BeforeScenarioScope $scope) { - /** @var InitializedContextEnvironment $environment */ + /** + * @var InitializedContextEnvironment $environment + */ $environment = $scope->getEnvironment(); - $this->restContext = $environment->getContext(RestContext::class); + /** + * @var RestContext $restContext + */ + $restContext = $environment->getContext(RestContext::class); + $this->restContext = $restContext; } /** @@ -153,7 +159,11 @@ public function assertPropertyIsRequiredForOpenAPi(string $propertyName, string */ private function getPropertyInfo(string $propertyName, string $className, int $specVersion = 2): \stdClass { - foreach ($this->getProperties($className, $specVersion) as $classPropertyName => $property) { + /** + * @var iterable $properties + */ + $properties = $this->getProperties($className, $specVersion); + foreach ($properties as $classPropertyName => $property) { if ($classPropertyName === $propertyName) { return $property; } diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 14084e54a45..1376d38586d 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -275,10 +275,14 @@ public function testEnableProfilerWithDebug() */ public function testEnableNelmioApiDoc() { + if (!class_exists(NelmioApiDocBundle::class)) { + $this->markTestSkipped('NelmioApiDocBundle is not installed.'); + } + $containerBuilderProphecy = $this->getBaseContainerBuilderProphecy(); $containerBuilderProphecy->getParameter('kernel.bundles')->willReturn([ 'DoctrineBundle' => DoctrineBundle::class, - 'NelmioApiDocBundle' => NelmioApiDocBundle::class, + 'NelmioApiDocBundle' => NelmioApiDocBundle::class, // @phpstan-ignore-line ])->shouldBeCalled(); $containerBuilderProphecy->setDefinition('api_platform.nelmio_api_doc.annotations_provider', Argument::type(Definition::class))->shouldBeCalled(); $containerBuilderProphecy->setDefinition('api_platform.nelmio_api_doc.parser', Argument::type(Definition::class))->shouldBeCalled(); diff --git a/tests/Fixtures/TestBundle/Document/User.php b/tests/Fixtures/TestBundle/Document/User.php index 97e17a49ab4..c625cda8b1e 100644 --- a/tests/Fixtures/TestBundle/Document/User.php +++ b/tests/Fixtures/TestBundle/Document/User.php @@ -120,10 +120,12 @@ public function getRoles(): array public function getPassword() { + return null; } public function getSalt() { + return null; } public function eraseCredentials() diff --git a/tests/Fixtures/TestBundle/Entity/Dummy.php b/tests/Fixtures/TestBundle/Entity/Dummy.php index 8be0ecb5a33..af81454acb1 100644 --- a/tests/Fixtures/TestBundle/Entity/Dummy.php +++ b/tests/Fixtures/TestBundle/Entity/Dummy.php @@ -98,8 +98,6 @@ class Dummy * @var \DateTime A dummy date * * @ORM\Column(type="datetime", nullable=true) - * @fixme wtf? - * @ Assert\DateTime * @ApiProperty(iri="http://schema.org/DateTime") */ public $dummyDate; diff --git a/tests/Fixtures/TestBundle/Entity/User.php b/tests/Fixtures/TestBundle/Entity/User.php index 833b9b91018..1b907fd6680 100644 --- a/tests/Fixtures/TestBundle/Entity/User.php +++ b/tests/Fixtures/TestBundle/Entity/User.php @@ -156,10 +156,12 @@ public function getRoles(): array public function getPassword() { + return null; } public function getSalt() { + return null; } public function eraseCredentials() diff --git a/tests/JsonLd/Serializer/ObjectNormalizerTest.php b/tests/JsonLd/Serializer/ObjectNormalizerTest.php index bcc77a7ab20..8803496a8fe 100644 --- a/tests/JsonLd/Serializer/ObjectNormalizerTest.php +++ b/tests/JsonLd/Serializer/ObjectNormalizerTest.php @@ -48,7 +48,7 @@ public function testNormalize() '@id' => '_:1234', ]); - $normalizer = new ObjectNormalizer( + $normalizer = new ObjectNormalizer( // @phpstan-ignore-line $serializerProphecy->reveal(), $iriConverterProphecy->reveal(), $contextBuilderProphecy->reveal() @@ -77,7 +77,7 @@ public function testNormalizeEmptyArray() $contextBuilderProphecy = $this->prophesize(AnonymousContextBuilderInterface::class); $contextBuilderProphecy->getAnonymousResourceContext($dummy, Argument::type('array'))->shouldNotBeCalled(); - $normalizer = new ObjectNormalizer( + $normalizer = new ObjectNormalizer( // @phpstan-ignore-line $serializerProphecy->reveal(), $iriConverterProphecy->reveal(), $contextBuilderProphecy->reveal() @@ -101,7 +101,7 @@ public function testNormalizeWithOutput() $contextBuilderProphecy = $this->prophesize(AnonymousContextBuilderInterface::class); $contextBuilderProphecy->getAnonymousResourceContext($dummy, ['iri' => '/dummy/1234', 'api_resource' => $dummy])->shouldBeCalled()->willReturn(['@id' => '/dummy/1234', '@type' => 'Dummy', '@context' => []]); - $normalizer = new ObjectNormalizer( + $normalizer = new ObjectNormalizer( // @phpstan-ignore-line $serializerProphecy->reveal(), $iriConverterProphecy->reveal(), $contextBuilderProphecy->reveal() @@ -131,7 +131,7 @@ public function testNormalizeWithContext() $contextBuilderProphecy = $this->prophesize(AnonymousContextBuilderInterface::class); $contextBuilderProphecy->getAnonymousResourceContext($dummy, ['iri' => '/dummy/1234', 'api_resource' => $dummy, 'has_context' => true])->shouldBeCalled()->willReturn(['@id' => '/dummy/1234', '@type' => 'Dummy']); - $normalizer = new ObjectNormalizer( + $normalizer = new ObjectNormalizer( // @phpstan-ignore-line $serializerProphecy->reveal(), $iriConverterProphecy->reveal(), $contextBuilderProphecy->reveal() From 60e3b2ff269831dbf69fc83d6e9c07c5916e945f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 18:05:12 +0100 Subject: [PATCH 17/27] remove remaining FOSUser config --- tests/Fixtures/app/config/config_mongodb.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/Fixtures/app/config/config_mongodb.yml b/tests/Fixtures/app/config/config_mongodb.yml index 3b1e3d353d2..b245d34a78a 100644 --- a/tests/Fixtures/app/config/config_mongodb.yml +++ b/tests/Fixtures/app/config/config_mongodb.yml @@ -22,14 +22,6 @@ api_platform: - '%kernel.project_dir%/../TestBundle/Model' - '%kernel.project_dir%/config/api_resources_mongodb_odm.yaml' -fos_user: - db_driver: 'mongodb' - firewall_name: 'api' - user_class: 'ApiPlatform\Core\Tests\Fixtures\TestBundle\Document\User' - from_email: - address: 'no-reply@les-tilleuls.coop' - sender_name: 'Kévin Dunglas' - services: app.my_dummy_resource.mongodb.boolean_filter: parent: 'api_platform.doctrine_mongodb.odm.boolean_filter' From bd4eae1e83be4544fbbbc18908d6fd0b76c32c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 29 Oct 2020 23:52:57 +0100 Subject: [PATCH 18/27] some more fixes --- .github/workflows/ci.yml | 2 -- behat.yml.dist | 4 ++-- phpunit.xml.dist | 1 + phpunit_mongodb.xml | 1 + 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3116f52b712..9f35c8270ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -687,7 +687,6 @@ jobs: fail-fast: false timeout-minutes: 20 env: - LEGACY: '1' SYMFONY_REQUIRE: '^3.4 || ^4.0' steps: - name: Checkout @@ -835,7 +834,6 @@ jobs: fail-fast: false timeout-minutes: 20 env: - LEGACY: '1' SYMFONY_REQUIRE: '^3.4 || ^4.0' steps: - name: Checkout diff --git a/behat.yml.dist b/behat.yml.dist index 8a0677ad94a..b76166b7c4f 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -137,11 +137,11 @@ default-legacy: suites: default: filters: - tags: '~@postgres&&~@mongodb&&~@elasticsearch' + tags: '~@postgres&&~@mongodb&&~@elasticsearch~@legacy' default-legacy-coverage: suites: default: <<: *default-coverage-suite filters: - tags: '~@postgres&&~@mongodb&&~@elasticsearch' + tags: '~@postgres&&~@mongodb&&~@elasticsearch~@legacy' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 22df90c7d87..a9c000759c7 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -32,6 +32,7 @@ features tests vendor + src/Bridge/NelmioApiDoc src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php diff --git a/phpunit_mongodb.xml b/phpunit_mongodb.xml index 051f8f9e583..0ef9e7e4d5b 100644 --- a/phpunit_mongodb.xml +++ b/phpunit_mongodb.xml @@ -29,6 +29,7 @@ features tests vendor + src/Bridge/NelmioApiDoc src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php From e03563163a265369c8b665ea05d28ec964439aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 30 Oct 2020 00:47:28 +0100 Subject: [PATCH 19/27] fix lowest deps --- composer.json | 2 +- tests/Fixtures/app/config/config_behat.yml | 4 +++- tests/Fixtures/app/config/config_common.yml | 3 +++ tests/Fixtures/app/config/config_mongodb.yml | 8 ++++++++ tests/Fixtures/app/config/config_test.yml | 1 - 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index a4bd9e20a70..db66343993c 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "doctrine/annotations": "^1.7", "doctrine/common": "^2.11 || ^3.0", "doctrine/data-fixtures": "^1.2.2", - "doctrine/doctrine-bundle": "^1.8 || ^2.0", + "doctrine/doctrine-bundle": "^1.12 || ^2.0", "doctrine/mongodb-odm": "^2.0", "doctrine/mongodb-odm-bundle": "^4.0", "doctrine/orm": "^2.6.4 || ^3.0", diff --git a/tests/Fixtures/app/config/config_behat.yml b/tests/Fixtures/app/config/config_behat.yml index 48a3db5309d..4133d556f9f 100644 --- a/tests/Fixtures/app/config/config_behat.yml +++ b/tests/Fixtures/app/config/config_behat.yml @@ -4,10 +4,12 @@ services: autoconfigure: true ApiPlatform\Core\Tests\Behat\CommandContext: ~ - ApiPlatform\Core\Tests\Behat\DoctrineContext: ~ + ApiPlatform\Core\Tests\Behat\DoctrineContext: + $doctrine: '@doctrine' ApiPlatform\Core\Tests\Behat\HttpCacheContext: ~ ApiPlatform\Core\Tests\Behat\HydraContext: ~ ApiPlatform\Core\Tests\Behat\JsonApiContext: + $doctrine: '@doctrine' $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' ApiPlatform\Core\Tests\Behat\JsonHalContext: $schemaFile: '%kernel.project_dir%/../JsonHal/jsonhal.json' diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index c011f1e3faf..720fb103c83 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -1,3 +1,6 @@ +imports: + - { resource: config_behat.yml } + framework: secret: 'dunglas.fr' validation: diff --git a/tests/Fixtures/app/config/config_mongodb.yml b/tests/Fixtures/app/config/config_mongodb.yml index b245d34a78a..331a7ac82c6 100644 --- a/tests/Fixtures/app/config/config_mongodb.yml +++ b/tests/Fixtures/app/config/config_mongodb.yml @@ -117,3 +117,11 @@ services: public: false tags: - { name: 'messenger.message_handler' } + + ApiPlatform\Core\Tests\Behat\DoctrineContext: + $doctrine: '@doctrine_mongodb' + $passwordEncoder: '@security.password_encoder' + + ApiPlatform\Core\Tests\Behat\JsonApiContext: + $doctrine: '@doctrine_mongodb' + $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' diff --git a/tests/Fixtures/app/config/config_test.yml b/tests/Fixtures/app/config/config_test.yml index 153696ef270..8c97adbfd3c 100644 --- a/tests/Fixtures/app/config/config_test.yml +++ b/tests/Fixtures/app/config/config_test.yml @@ -1,6 +1,5 @@ imports: - { resource: config_common.yml } - - { resource: config_behat.yml } api_platform: doctrine_mongodb_odm: false From e40404835e3839d466924f8f0e38fc74dffe50a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 30 Oct 2020 01:12:08 +0100 Subject: [PATCH 20/27] wip --- .../Fixtures/app/config/config_behat_mongodb.yml | 15 +++++++++++++++ .../{config_behat.yml => config_behat_orm.yml} | 0 tests/Fixtures/app/config/config_common.yml | 3 --- tests/Fixtures/app/config/config_mongodb.yml | 9 +-------- tests/Fixtures/app/config/config_test.yml | 1 + 5 files changed, 17 insertions(+), 11 deletions(-) create mode 100644 tests/Fixtures/app/config/config_behat_mongodb.yml rename tests/Fixtures/app/config/{config_behat.yml => config_behat_orm.yml} (100%) diff --git a/tests/Fixtures/app/config/config_behat_mongodb.yml b/tests/Fixtures/app/config/config_behat_mongodb.yml new file mode 100644 index 00000000000..7c69457562f --- /dev/null +++ b/tests/Fixtures/app/config/config_behat_mongodb.yml @@ -0,0 +1,15 @@ +services: + _defaults: + autowire: true + autoconfigure: true + + ApiPlatform\Core\Tests\Behat\CommandContext: ~ + ApiPlatform\Core\Tests\Behat\DoctrineContext: + $doctrine: '@doctrine_mongodb' + ApiPlatform\Core\Tests\Behat\HttpCacheContext: ~ + ApiPlatform\Core\Tests\Behat\HydraContext: ~ + ApiPlatform\Core\Tests\Behat\JsonApiContext: + $doctrine: '@doctrine_mongodb' + $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' + ApiPlatform\Core\Tests\Behat\JsonHalContext: + $schemaFile: '%kernel.project_dir%/../JsonHal/jsonhal.json' diff --git a/tests/Fixtures/app/config/config_behat.yml b/tests/Fixtures/app/config/config_behat_orm.yml similarity index 100% rename from tests/Fixtures/app/config/config_behat.yml rename to tests/Fixtures/app/config/config_behat_orm.yml diff --git a/tests/Fixtures/app/config/config_common.yml b/tests/Fixtures/app/config/config_common.yml index 720fb103c83..c011f1e3faf 100644 --- a/tests/Fixtures/app/config/config_common.yml +++ b/tests/Fixtures/app/config/config_common.yml @@ -1,6 +1,3 @@ -imports: - - { resource: config_behat.yml } - framework: secret: 'dunglas.fr' validation: diff --git a/tests/Fixtures/app/config/config_mongodb.yml b/tests/Fixtures/app/config/config_mongodb.yml index 331a7ac82c6..15565a806d3 100644 --- a/tests/Fixtures/app/config/config_mongodb.yml +++ b/tests/Fixtures/app/config/config_mongodb.yml @@ -1,5 +1,6 @@ imports: - { resource: config_common.yml } + - { resource: config_behat_mongodb.yml } parameters: env(MONGODB_DB): api_platform_test @@ -117,11 +118,3 @@ services: public: false tags: - { name: 'messenger.message_handler' } - - ApiPlatform\Core\Tests\Behat\DoctrineContext: - $doctrine: '@doctrine_mongodb' - $passwordEncoder: '@security.password_encoder' - - ApiPlatform\Core\Tests\Behat\JsonApiContext: - $doctrine: '@doctrine_mongodb' - $jsonApiSchemaFile: '%kernel.project_dir%/../JsonSchema/jsonapi.json' diff --git a/tests/Fixtures/app/config/config_test.yml b/tests/Fixtures/app/config/config_test.yml index 8c97adbfd3c..6e4d2182897 100644 --- a/tests/Fixtures/app/config/config_test.yml +++ b/tests/Fixtures/app/config/config_test.yml @@ -1,5 +1,6 @@ imports: - { resource: config_common.yml } + - { resource: config_behat_orm.yml } api_platform: doctrine_mongodb_odm: false From 6fd9b3cfce8c86b9fab9c484a7de053a2c077e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 2 Nov 2020 19:47:02 +0100 Subject: [PATCH 21/27] upgrade some deps --- composer.json | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index db66343993c..082b093624b 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "friends-of-behat/mink-browserkit-driver": "^1.3.1", "friends-of-behat/mink-extension": "^2.2", "friends-of-behat/symfony-extension": "^2.1", - "behatch/contexts": "dev-fix/symfony-33393", + "behatch/contexts": "dev-api-platform", "doctrine/annotations": "^1.7", "doctrine/common": "^2.11 || ^3.0", "doctrine/data-fixtures": "^1.2.2", @@ -54,6 +54,7 @@ "psr/log": "^1.0", "ramsey/uuid": "^3.7 || ^4.0", "ramsey/uuid-doctrine": "^1.4", + "soyuka/stubs-mongodb": "^1.0", "symfony/asset": "^3.4 || ^4.0 || ^5.0", "symfony/browser-kit": "^4.3 || ^5.0", "symfony/cache": "^3.4 || ^4.0 || ^5.0", @@ -80,7 +81,6 @@ "symfony/validator": "^3.4 || ^4.0 || ^5.0", "symfony/web-profiler-bundle": "^4.2 || ^5.0", "symfony/yaml": "^3.4 || ^4.0 || ^5.0", - "teohhanhui/stubs-mongodb": "@dev", "twig/twig": "^1.42.3 || ^2.12 || ^3.0", "webonyx/graphql-php": "^14.0" }, @@ -115,10 +115,6 @@ } }, "repositories": [ - { - "type": "vcs", - "url": "https://github.com/teohhanhui/stubs-mongodb" - }, { "type": "vcs", "url": "https://github.com/dunglas/contexts" From 9cde61fb633733d9f721330fd509cdb6bbb844d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 2 Nov 2020 20:06:50 +0100 Subject: [PATCH 22/27] Try to fix tests --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f35c8270ed..e5767acdd6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -251,6 +251,13 @@ jobs: - name: Install PHPUnit run: vendor/bin/simple-phpunit --version - name: Clear test app cache + if: (!startsWith(matrix.php, 'rc')) + run: | + mkdir -p /tmp/api-platform/core/var + ln -s /tmp/api-platform/core/var tests/Fixtures/app/var + tests/Fixtures/app/console cache:clear --ansi + - name: Clear test app cache (PHP 8) + if: (startsWith(matrix.php, 'rc')) run: | mkdir -p /tmp/api-platform/core/var ln -s /tmp/api-platform/core/var tests/Fixtures/app/var From 03850fe15bf91120a0ce901baf98b93e4f598af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 2 Nov 2020 20:57:02 +0100 Subject: [PATCH 23/27] bump property access --- .github/workflows/ci.yml | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5767acdd6f..330e026dafc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: env: COMPOSER_ALLOW_SUPERUSER: '1' # https://getcomposer.org/doc/03-cli.md#composer-allow-superuser COMPOSER_INSTALLER_COMMIT: fb22b78362d31c0d2bf516d1f8cdfd2745caa431 - COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} COVERAGE: '0' EXT_MONGODB_VERSION: '1.7.5' EXT_PCOV_VERSION: '1.0.6' diff --git a/composer.json b/composer.json index 082b093624b..4102812ce35 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "psr/container": "^1.0", "symfony/http-foundation": "^4.3.6 || ^5.0", "symfony/http-kernel": "^4.3.7 || ^5.0", - "symfony/property-access": "^3.4 || ^4.0 || ^5.0", + "symfony/property-access": "^3.4.19 || ^4.1.8 || ^5.0", "symfony/property-info": "^3.4 || ^4.0 || ^5.0", "symfony/serializer": "^4.3 || ^5.0", "symfony/web-link": "^4.1 || ^5.0", From 44f8acff0c6901a2ede2bd6831d84e91f279a505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 2 Nov 2020 21:55:00 +0100 Subject: [PATCH 24/27] remove support for unmaintained Symfony versions --- .github/workflows/ci.yml | 2 +- composer.json | 64 ++++++++++++++++++++-------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 330e026dafc..53f17e3036a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -261,7 +261,7 @@ jobs: run: | mkdir -p /tmp/api-platform/core/var ln -s /tmp/api-platform/core/var tests/Fixtures/app/var - tests/Fixtures/app/console cache:clear --ansi + rm -Rf tests/Fixtures/app/var/cache/* - name: Enable code coverage if: matrix.coverage run: echo '::set-env name=COVERAGE::1' diff --git a/composer.json b/composer.json index 4102812ce35..1c65da52cd3 100644 --- a/composer.json +++ b/composer.json @@ -18,12 +18,12 @@ "fig/link-util": "^1.0", "psr/cache": "^1.0", "psr/container": "^1.0", - "symfony/http-foundation": "^4.3.6 || ^5.0", - "symfony/http-kernel": "^4.3.7 || ^5.0", - "symfony/property-access": "^3.4.19 || ^4.1.8 || ^5.0", - "symfony/property-info": "^3.4 || ^4.0 || ^5.0", - "symfony/serializer": "^4.3 || ^5.0", - "symfony/web-link": "^4.1 || ^5.0", + "symfony/http-foundation": "^4.4 || ^5.1", + "symfony/http-kernel": "^4.4 || ^5.1", + "symfony/property-access": "^3.4.19 || ^4.4 || ^5.1", + "symfony/property-info": "^3.4 || ^4.4 || ^5.1", + "symfony/serializer": "^4.4 || ^5.1", + "symfony/web-link": "^4.4 || ^5.1", "willdurand/negotiation": "^2.0.3 || 3.0.x-dev" }, "require-dev": { @@ -44,7 +44,7 @@ "guzzlehttp/guzzle": "^6.0 || ^7.0", "jangregor/phpstan-prophecy": "^0.8", "justinrainbow/json-schema": "^5.2.1", - "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.0", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.1", "phpdocumentor/type-resolver": "^0.3 || ^0.4 || ^1.4", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^0.12.4", @@ -55,32 +55,32 @@ "ramsey/uuid": "^3.7 || ^4.0", "ramsey/uuid-doctrine": "^1.4", "soyuka/stubs-mongodb": "^1.0", - "symfony/asset": "^3.4 || ^4.0 || ^5.0", - "symfony/browser-kit": "^4.3 || ^5.0", - "symfony/cache": "^3.4 || ^4.0 || ^5.0", - "symfony/config": "^3.4 || ^4.0 || ^5.0", - "symfony/console": "^3.4 || ^4.0 || ^5.0", - "symfony/css-selector": "^3.4 || ^4.0 || ^5.0", - "symfony/debug": "^3.4 || ^4.0 || ^5.0", - "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0", - "symfony/doctrine-bridge": "^3.4 || ^4.0 || ^5.0", - "symfony/dom-crawler": "^3.4 || ^4.0 || ^5.0", - "symfony/event-dispatcher": "^3.4 || ^4.0 || ^5.0", - "symfony/expression-language": "^3.4 || ^4.0 || ^5.0", - "symfony/finder": "^3.4 || ^4.0 || ^5.0", - "symfony/form": "^3.4 || ^4.0 || ^5.0", - "symfony/framework-bundle": "^4.3.2 || ^5.0", - "symfony/http-client": "^4.3 || ^5.0", + "symfony/asset": "^3.4 || ^4.4 || ^5.1", + "symfony/browser-kit": "^4.4 || ^5.1", + "symfony/cache": "^3.4 || ^4.4 || ^5.1", + "symfony/config": "^3.4 || ^4.4 || ^5.1", + "symfony/console": "^3.4 || ^4.4 || ^5.1", + "symfony/css-selector": "^3.4 || ^4.4 || ^5.1", + "symfony/debug": "^3.4 || ^4.4 || ^5.1", + "symfony/dependency-injection": "^3.4 || ^4.4 || ^5.1", + "symfony/doctrine-bridge": "^3.4 || ^4.4 || ^5.1", + "symfony/dom-crawler": "^3.4 || ^4.4 || ^5.1", + "symfony/event-dispatcher": "^3.4 || ^4.4 || ^5.1", + "symfony/expression-language": "^3.4 || ^4.4 || ^5.1", + "symfony/finder": "^3.4 || ^4.4 || ^5.1", + "symfony/form": "^3.4 || ^4.4 || ^5.1", + "symfony/framework-bundle": "^4.4 || ^5.1", + "symfony/http-client": "^4.4 || ^5.1", "symfony/mercure-bundle": "*", - "symfony/messenger": "^4.3 || ^5.0", + "symfony/messenger": "^4.4 || ^5.1", "symfony/phpunit-bridge": "^5.1.7", - "symfony/routing": "^3.4 || ^4.3 || ^5.0", - "symfony/security-bundle": "^3.4 || ^4.0 || ^5.0", - "symfony/security-core": "^4.3 || ^5.0", - "symfony/twig-bundle": "^3.4 || ^4.0 || ^5.0", - "symfony/validator": "^3.4 || ^4.0 || ^5.0", - "symfony/web-profiler-bundle": "^4.2 || ^5.0", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0", + "symfony/routing": "^3.4 || ^4.4 || ^5.1", + "symfony/security-bundle": "^3.4 || ^4.4 || ^5.1", + "symfony/security-core": "^4.4 || ^5.1", + "symfony/twig-bundle": "^3.4 || ^4.4 || ^5.1", + "symfony/validator": "^3.4 || ^4.4 || ^5.1", + "symfony/web-profiler-bundle": "^4.4 || ^5.1", + "symfony/yaml": "^3.4 || ^4.4 || ^5.1", "twig/twig": "^1.42.3 || ^2.12 || ^3.0", "webonyx/graphql-php": "^14.0" }, @@ -131,7 +131,7 @@ "dev-master": "2.5.x-dev" }, "symfony": { - "require": "^3.4 || ^4.0 || ^5.0" + "require": "^3.4 || ^4.4 || ^5.1" } } } From 53531d229abf03a57daabb616b32c842dfca619a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 2 Nov 2020 22:30:30 +0100 Subject: [PATCH 25/27] remove legacy tests --- .github/workflows/ci.yml | 243 ------------------------- behat.yml.dist | 21 +-- features/legacy/fos_user.feature | 37 ---- features/legacy/nelmio_api_doc.feature | 17 -- phpunit.xml.dist | 1 + 5 files changed, 5 insertions(+), 314 deletions(-) delete mode 100644 features/legacy/fos_user.feature delete mode 100644 features/legacy/nelmio_api_doc.feature diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53f17e3036a..ff9522acd1a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -674,249 +674,6 @@ jobs: path: build/out/openapi continue-on-error: true - behat-legacy: - name: Behat (PHP ${{ matrix.php }}) (legacy) - runs-on: ubuntu-latest - container: - image: php:${{ matrix.php }}-alpine - options: >- - --tmpfs /tmp:exec - --tmpfs /var/tmp:exec - strategy: - matrix: - php: - - '7.1' - - '7.2' - - '7.3' - include: - - php: '7.3' - coverage: true - fail-fast: false - timeout-minutes: 20 - env: - SYMFONY_REQUIRE: '^3.4 || ^4.0' - steps: - - name: Checkout - uses: actions/checkout@v1 - - name: Install system packages - run: | - apk add \ - bash \ - unzip \ - git openssh - - name: Cache mongodb PHP extension build - if: (!startsWith(matrix.php, '7.1')) - uses: actions/cache@v2 - with: - path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} - key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} - restore-keys: | - ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - continue-on-error: true - - name: Install mongodb PHP extension - if: (!startsWith(matrix.php, '7.1')) - env: - BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} - SRC_DIR: /usr/src/php/ext/mongodb - run: | - apk add \ - $PHPIZE_DEPS - mkdir -p "$SRC_DIR" "$BUILD_DIR" - cd "$SRC_DIR" - curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 - phpize - cd "$BUILD_DIR" - "$SRC_DIR"/configure --config-cache - make -j"$(nproc)" - make -j"$(nproc)" install - docker-php-ext-enable mongodb - - name: Install pcov PHP extension - if: matrix.coverage - env: - BUILD_DIR: /var/tmp/build/ext-pcov-${{ env.EXT_PCOV_VERSION }} - SRC_DIR: /usr/src/php/ext/pcov - run: | - apk add \ - $PHPIZE_DEPS - mkdir -p "$SRC_DIR" "$BUILD_DIR" - cd "$SRC_DIR" - curl -fsSL "https://pecl.php.net/get/pcov-$EXT_PCOV_VERSION.tgz" | tar -zx --strip-components 1 - phpize - cd "$BUILD_DIR" - "$SRC_DIR"/configure --config-cache - make -j"$(nproc)" - make -j"$(nproc)" install - docker-php-ext-enable pcov - - name: Disable PHP memory limit - run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - - name: Install Composer - run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet - - name: Cache Composer packages - uses: actions/cache@v2 - with: - path: ~/.composer/cache - key: composer-php${{ matrix.php }}-legacy-${{ github.sha }} - restore-keys: | - composer-php${{ matrix.php }}-legacy- - composer-php${{ matrix.php }}- - composer- - continue-on-error: true - - name: Install Symfony Flex - run: | - composer global require --prefer-dist --no-progress --no-suggest --ansi \ - symfony/flex - - name: Remove Doctrine MongoDB ODM - if: startsWith(matrix.php, '7.1') - run: | - composer remove --dev --no-progress --no-update --ansi \ - doctrine/mongodb-odm \ - doctrine/mongodb-odm-bundle \ - - name: Update project dependencies - run: | - mkdir -p /tmp/api-platform/core/vendor - ln -s /tmp/api-platform/core/vendor vendor - composer update --no-progress --no-suggest --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: | - mkdir -p /tmp/api-platform/core/var - ln -s /tmp/api-platform/core/var tests/Fixtures/app/var - tests/Fixtures/app/console cache:clear --ansi - - name: Enable code coverage - if: matrix.coverage - run: echo '::set-env name=COVERAGE::1' - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - if [ "$COVERAGE" = '1' ]; then - vendor/bin/behat --format=progress --out=std --format=junit --out=build/logs/behat/junit --profile=default-legacy-coverage --no-interaction --colors - else - vendor/bin/behat --format=progress --out=std --format=junit --out=build/logs/behat/junit --profile=default-legacy --no-interaction --colors - fi - - name: Merge code coverage reports - if: matrix.coverage - run: | - wget -qO /usr/local/bin/phpcov https://phar.phpunit.de/phpcov.phar - chmod +x /usr/local/bin/phpcov - phpcov merge --clover build/logs/behat/clover.xml build/coverage - continue-on-error: true - - name: Upload test artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: behat-logs-php${{ matrix.php }}-legacy - path: build/logs/behat - continue-on-error: true - - name: Upload coverage results to Codecov - if: matrix.coverage - uses: codecov/codecov-action@v1 - with: - name: behat-php${{ matrix.php }}-legacy - flags: behat_legacy - fail_ci_if_error: true - continue-on-error: true - - name: Upload coverage results to Coveralls - if: matrix.coverage - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - composer global require --prefer-dist --no-progress --no-suggest --ansi cedx/coveralls - export PATH="$PATH:$HOME/.composer/vendor/bin" - coveralls build/logs/behat/clover.xml - continue-on-error: true - - behat-lowest-deps-legacy: - name: Behat (PHP ${{ matrix.php }}) (lowest dependencies) (legacy) - runs-on: ubuntu-latest - container: - image: php:${{ matrix.php }}-alpine - options: >- - --tmpfs /tmp:exec - --tmpfs /var/tmp:exec - strategy: - matrix: - php: - - '7.3' - fail-fast: false - timeout-minutes: 20 - env: - SYMFONY_REQUIRE: '^3.4 || ^4.0' - steps: - - name: Checkout - uses: actions/checkout@v1 - - name: Install system packages - run: | - apk add \ - unzip \ - git openssh - - name: Cache mongodb PHP extension build - uses: actions/cache@v2 - with: - path: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} - key: ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}-${{ github.sha }} - restore-keys: | - ext-mongodb-${{ env.EXT_MONGODB_VERSION }}-php${{ matrix.php }}- - continue-on-error: true - - name: Install mongodb PHP extension - env: - BUILD_DIR: /var/tmp/build/ext-mongodb-${{ env.EXT_MONGODB_VERSION }} - SRC_DIR: /usr/src/php/ext/mongodb - run: | - apk add \ - $PHPIZE_DEPS - mkdir -p "$SRC_DIR" "$BUILD_DIR" - cd "$SRC_DIR" - curl -fsSL "https://pecl.php.net/get/mongodb-$EXT_MONGODB_VERSION.tgz" | tar -zx --strip-components 1 - phpize - cd "$BUILD_DIR" - "$SRC_DIR"/configure --config-cache - make -j"$(nproc)" - make -j"$(nproc)" install - docker-php-ext-enable mongodb - - name: Disable PHP memory limit - run: echo 'memory_limit=-1' >> /usr/local/etc/php/php.ini - - name: Install Composer - run: wget -qO - https://raw.githubusercontent.com/composer/getcomposer.org/$COMPOSER_INSTALLER_COMMIT/web/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet - - name: Cache Composer packages - uses: actions/cache@v2 - with: - path: ~/.composer/cache - key: composer-php${{ matrix.php }}-lowest-deps-legacy-${{ github.sha }} - restore-keys: | - composer-php${{ matrix.php }}-lowest-deps-legacy- - composer-php${{ matrix.php }}-lowest-deps- - composer-php${{ matrix.php }}- - composer- - continue-on-error: true - - name: Install Symfony Flex - run: | - composer global require --prefer-dist --no-progress --no-suggest --ansi \ - symfony/flex - - name: Update project dependencies - run: | - mkdir -p /tmp/api-platform/core/vendor - ln -s /tmp/api-platform/core/vendor vendor - composer update --no-progress --no-suggest --prefer-stable --prefer-lowest --ansi - - name: Install PHPUnit - run: vendor/bin/simple-phpunit --version - - name: Clear test app cache - run: | - mkdir -p /tmp/api-platform/core/var - ln -s /tmp/api-platform/core/var tests/Fixtures/app/var - tests/Fixtures/app/console cache:clear --ansi - - name: Run Behat tests - run: | - mkdir -p build/logs/behat - vendor/bin/behat --format=progress --out=std --format=junit --out=build/logs/behat/junit --profile=default-legacy --no-interaction --colors - - name: Upload test artifacts - if: always() - uses: actions/upload-artifact@v1 - with: - name: behat-logs-php${{ matrix.php }}-lowest-deps-legacy - path: build/logs/behat - continue-on-error: true - phpunit-postgresql: name: PHPUnit (PHP ${{ matrix.php }}) (PostgreSQL) runs-on: ubuntu-latest diff --git a/behat.yml.dist b/behat.yml.dist index b76166b7c4f..72a33b5ac06 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -14,7 +14,7 @@ default: - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: - tags: '~@postgres&&~@mongodb&&~@elasticsearch&&~@legacy' + tags: '~@postgres&&~@mongodb&&~@elasticsearch' extensions: 'FriendsOfBehat\SymfonyExtension': bootstrap: 'tests/Fixtures/app/bootstrap.php' @@ -48,7 +48,7 @@ postgres: - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: - tags: '~@sqlite&&~@mongodb&&~@elasticsearch&&~@legacy' + tags: '~@sqlite&&~@mongodb&&~@elasticsearch' mongodb: suites: @@ -67,7 +67,7 @@ mongodb: - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: - tags: '~@sqlite&&~@elasticsearch&&~@!mongodb&&~@legacy' + tags: '~@sqlite&&~@elasticsearch&&~@!mongodb&&' elasticsearch: suites: @@ -82,7 +82,7 @@ elasticsearch: - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' filters: - tags: '@elasticsearch&&~@legacy' + tags: '@elasticsearch' default-coverage: suites: @@ -132,16 +132,3 @@ elasticsearch-coverage: - 'ApiPlatform\Core\Tests\Behat\CoverageContext' - 'Behat\MinkExtension\Context\MinkContext' - 'behatch:context:rest' - -default-legacy: - suites: - default: - filters: - tags: '~@postgres&&~@mongodb&&~@elasticsearch~@legacy' - -default-legacy-coverage: - suites: - default: - <<: *default-coverage-suite - filters: - tags: '~@postgres&&~@mongodb&&~@elasticsearch~@legacy' diff --git a/features/legacy/fos_user.feature b/features/legacy/fos_user.feature deleted file mode 100644 index c665839303c..00000000000 --- a/features/legacy/fos_user.feature +++ /dev/null @@ -1,37 +0,0 @@ -@legacy -Feature: FOSUser integration - In order to use FOSUserBundle - As an API software developer - I need to be able manage users - - @createSchema - Scenario: Create a user - When I add "Content-Type" header equal to "application/ld+json" - And I send a "POST" request to "/users" with body: - """ - { - "fullname": "Dummy User", - "username": "dummy.user", - "email": "dummy.user@example.com", - "plainPassword": "azerty" - } - """ - Then the response status code should be 201 - And the response should be in JSON - And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" - And the JSON should be equal to: - """ - { - "@context": "/contexts/User", - "@id": "/users/1", - "@type": "User", - "email": "dummy.user@example.com", - "fullname": "Dummy User", - "username": "dummy.user" - } - """ - And the password "azerty" for user 1 should be hashed - - Scenario: Delete a user - When I send a "DELETE" request to "/users/1" - Then the response status code should be 204 diff --git a/features/legacy/nelmio_api_doc.feature b/features/legacy/nelmio_api_doc.feature deleted file mode 100644 index 846547c2169..00000000000 --- a/features/legacy/nelmio_api_doc.feature +++ /dev/null @@ -1,17 +0,0 @@ -@legacy -Feature: NelmioApiDoc integration - In order to use NelmioApiDocBundle - As an API software developer - I need to see the generated documentation - - Scenario: Test if the NelmioApiDoc integration works - When I send a "GET" request to "/nelmioapidoc" - Then the response status code should be 200 - And I should see text matching "AbstractDummy" - And I should see text matching "Dummy" - And I should see text matching "User" - And I should see text matching "Retrieves the collection of Dummy resources." - And I should see text matching "Creates a Dummy resource." - And I should see text matching "Deletes the Dummy resource." - And I should see text matching "Updates the Dummy resource." - And I should see text matching "Replaces the Dummy resource." diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a9c000759c7..a24d73d3f0f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -33,6 +33,7 @@ tests vendor src/Bridge/NelmioApiDoc + src/Bridge/FosUser src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php From 8940ef31abc5e6848b5091f47dc00b5888c44c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 2 Nov 2020 23:07:57 +0100 Subject: [PATCH 26/27] fix Elasticsearch build --- tests/Fixtures/app/config/config_elasticsearch.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Fixtures/app/config/config_elasticsearch.yml b/tests/Fixtures/app/config/config_elasticsearch.yml index 16c2a25bad1..33162ed0a5e 100644 --- a/tests/Fixtures/app/config/config_elasticsearch.yml +++ b/tests/Fixtures/app/config/config_elasticsearch.yml @@ -16,6 +16,8 @@ services: public: true ApiPlatform\Core\Tests\Behat\ElasticsearchContext: - $client: '@test.api_platform.elasticsearch.client' - $elasticsearchMappingsPath: '%kernel.project_dir%/../Elasticsearch/Mappings/' - $elasticsearchFixturesPath: '%kernel.project_dir%/../Elasticsearch/Fixtures/' + public: true + arguments: + $client: '@test.api_platform.elasticsearch.client' + $elasticsearchMappingsPath: '%kernel.project_dir%/../Elasticsearch/Mappings/' + $elasticsearchFixturesPath: '%kernel.project_dir%/../Elasticsearch/Fixtures/' From 2e4f33a98eaff4d31d12535815869d1d4bd3f890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 5 Nov 2020 14:08:50 +0100 Subject: [PATCH 27/27] fix PHPstan --- composer.json | 2 +- phpstan.neon.dist | 4 ---- src/Identifier/Normalizer/IntegerDenormalizer.php | 2 ++ src/JsonApi/Serializer/ItemNormalizer.php | 1 + src/Serializer/AbstractItemNormalizer.php | 1 + tests/Behat/JsonContext.php | 3 +-- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 1c65da52cd3..54dda7e0795 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.1", "phpdocumentor/type-resolver": "^0.3 || ^0.4 || ^1.4", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.4", + "phpstan/phpstan": "^0.12.53@dev", "phpstan/phpstan-doctrine": "^0.12.7", "phpstan/phpstan-phpunit": "^0.12.4", "phpstan/phpstan-symfony": "^0.12.4", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b64479518ef..86461c1a5d0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -36,10 +36,6 @@ parameters: ignoreErrors: # Real problems, hard to fix - '#Parameter \#2 \$dqlPart of method Doctrine\\ORM\\QueryBuilder::add\(\) expects array\|object, string given\.#' - - - message: '#Return type \(mixed\) of method ApiPlatform\\Core\\Identifier\\Normalizer\\IntegerDenormalizer::denormalize\(\) should be compatible with return type \(array\|object\) of method Symfony\\Component\\Serializer\\Normalizer\\DenormalizerInterface::denormalize\(\)#' - path: src/Identifier/Normalizer/IntegerDenormalizer.php - # False positives - message: '#Strict comparison using !== between .+ and .+ will always evaluate to false\.#' diff --git a/src/Identifier/Normalizer/IntegerDenormalizer.php b/src/Identifier/Normalizer/IntegerDenormalizer.php index d75e1e9cf00..80888972819 100644 --- a/src/Identifier/Normalizer/IntegerDenormalizer.php +++ b/src/Identifier/Normalizer/IntegerDenormalizer.php @@ -21,6 +21,8 @@ final class IntegerDenormalizer implements DenormalizerInterface, CacheableSuppo { /** * {@inheritdoc} + * + * @phpstan-ignore-next-line this is a real problem, the parent interface cannot return int, but it's hard to fix, we'll try in v3 */ public function denormalize($data, $class, $format = null, array $context = []): int { diff --git a/src/JsonApi/Serializer/ItemNormalizer.php b/src/JsonApi/Serializer/ItemNormalizer.php index afb27e57edd..3efc74135c7 100644 --- a/src/JsonApi/Serializer/ItemNormalizer.php +++ b/src/JsonApi/Serializer/ItemNormalizer.php @@ -216,6 +216,7 @@ protected function normalizeRelation(PropertyMetadata $propertyMetadata, $relate } $normalizedRelatedObject = $this->serializer->normalize($relatedObject, $format, $context); + // @phpstan-ignore-next-line throwing an explicit exception helps debugging if (!\is_string($normalizedRelatedObject) && !\is_array($normalizedRelatedObject) && !$normalizedRelatedObject instanceof \ArrayObject && null !== $normalizedRelatedObject) { throw new UnexpectedValueException('Expected normalized relation to be an IRI, array, \ArrayObject or null'); } diff --git a/src/Serializer/AbstractItemNormalizer.php b/src/Serializer/AbstractItemNormalizer.php index bdd14483f4e..20e230287a9 100644 --- a/src/Serializer/AbstractItemNormalizer.php +++ b/src/Serializer/AbstractItemNormalizer.php @@ -607,6 +607,7 @@ protected function normalizeRelation(PropertyMetadata $propertyMetadata, $relate } $normalizedRelatedObject = $this->serializer->normalize($relatedObject, $format, $context); + // @phpstan-ignore-next-line throwing an explicit exception helps debugging if (!\is_string($normalizedRelatedObject) && !\is_array($normalizedRelatedObject) && !$normalizedRelatedObject instanceof \ArrayObject && null !== $normalizedRelatedObject) { throw new UnexpectedValueException('Expected normalized relation to be an IRI, array, \ArrayObject or null'); } diff --git a/tests/Behat/JsonContext.php b/tests/Behat/JsonContext.php index aca91dcf4c9..5cb109b7b6c 100644 --- a/tests/Behat/JsonContext.php +++ b/tests/Behat/JsonContext.php @@ -57,8 +57,7 @@ public function theJsonIsASupersetOf(PyStringNode $content) $array = json_decode($this->httpCallResultPool->getResult()->getValue(), true); $subset = json_decode($content->getRaw(), true); - // Compatibility with PHPUnit 7 - method_exists(Assert::class, 'assertArraySubset') ? Assert::assertArraySubset($subset, $array) : ApiTestCase::assertArraySubset($subset, $array); // @phpstan-ignore-line + method_exists(Assert::class, 'assertArraySubset') ? Assert::assertArraySubset($subset, $array) : ApiTestCase::assertArraySubset($subset, $array); // @phpstan-ignore-line Compatibility with PHPUnit 7 } private function sortArrays($obj)