diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad9858022..6d38a8a6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,10 +19,13 @@ jobs: - '8.0' - '8.1' - '8.2' + - '8.3' symfony-version: - '5.4.*' - '6.0.*' - '6.2.*' + - '6.4.*' + - '7.0.*' dependencies: - 'lowest' - 'highest' @@ -31,6 +34,12 @@ jobs: exclude: - php-version: '8.0' symfony-version: '6.2.*' + - php-version: '8.0' + symfony-version: '6.4.*' + - php-version: '8.0' + symfony-version: '7.0.*' + - php-version: '8.1' + symfony-version: '7.0.*' include: - php-version: '8.0' symfony-version: '5.4.*' diff --git a/composer.json b/composer.json index be7db70e5..7b031d2e0 100644 --- a/composer.json +++ b/composer.json @@ -35,15 +35,15 @@ "phpdocumentor/reflection-docblock": "^5.2", "phpdocumentor/type-resolver": "^1.6.1", "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/config": "^5.4 || ^6.0", - "symfony/dependency-injection": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/expression-language": "^5.4 || ^6.0", - "symfony/framework-bundle": "^5.4 || ^6.0", - "symfony/http-foundation": "^5.4 || ^6.0", - "symfony/http-kernel": "^5.4 || ^6.0", - "symfony/options-resolver": "^5.4 || ^6.0", - "symfony/property-access": "^5.4 || ^6.0", + "symfony/config": "^5.4 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/expression-language": "^5.4 || ^6.0 || ^7.0", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", + "symfony/http-foundation": "^5.4 || ^6.0 || ^7.0", + "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/property-access": "^5.4 || ^6.0 || ^7.0", "webonyx/graphql-php": "^15.4" }, "suggest": { @@ -55,27 +55,27 @@ "require-dev": { "doctrine/annotations": "^1.13", "doctrine/orm": "^2.5", - "monolog/monolog": "^2.8.0", + "monolog/monolog": "^2.8.0 || ^3.0", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "1.8.4", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-symfony": "^1.0", "phpunit/phpunit": "^9.5.10", "react/promise": "^2.5", - "symfony/asset": "^5.4 || ^6.0", - "symfony/browser-kit": "^5.4 || ^6.0", - "symfony/css-selector": "^5.4 || ^6.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/dom-crawler": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", + "symfony/asset": "^5.4 || ^6.0 || ^7.0", + "symfony/browser-kit": "^5.4 || ^6.0 || ^7.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/dom-crawler": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", "symfony/monolog-bundle": "^3.7", "symfony/phpunit-bridge": "^6.0", - "symfony/process": "^5.4 || ^6.0", - "symfony/routing": "^5.4 || ^6.0", - "symfony/security-bundle": "^5.4 || ^6.0", - "symfony/validator": "^5.4 || ^6.0", - "symfony/var-dumper": "^5.4 || ^6.0", - "symfony/yaml": "^5.4 || ^6.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/routing": "^5.4 || ^6.0 || ^7.0", + "symfony/security-bundle": "^5.4 || ^6.0 || ^7.0", + "symfony/validator": "^5.4 || ^6.0 || ^7.0", + "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0", "twig/twig": "^2.10|^3.0" }, "conflict": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f0b5cca59..2251606b7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -441,24 +441,24 @@ parameters: path: tests/Functional/Controller/GraphControllerTest.php - - message: "#^Method Overblog\\\\GraphQLBundle\\\\Tests\\\\Functional\\\\TestCase\\:\\:createKernel\\(\\) should return Symfony\\\\Component\\\\HttpKernel\\\\KernelInterface but returns object\\.$#" + message: "#^Method Overblog\\\\GraphQLBundle\\\\Tests\\\\Functional\\\\BaseTestCase\\:\\:createKernel\\(\\) should return Symfony\\\\Component\\\\HttpKernel\\\\KernelInterface but returns object\\.$#" count: 1 - path: tests/Functional/TestCase.php + path: tests/Functional/BaseTestCase.php - message: "#^Missing call to parent\\:\\:tearDown\\(\\) method\\.$#" count: 1 - path: tests/Functional/TestCase.php + path: tests/Functional/BaseTestCase.php - message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#" count: 1 - path: tests/Functional/TestCase.php + path: tests/Functional/BaseTestCase.php - message: "#^Parameter \\#3 \\$message of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) expects string, string\\|false given\\.$#" count: 1 - path: tests/Functional/TestCase.php + path: tests/Functional/BaseTestCase.php - message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#" diff --git a/src/CacheWarmer/CompileCacheWarmer.php b/src/CacheWarmer/CompileCacheWarmer.php index b41dbf43b..e23f17c2a 100644 --- a/src/CacheWarmer/CompileCacheWarmer.php +++ b/src/CacheWarmer/CompileCacheWarmer.php @@ -27,11 +27,9 @@ public function isOptional(): bool } /** - * @param string $cacheDir - * * @return string[] */ - public function warmUp($cacheDir) + public function warmUp(string $cacheDir, string $buildDir = null): array { if ($this->compiled) { // use warm up cache dir if type generator cache dir not already explicitly declared diff --git a/tests/ExpressionLanguage/TestCase.php b/tests/ExpressionLanguage/TestCase.php index cc0ee7c93..0db2a43d1 100644 --- a/tests/ExpressionLanguage/TestCase.php +++ b/tests/ExpressionLanguage/TestCase.php @@ -87,6 +87,7 @@ protected function getSecurityIsGrantedWithExpectation($with, $expects = null, $ $returnValue = $this->returnValue($return); } + // @phpstan-ignore-next-line $methodExpectation = $security ->expects($expects) ->method('isGranted'); @@ -96,6 +97,7 @@ protected function getSecurityIsGrantedWithExpectation($with, $expects = null, $ // @phpstan-ignore-next-line $methodExpectation->will($returnValue); + // @phpstan-ignore-next-line return new Security($security); } diff --git a/tests/Functional/App/Resolver/NodeResolver.php b/tests/Functional/App/Resolver/NodeResolver.php index cf276938f..16c3a8de8 100644 --- a/tests/Functional/App/Resolver/NodeResolver.php +++ b/tests/Functional/App/Resolver/NodeResolver.php @@ -5,13 +5,9 @@ namespace Overblog\GraphQLBundle\Tests\Functional\App\Resolver; use GraphQL\Type\Definition\ResolveInfo; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; -final class NodeResolver implements ContainerAwareInterface +final class NodeResolver { - use ContainerAwareTrait; - private array $userData = [ '1' => [ 'id' => 1, diff --git a/tests/Functional/App/TestKernel.php b/tests/Functional/App/TestKernel.php index a985a7c66..3c2c5981f 100644 --- a/tests/Functional/App/TestKernel.php +++ b/tests/Functional/App/TestKernel.php @@ -73,6 +73,16 @@ public function registerContainerConfiguration(LoaderInterface $loader): void $loader->load(__DIR__.'/config/config.yml'); } + // @phpstan-ignore-next-line + if (Kernel::VERSION_ID < 60200) { + $loader->load(__DIR__.'/config/config_pre_62.yml'); + } + + // @phpstan-ignore-next-line + if (Kernel::VERSION_ID >= 70000) { + $loader->load(__DIR__.'/config/config_post_70.yml'); + } + $loader->load(function (ContainerBuilder $container): void { $container->addCompilerPass($this); }); diff --git a/tests/Functional/App/config/config.yml b/tests/Functional/App/config/config.yml index ddc30b7da..aa96efbd5 100644 --- a/tests/Functional/App/config/config.yml +++ b/tests/Functional/App/config/config.yml @@ -9,7 +9,6 @@ framework: http_method_override: false security: - enable_authenticator_manager: true providers: in_memory: memory: diff --git a/tests/Functional/App/config/config_post_70.yml b/tests/Functional/App/config/config_post_70.yml new file mode 100644 index 000000000..b849c9793 --- /dev/null +++ b/tests/Functional/App/config/config_post_70.yml @@ -0,0 +1,2 @@ +framework: + handle_all_throwables: false diff --git a/tests/Functional/App/config/config_pre_62.yml b/tests/Functional/App/config/config_pre_62.yml new file mode 100644 index 000000000..dae2f3a66 --- /dev/null +++ b/tests/Functional/App/config/config_pre_62.yml @@ -0,0 +1,2 @@ +security: + enable_authenticator_manager: true diff --git a/tests/Functional/App/config/conflictingValidatorNamespaces/config.yml b/tests/Functional/App/config/conflictingValidatorNamespaces/config.yml index 63b530a45..42a43e07f 100644 --- a/tests/Functional/App/config/conflictingValidatorNamespaces/config.yml +++ b/tests/Functional/App/config/conflictingValidatorNamespaces/config.yml @@ -2,10 +2,8 @@ imports: - { resource: ../config.yml } framework: - annotations: true validation: enabled: true - enable_annotations: true overblog_graphql: definitions: diff --git a/tests/Functional/App/config/typeShorthand/config.yml b/tests/Functional/App/config/typeShorthand/config.yml index 6e1b1d5f4..3f2205f56 100644 --- a/tests/Functional/App/config/typeShorthand/config.yml +++ b/tests/Functional/App/config/typeShorthand/config.yml @@ -1,10 +1,8 @@ imports: - { resource: ../config.yml } framework: - annotations: true validation: enabled: true - enable_annotations: true overblog_graphql: errors_handler: @@ -15,6 +13,5 @@ overblog_graphql: query: RootQuery mappings: types: - - - type: yaml - dir: "%kernel.project_dir%/config/typeShorthand/mapping" + - type: yaml + dir: "%kernel.project_dir%/config/typeShorthand/mapping" diff --git a/tests/Functional/App/config/validator/config.yml b/tests/Functional/App/config/validator/config.yml index 93dfd1848..fa4234e3e 100644 --- a/tests/Functional/App/config/validator/config.yml +++ b/tests/Functional/App/config/validator/config.yml @@ -2,10 +2,8 @@ imports: - { resource: ../config.yml } framework: - annotations: true validation: enabled: true - enable_annotations: true overblog_graphql: definitions: @@ -38,4 +36,3 @@ services: - { name: "overblog_graphql.mutation", alias: "mutation_mock", method: "mutationMock" } - { name: "overblog_graphql.mutation", alias: "mutation_errors", method: "mutationErrors" } - { name: "overblog_graphql.mutation", alias: "no_validation", method: "noValidation" } - diff --git a/tests/Functional/BaseTestCase.php b/tests/Functional/BaseTestCase.php new file mode 100644 index 000000000..172e613b0 --- /dev/null +++ b/tests/Functional/BaseTestCase.php @@ -0,0 +1,172 @@ +remove(sys_get_temp_dir().'/OverblogGraphQLBundle/'); + } + + protected function tearDown(): void + { + static::ensureKernelShutdown(); + } + + protected static function executeGraphQLRequest(string $query, array $rootValue = [], string $schemaName = null, array $variables = []): array + { + $request = new Request(); + $request->query->set('query', $query); + if (!empty($variables)) { + $request->query->set('variables', $variables); + } + + // @phpstan-ignore-next-line + $req = static::getContainer()->get('overblog_graphql.request_parser')->parse($request); + // @phpstan-ignore-next-line + $res = static::getContainer()->get('overblog_graphql.request_executor')->execute($schemaName, $req, $rootValue); + + return $res->toArray(); + } + + protected static function assertGraphQL(string $query, array $expectedData = null, array $expectedErrors = null, array $rootValue = [], string $schemaName = null): void + { + $result = static::executeGraphQLRequest($query, $rootValue, $schemaName); + + $expected = []; + + if (null !== $expectedErrors) { + $expected['errors'] = $expectedErrors; + } + + if (null !== $expectedData) { + $expected['data'] = $expectedData; + } + + static::assertSame($expected, $result, json_encode($result)); + } + + protected static function query(string $query, string $username, string $testCase, string $password = self::DEFAULT_PASSWORD): KernelBrowser + { + $client = static::createClientAuthenticated($username, $testCase, $password); + $client->request('GET', '/', ['query' => $query]); + + return $client; + } + + protected static function createClientAuthenticated(?string $username, string $testCase, ?string $password = self::DEFAULT_PASSWORD): KernelBrowser + { + static::ensureKernelShutdown(); + $client = static::createClient(['test_case' => $testCase]); + + if (null !== $username) { + $client->setServerParameters([ + 'PHP_AUTH_USER' => $username, + 'PHP_AUTH_PW' => $password, + ]); + } + + return $client; + } + + protected static function assertResponse(string $query, array $expected, ?string $username, string $testCase, ?string $password = self::DEFAULT_PASSWORD, array $variables = null): KernelBrowser + { + $client = self::createClientAuthenticated($username, $testCase, $password); + $result = self::sendRequest($client, $query, false, $variables); + + static::assertSame($expected, json_decode($result, true), $result); + + return $client; + } + + /** + * @return mixed + */ + protected static function sendRequest(KernelBrowser $client, string $query, bool $isDecoded = false, array $variables = null) + { + $client->request('GET', '/', ['query' => $query, 'variables' => json_encode($variables)]); + $result = $client->getResponse()->getContent(); + + return $isDecoded ? json_decode($result, true) : $result; + } + + /** + * @return mixed|ExpressionFunction + */ + public static function expressionFunctionFromPhp(string $phpFunctionName) + { + if (is_callable([ExpressionFunction::class, 'fromPhp'])) { + return call_user_func([ExpressionFunction::class, 'fromPhp'], $phpFunctionName); + } + + return new ExpressionFunction($phpFunctionName, fn () => sprintf('\%s(%s)', $phpFunctionName, implode(', ', func_get_args())), function (): void {}); + } + + /** + * @param KernelBrowser $client + */ + protected function disableCatchExceptions($client): void + { + if (is_callable([$client, 'catchExceptions'])) { + $client->catchExceptions(false); + } + } +} diff --git a/tests/Functional/TestCase.php b/tests/Functional/TestCase.php index e6652e687..9ddd4af83 100644 --- a/tests/Functional/TestCase.php +++ b/tests/Functional/TestCase.php @@ -4,176 +4,26 @@ namespace Overblog\GraphQLBundle\Tests\Functional; -use Overblog\GraphQLBundle\ExpressionLanguage\ExpressionFunction; -use Overblog\GraphQLBundle\Tests\Functional\App\TestKernel; -use Symfony\Bundle\FrameworkBundle\KernelBrowser; -use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\HttpKernel\Kernel; -use function call_user_func; -use function func_get_args; -use function implode; -use function is_callable; -use function json_decode; -use function json_encode; -use function sprintf; -use function strtolower; -use function sys_get_temp_dir; - -/** - * TestCase. - */ -abstract class TestCase extends WebTestCase -{ - public const USER_RYAN = 'ryan'; - public const USER_ADMIN = 'admin'; - public const ANONYMOUS_USER = null; - public const DEFAULT_PASSWORD = '123'; - - /** - * {@inheritdoc} - */ - protected static function getKernelClass(): string - { - return TestKernel::class; - } - - /** - * {@inheritdoc} - */ - protected static function createKernel(array $options = []): KernelInterface +if (Kernel::VERSION_ID < 70000) { + abstract class TestCase extends BaseTestCase { - if (null === static::$class) { - static::$class = static::getKernelClass(); + protected static function getContainer(): ContainerInterface + { + /** @phpstan-ignore-next-line */ + return static::$kernel->getContainer(); } - - $options['test_case'] ??= ''; - - $env = $options['environment'] ?? 'test'.strtolower($options['test_case']); - $debug = $options['debug'] ?? true; - - return new static::$class($env, $debug, $options['test_case']); - } - - /** - * {@inheritdoc} - */ - public static function setUpBeforeClass(): void - { - $fs = new Filesystem(); - $fs->remove(sys_get_temp_dir().'/OverblogGraphQLBundle/'); - } - - protected function tearDown(): void - { - static::ensureKernelShutdown(); - } - - protected static function executeGraphQLRequest(string $query, array $rootValue = [], string $schemaName = null, array $variables = []): array - { - $request = new Request(); - $request->query->set('query', $query); - if (!empty($variables)) { - $request->query->set('variables', $variables); - } - - // @phpstan-ignore-next-line - $req = static::getContainer()->get('overblog_graphql.request_parser')->parse($request); - // @phpstan-ignore-next-line - $res = static::getContainer()->get('overblog_graphql.request_executor')->execute($schemaName, $req, $rootValue); - - return $res->toArray(); - } - - protected static function assertGraphQL(string $query, array $expectedData = null, array $expectedErrors = null, array $rootValue = [], string $schemaName = null): void - { - $result = static::executeGraphQLRequest($query, $rootValue, $schemaName); - - $expected = []; - - if (null !== $expectedErrors) { - $expected['errors'] = $expectedErrors; - } - - if (null !== $expectedData) { - $expected['data'] = $expectedData; - } - - static::assertSame($expected, $result, json_encode($result)); } - - protected static function getContainer(): ContainerInterface - { - /** @phpstan-ignore-next-line */ - return static::$kernel->getContainer(); - } - - protected static function query(string $query, string $username, string $testCase, string $password = self::DEFAULT_PASSWORD): KernelBrowser - { - $client = static::createClientAuthenticated($username, $testCase, $password); - $client->request('GET', '/', ['query' => $query]); - - return $client; - } - - protected static function createClientAuthenticated(?string $username, string $testCase, ?string $password = self::DEFAULT_PASSWORD): KernelBrowser - { - static::ensureKernelShutdown(); - $client = static::createClient(['test_case' => $testCase]); - - if (null !== $username) { - $client->setServerParameters([ - 'PHP_AUTH_USER' => $username, - 'PHP_AUTH_PW' => $password, - ]); - } - - return $client; - } - - protected static function assertResponse(string $query, array $expected, ?string $username, string $testCase, ?string $password = self::DEFAULT_PASSWORD, array $variables = null): KernelBrowser - { - $client = self::createClientAuthenticated($username, $testCase, $password); - $result = self::sendRequest($client, $query, false, $variables); - - static::assertSame($expected, json_decode($result, true), $result); - - return $client; - } - - /** - * @return mixed - */ - protected static function sendRequest(KernelBrowser $client, string $query, bool $isDecoded = false, array $variables = null) - { - $client->request('GET', '/', ['query' => $query, 'variables' => json_encode($variables)]); - $result = $client->getResponse()->getContent(); - - return $isDecoded ? json_decode($result, true) : $result; - } - - /** - * @return mixed|ExpressionFunction - */ - public static function expressionFunctionFromPhp(string $phpFunctionName) - { - if (is_callable([ExpressionFunction::class, 'fromPhp'])) { - return call_user_func([ExpressionFunction::class, 'fromPhp'], $phpFunctionName); - } - - return new ExpressionFunction($phpFunctionName, fn () => sprintf('\%s(%s)', $phpFunctionName, implode(', ', func_get_args())), function (): void {}); - } - - /** - * @param KernelBrowser $client - */ - protected function disableCatchExceptions($client): void +} else { + abstract class TestCase extends BaseTestCase { - if (is_callable([$client, 'catchExceptions'])) { - $client->catchExceptions(false); + protected static function getContainer(): Container + { + /** @phpstan-ignore-next-line */ + return static::$kernel->getContainer(); } } } diff --git a/tests/Functional/Validator/DummyEntity.php b/tests/Functional/Validator/DummyEntity.php index 5142d0fdb..ebc43a6fd 100644 --- a/tests/Functional/Validator/DummyEntity.php +++ b/tests/Functional/Validator/DummyEntity.php @@ -8,45 +8,32 @@ /** * Class DummyEntity. - * - * @Assert\Callback({"Overblog\GraphQLBundle\Tests\Functional\Validator\StaticValidator", "validateClass"}) */ +#[Assert\Callback([StaticValidator::class, 'validateClass'])] final class DummyEntity { - /** - * @Assert\EqualTo("Lorem Ipsum") - */ + #[Assert\EqualTo('Lorem Ipsum')] private string $string1; - /** - * @Assert\EqualTo("Lorem Ipsum") - */ + #[Assert\EqualTo('Lorem Ipsum')] private string $string2; - /** - * @Assert\EqualTo("{""text"":""Lorem Ipsum""}") - */ + #[Assert\EqualTo('{"text":"Lorem Ipsum"}')] private string $string3; - /** - * @Assert\EqualTo("Dolor Sit Amet") - */ + #[Assert\EqualTo('Dolor Sit Amet')] public function getString1(): string { return $this->string1; } - /** - * @Assert\EqualTo("Dolor Sit Amet") - */ + #[Assert\EqualTo('Dolor Sit Amet')] public function getString2(): string { return $this->string2; } - /** - * @Assert\Json() - */ + #[Assert\Json()] public function getString3(): string { return $this->string3;