From a516dc6fc04db11d9d65f8de36297babf8fc16de Mon Sep 17 00:00:00 2001 From: Aaron Gustavo Nieves <64917965+TavoNiievez@users.noreply.github.com> Date: Sat, 9 Aug 2025 14:27:12 -0500 Subject: [PATCH] Standardize to PHP 8.2 and PSR-4 (#217) --- .github/workflows/main.yml | 16 +++++++++++++--- .gitignore | 3 ++- composer.json | 14 +++++++++++--- readme.md | 2 +- src/Codeception/Module/Symfony.php | 9 +++++++-- .../Module/Symfony/BrowserAssertionsTrait.php | 6 ++---- .../Module/Symfony/ConsoleAssertionsTrait.php | 14 +++++++------- .../Module/Symfony/DomCrawlerAssertionsTrait.php | 6 ++++-- .../Module/Symfony/EventsAssertionsTrait.php | 1 + .../Module/Symfony/FormAssertionsTrait.php | 1 + .../Module/Symfony/HttpClientAssertionsTrait.php | 7 ++++--- .../Module/Symfony/LoggerAssertionsTrait.php | 3 ++- .../Module/Symfony/SecurityAssertionsTrait.php | 1 + .../Module/Symfony/SessionAssertionsTrait.php | 1 + .../Module/Symfony/TimeAssertionsTrait.php | 1 + .../Module/Symfony/TwigAssertionsTrait.php | 1 + .../Module/Symfony/ValidatorAssertionsTrait.php | 2 +- 17 files changed, 60 insertions(+), 28 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ddd65355..8027f64b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,6 +8,8 @@ jobs: matrix: php: [8.2, 8.3, 8.4] symfony: ["5.4.*", "6.4.*", "6.4wApi", "7.3.*"] + env: + only_sf_latest: &only_sf_latest ${{ matrix.symfony == '7.3.*' }} steps: - name: Checkout code @@ -17,7 +19,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - tools: composer:v2, phpstan + tools: composer:v2 extensions: ctype, iconv, intl, json, mbstring, pdo, pdo_sqlite coverage: none @@ -79,8 +81,16 @@ jobs: composer update --prefer-dist --no-progress - name: Run PHPStan (max) - if: ${{ matrix.symfony == '7.2.*' }} - run: phpstan analyse src --level=max --no-progress --error-format=github --memory-limit=1G + if: *only_sf_latest + run: composer phpstan + + - name: Run PHP-CS-Fixer + if: *only_sf_latest + run: composer cs-check + + - name: Run Composer Audit + if: *only_sf_latest + run: composer audit - name: Validate Composer files run: composer validate --strict diff --git a/.gitignore b/.gitignore index 55018224..a8169301 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /.idea/ /vendor/ /composer.lock -/framework-tests \ No newline at end of file +/framework-tests +/.php-cs-fixer.cache \ No newline at end of file diff --git a/composer.json b/composer.json index b2202e83..03ca4985 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,8 @@ "codeception/module-asserts": "^3.0", "codeception/module-doctrine": "^3.1", "doctrine/orm": "^3.5", + "friendsofphp/php-cs-fixer": "^3.85", + "phpstan/phpstan": "^2.1", "symfony/browser-kit": "^5.4 | ^6.4 | ^7.3", "symfony/cache": "^5.4 | ^6.4 | ^7.3", "symfony/config": "^5.4 | ^6.4 | ^7.3", @@ -66,11 +68,17 @@ "symfony/web-profiler-bundle": "Tool that gives information about the execution of requests" }, "autoload": { - "classmap": ["src/"] + "psr-4": { + "Codeception\\": "src/Codeception/" + } }, "config": { - "classmap-authoritative": true, "sort-packages": true }, - "minimum-stability": "RC" + "minimum-stability": "RC", + "scripts": { + "phpstan": "phpstan analyse src --level=max --memory-limit=1G", + "cs-check": "php-cs-fixer fix src --dry-run --diff --using-cache=no", + "cs-fix": "php-cs-fixer fix src --using-cache=no" + } } diff --git a/readme.md b/readme.md index 79a33595..34cac759 100644 --- a/readme.md +++ b/readme.md @@ -10,7 +10,7 @@ A Codeception module for Symfony framework. ## Requirements * `Symfony` `5.4.x`, `6.4.x`, `7.3.x` or higher, as per the [Symfony supported versions](https://symfony.com/releases). -* `PHP 8.1` or higher. +* `PHP 8.2` or higher. ## Installation diff --git a/src/Codeception/Module/Symfony.php b/src/Codeception/Module/Symfony.php index c3f93dac..0f98cf13 100644 --- a/src/Codeception/Module/Symfony.php +++ b/src/Codeception/Module/Symfony.php @@ -54,6 +54,7 @@ use Symfony\Component\Mailer\DataCollector\MessageDataCollector; use Symfony\Component\Translation\DataCollector\TranslationDataCollector; use Symfony\Component\VarDumper\Cloner\Data; + use function array_keys; use function array_map; use function array_unique; @@ -64,6 +65,7 @@ use function file_exists; use function implode; use function in_array; +use function extension_loaded; use function ini_get; use function ini_set; use function is_object; @@ -292,8 +294,7 @@ public function _getEntityManager(): EntityManagerInterface $this->persistPermanentService($emService); $container = $this->_getContainer(); foreach ( - ['doctrine', 'doctrine.orm.default_entity_manager', 'doctrine.dbal.default_connection'] - as $service + ['doctrine', 'doctrine.orm.default_entity_manager', 'doctrine.dbal.default_connection'] as $service ) { if ($container->has($service)) { $this->persistPermanentService($service); @@ -495,6 +496,10 @@ protected function getInternalDomains(): array */ private function setXdebugMaxNestingLevel(int $max): void { + if (!extension_loaded('xdebug')) { + return; + } + if ((int) ini_get('xdebug.max_nesting_level') < $max) { ini_set('xdebug.max_nesting_level', (string) $max); } diff --git a/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php b/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php index 760f6cc7..8bd940b7 100644 --- a/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/BrowserAssertionsTrait.php @@ -19,6 +19,7 @@ use Symfony\Component\HttpFoundation\Test\Constraint\ResponseIsSuccessful; use Symfony\Component\HttpFoundation\Test\Constraint\ResponseIsUnprocessable; use Symfony\Component\HttpFoundation\Test\Constraint\ResponseStatusCodeSame; + use function sprintf; trait BrowserAssertionsTrait @@ -329,10 +330,7 @@ public function seePageRedirectsTo(string $page, string $redirectsTo): void $client->followRedirects(false); $this->amOnPage($page); - $this->assertTrue( - $client->getResponse()->isRedirection(), - 'The response is not a redirection.' - ); + $this->assertThatForResponse(new ResponseIsRedirected(), 'The response is not a redirection.'); $client->followRedirect(); $this->seeInCurrentUrl($redirectsTo); diff --git a/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php b/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php index 7b9dab27..5239bca1 100644 --- a/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/ConsoleAssertionsTrait.php @@ -78,19 +78,19 @@ private function configureOptions(array $parameters): array $options['interactive'] = false; } - if (in_array('-vvv', $parameters, true) - || in_array('--verbose=3', $parameters, true) + if (in_array('-vvv', $parameters, true) + || in_array('--verbose=3', $parameters, true) || (isset($parameters['--verbose']) && $parameters['--verbose'] === 3) ) { $options['verbosity'] = OutputInterface::VERBOSITY_DEBUG; - } elseif (in_array('-vv', $parameters, true) - || in_array('--verbose=2', $parameters, true) + } elseif (in_array('-vv', $parameters, true) + || in_array('--verbose=2', $parameters, true) || (isset($parameters['--verbose']) && $parameters['--verbose'] === 2) ) { $options['verbosity'] = OutputInterface::VERBOSITY_VERY_VERBOSE; - } elseif (in_array('-v', $parameters, true) - || in_array('--verbose=1', $parameters, true) - || in_array('--verbose', $parameters, true) + } elseif (in_array('-v', $parameters, true) + || in_array('--verbose=1', $parameters, true) + || in_array('--verbose', $parameters, true) || (isset($parameters['--verbose']) && $parameters['--verbose'] === 1) ) { $options['verbosity'] = OutputInterface::VERBOSITY_VERBOSE; diff --git a/src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php b/src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php index f25f9bf3..ec313bd6 100644 --- a/src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/DomCrawlerAssertionsTrait.php @@ -39,7 +39,8 @@ public function assertCheckboxNotChecked(string $fieldName, string $message = '' $this->assertThatCrawler( new LogicalNot( new CrawlerSelectorExists("input[name=\"$fieldName\"]:checked") - ), $message + ), + $message ); } @@ -57,7 +58,8 @@ public function assertInputValueNotSame(string $fieldName, string $expectedValue $this->assertThatCrawler( new LogicalNot( new CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue) - ), $message + ), + $message ); } diff --git a/src/Codeception/Module/Symfony/EventsAssertionsTrait.php b/src/Codeception/Module/Symfony/EventsAssertionsTrait.php index d9ba09f0..3108351e 100644 --- a/src/Codeception/Module/Symfony/EventsAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/EventsAssertionsTrait.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\Assert; use Symfony\Component\HttpKernel\DataCollector\EventDataCollector; + use function array_column; use function array_merge; use function count; diff --git a/src/Codeception/Module/Symfony/FormAssertionsTrait.php b/src/Codeception/Module/Symfony/FormAssertionsTrait.php index 26ab54aa..09314c6e 100644 --- a/src/Codeception/Module/Symfony/FormAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/FormAssertionsTrait.php @@ -6,6 +6,7 @@ use Symfony\Component\Form\Extension\DataCollector\FormDataCollector; use Symfony\Component\VarDumper\Cloner\Data; + use function is_array; use function is_int; use function is_string; diff --git a/src/Codeception/Module/Symfony/HttpClientAssertionsTrait.php b/src/Codeception/Module/Symfony/HttpClientAssertionsTrait.php index a8124b5f..bc55ae8f 100644 --- a/src/Codeception/Module/Symfony/HttpClientAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/HttpClientAssertionsTrait.php @@ -6,6 +6,7 @@ use Symfony\Component\HttpClient\DataCollector\HttpClientDataCollector; use Symfony\Component\VarDumper\Cloner\Data; + use function array_change_key_case; use function array_filter; use function array_intersect_key; @@ -56,10 +57,10 @@ function (array $trace) use ($expectedUrl, $expectedMethod, $expectedBody, $expe $bodyMatches = $expectedBody === null || $expectedBody === $actualBody; $headersMatch = $expectedHeaders === [] || ( - is_array($headerValues = $this->extractValue($options['headers'] ?? [])) + is_array($headerValues = $this->extractValue($options['headers'] ?? [])) && ($normalizedExpected = array_change_key_case($expectedHeaders)) === array_intersect_key(array_change_key_case($headerValues), $normalizedExpected) - ); + ); return $bodyMatches && $headersMatch; }, @@ -100,7 +101,7 @@ public function assertNotHttpClientRequest( ): void { $matchingRequests = array_filter( $this->getHttpClientTraces($httpClientId, __FUNCTION__), - fn(array $trace): bool => $this->matchesUrlAndMethod($trace, $unexpectedUrl, $unexpectedMethod) + fn (array $trace): bool => $this->matchesUrlAndMethod($trace, $unexpectedUrl, $unexpectedMethod) ); $this->assertEmpty( diff --git a/src/Codeception/Module/Symfony/LoggerAssertionsTrait.php b/src/Codeception/Module/Symfony/LoggerAssertionsTrait.php index 149b1a08..f7fdbbcc 100644 --- a/src/Codeception/Module/Symfony/LoggerAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/LoggerAssertionsTrait.php @@ -6,6 +6,7 @@ use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector; use Symfony\Component\VarDumper\Cloner\Data; + use function sprintf; trait LoggerAssertionsTrait @@ -45,7 +46,7 @@ public function dontSeeDeprecations(string $message = ''): void "Found %d deprecation message%s in the log:\n%s", $count, $count !== 1 ? 's' : '', - implode("\n", array_map(static fn(string $m): string => " - $m", $foundDeprecations)), + implode("\n", array_map(static fn (string $m): string => " - $m", $foundDeprecations)), ); $this->assertEmpty($foundDeprecations, $errorMessage); } diff --git a/src/Codeception/Module/Symfony/SecurityAssertionsTrait.php b/src/Codeception/Module/Symfony/SecurityAssertionsTrait.php index 3d0ecaf6..38025985 100644 --- a/src/Codeception/Module/Symfony/SecurityAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/SecurityAssertionsTrait.php @@ -10,6 +10,7 @@ use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; + use function sprintf; trait SecurityAssertionsTrait diff --git a/src/Codeception/Module/Symfony/SessionAssertionsTrait.php b/src/Codeception/Module/Symfony/SessionAssertionsTrait.php index 9382184a..70528946 100644 --- a/src/Codeception/Module/Symfony/SessionAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/SessionAssertionsTrait.php @@ -17,6 +17,7 @@ use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge; use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; + use function class_exists; use function in_array; use function is_int; diff --git a/src/Codeception/Module/Symfony/TimeAssertionsTrait.php b/src/Codeception/Module/Symfony/TimeAssertionsTrait.php index 1affaba6..15f89115 100644 --- a/src/Codeception/Module/Symfony/TimeAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/TimeAssertionsTrait.php @@ -5,6 +5,7 @@ namespace Codeception\Module\Symfony; use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector; + use function round; use function sprintf; diff --git a/src/Codeception/Module/Symfony/TwigAssertionsTrait.php b/src/Codeception/Module/Symfony/TwigAssertionsTrait.php index 61899979..021e6456 100644 --- a/src/Codeception/Module/Symfony/TwigAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/TwigAssertionsTrait.php @@ -5,6 +5,7 @@ namespace Codeception\Module\Symfony; use Symfony\Bridge\Twig\DataCollector\TwigDataCollector; + use function array_key_first; trait TwigAssertionsTrait diff --git a/src/Codeception/Module/Symfony/ValidatorAssertionsTrait.php b/src/Codeception/Module/Symfony/ValidatorAssertionsTrait.php index 01875a04..bfbdac07 100644 --- a/src/Codeception/Module/Symfony/ValidatorAssertionsTrait.php +++ b/src/Codeception/Module/Symfony/ValidatorAssertionsTrait.php @@ -91,7 +91,7 @@ protected function getViolationsForSubject(object $subject, ?string $propertyPat if ($constraint !== null) { return (array)array_filter( $violations, - static fn(ConstraintViolationInterface $violation): bool => get_class((object)$violation->getConstraint()) === $constraint && + static fn (ConstraintViolationInterface $violation): bool => get_class((object)$violation->getConstraint()) === $constraint && ($propertyPath === null || $violation->getPropertyPath() === $propertyPath) ); }