From 5e042f1686bf7e4591eaa90a524f14cc796a9320 Mon Sep 17 00:00:00 2001 From: Aaron Gustavo Nieves <64917965+TavoNiievez@users.noreply.github.com> Date: Sun, 8 Dec 2024 12:23:31 -0500 Subject: [PATCH 1/3] Support Symfony 7.2 (#203) --- .github/workflows/main.yml | 50 +++++++++++++---------------------- composer.json | 54 +++++++++++++++++++------------------- readme.md | 2 +- 3 files changed, 46 insertions(+), 60 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f7f897c8..85b0d49d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,18 +1,16 @@ name: CI - on: [push, pull_request] jobs: tests: runs-on: ubuntu-latest - strategy: matrix: php: [8.1, 8.2, 8.3, 8.4] - symfony: ["5.4.*", "6.4.*", "7.1.*"] + symfony: ["5.4.*", "6.4.*", "7.2.*"] exclude: - php: 8.1 - symfony: "7.1.*" + symfony: "7.2.*" steps: - name: Checkout code @@ -26,40 +24,28 @@ jobs: extensions: ctype, iconv, intl, json, mbstring, pdo, pdo_sqlite coverage: none - - name: Checkout Symfony 5.4 Sample - if: "matrix.symfony == '5.4.*'" - uses: actions/checkout@v4 - with: - repository: Codeception/symfony-module-tests - path: framework-tests - ref: "5.4" - - - name: Checkout Symfony 6.4 Sample - if: "matrix.symfony == '6.4.*'" - uses: actions/checkout@v4 - with: - repository: Codeception/symfony-module-tests - path: framework-tests - ref: "6.4" + - name: Set Symfony version reference + run: echo "SF_REF=${MATRIX_SYMFONY%.*}" >> $GITHUB_ENV + env: + MATRIX_SYMFONY: ${{ matrix.symfony }} - - name: Checkout Symfony 7.1 Sample - if: "matrix.symfony == '7.1.*'" + - name: Checkout Symfony ${{ env.SF_REF }} Sample uses: actions/checkout@v4 with: repository: Codeception/symfony-module-tests path: framework-tests - ref: "7.1" + ref: ${{ env.SF_REF }} - name: Get composer cache directory id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Cache composer dependencies + - name: Cache Composer dependencies uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} - restore-keys: ${{ runner.os }}-${{ matrix.php }}-composer- + key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json', 'composer.lock') }} + restore-keys: ${{ runner.os }}-php-${{ matrix.php }}-composer- - name: Install PHPUnit 10 run: composer require --dev --no-update "phpunit/phpunit=^10.0" @@ -78,27 +64,27 @@ jobs: composer require codeception/module-doctrine="3.*" --no-update composer update --prefer-dist --no-progress --no-dev - - name: Validate composer.json and composer.lock - run: composer validate + - name: Validate Composer files + run: composer validate --strict working-directory: framework-tests - - name: Install PHPUnit 10 in framework-tests + - name: Install PHPUnit in framework-tests run: composer require --dev --no-update "phpunit/phpunit=^10.0" working-directory: framework-tests - - name: Install Symfony Sample + - name: Prepare Symfony sample run: | composer remove codeception/codeception codeception/module-asserts codeception/module-doctrine codeception/lib-innerbrowser codeception/module-symfony --dev --no-update composer update --no-progress working-directory: framework-tests - - name: Prepare the test environment + - name: Setup Database run: | php bin/console doctrine:schema:update --force php bin/console doctrine:fixtures:load --quiet working-directory: framework-tests - - name: Run test suite + - name: Run tests run: | php vendor/bin/codecept build -c framework-tests php vendor/bin/codecept run Functional -c framework-tests diff --git a/composer.json b/composer.json index 65238b1d..82fb64f3 100644 --- a/composer.json +++ b/composer.json @@ -28,33 +28,33 @@ "codeception/module-asserts": "^3.0", "codeception/module-doctrine": "^3.1", "doctrine/orm": "^2.10", - "symfony/browser-kit": "^5.4 | ^6.4 | ^7.0", - "symfony/cache": "^5.4 | ^6.4 | ^7.0", - "symfony/config": "^5.4 | ^6.4 | ^7.0", - "symfony/dependency-injection": "^5.4 | ^6.4 | ^7.0", - "symfony/dom-crawler": "^5.4 | ^6.4 | ^7.0", - "symfony/dotenv": "^5.4 | ^6.4 | ^7.0", - "symfony/error-handler": "^5.4 | ^6.4 | ^7.0", - "symfony/filesystem": "^5.4 | ^6.4 | ^7.0", - "symfony/form": "^5.4 | ^6.4 | ^7.0", - "symfony/framework-bundle": "^5.4 | ^6.4 | ^7.0", - "symfony/http-client": "^5.4 | ^6.4 | ^7.0", - "symfony/http-foundation": "^5.4 | ^6.4 | ^7.0", - "symfony/http-kernel": "^5.4 | ^6.4 | ^7.0", - "symfony/mailer": "^5.4 | ^6.4 | ^7.0", - "symfony/mime": "^5.4 | ^6.4 | ^7.0", - "symfony/notifier": "^5.4 | ^6.4 | ^7.0", - "symfony/options-resolver": "^5.4 | ^6.4 | ^7.0", - "symfony/property-access": "^5.4 | ^6.4 | ^7.0", - "symfony/property-info": "^5.4 | ^6.4 | ^7.0", - "symfony/routing": "^5.4 | ^6.4 | ^7.0", - "symfony/security-bundle": "^5.4 | ^6.4 | ^7.0", - "symfony/security-core": "^5.4 | ^6.4 | ^7.0", - "symfony/security-csrf": "^5.4 | ^6.4 | ^7.0", - "symfony/security-http": "^5.4 | ^6.4 | ^7.0", - "symfony/twig-bundle": "^5.4 | ^6.4 | ^7.0", - "symfony/validator": "^5.4 | ^6.4 | ^7.0", - "symfony/var-exporter": "^5.4 | ^6.4 | ^7.0", + "symfony/browser-kit": "^5.4 | ^6.4 | ^7.2", + "symfony/cache": "^5.4 | ^6.4 | ^7.2", + "symfony/config": "^5.4 | ^6.4 | ^7.2", + "symfony/dependency-injection": "^5.4 | ^6.4 | ^7.2", + "symfony/dom-crawler": "^5.4 | ^6.4 | ^7.2", + "symfony/dotenv": "^5.4 | ^6.4 | ^7.2", + "symfony/error-handler": "^5.4 | ^6.4 | ^7.2", + "symfony/filesystem": "^5.4 | ^6.4 | ^7.2", + "symfony/form": "^5.4 | ^6.4 | ^7.2", + "symfony/framework-bundle": "^5.4 | ^6.4 | ^7.2", + "symfony/http-client": "^5.4 | ^6.4 | ^7.2", + "symfony/http-foundation": "^5.4 | ^6.4 | ^7.2", + "symfony/http-kernel": "^5.4 | ^6.4 | ^7.2", + "symfony/mailer": "^5.4 | ^6.4 | ^7.2", + "symfony/mime": "^5.4 | ^6.4 | ^7.2", + "symfony/notifier": "^5.4 | ^6.4 | ^7.2", + "symfony/options-resolver": "^5.4 | ^6.4 | ^7.2", + "symfony/property-access": "^5.4 | ^6.4 | ^7.2", + "symfony/property-info": "^5.4 | ^6.4 | ^7.2", + "symfony/routing": "^5.4 | ^6.4 | ^7.2", + "symfony/security-bundle": "^5.4 | ^6.4 | ^7.2", + "symfony/security-core": "^5.4 | ^6.4 | ^7.2", + "symfony/security-csrf": "^5.4 | ^6.4 | ^7.2", + "symfony/security-http": "^5.4 | ^6.4 | ^7.2", + "symfony/twig-bundle": "^5.4 | ^6.4 | ^7.2", + "symfony/validator": "^5.4 | ^6.4 | ^7.2", + "symfony/var-exporter": "^5.4 | ^6.4 | ^7.2", "vlucas/phpdotenv": "^4.2 | ^5.4" }, "suggest": { diff --git a/readme.md b/readme.md index ccedd850..c5bbcb98 100644 --- a/readme.md +++ b/readme.md @@ -9,7 +9,7 @@ A Codeception module for Symfony framework. ## Requirements -* `Symfony` `5.4.x`, `6.4.x`, `7.1.x` or higher, as per the [Symfony supported versions](https://symfony.com/releases). +* `Symfony` `5.4.x`, `6.4.x`, `7.2.x` or higher, as per the [Symfony supported versions](https://symfony.com/releases). * `PHP 8.1` or higher. ## Installation From 94e411b3262d54b7ef3f411683271c49f50ad406 Mon Sep 17 00:00:00 2001 From: Aaron Gustavo Nieves <64917965+TavoNiievez@users.noreply.github.com> Date: Mon, 20 Jan 2025 06:01:44 -0500 Subject: [PATCH 2/3] Added Symfony Translation assertions (#205) --- composer.json | 1 + src/Codeception/Module/Symfony.php | 2 + .../Symfony/TranslationAssertionsTrait.php | 178 ++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 src/Codeception/Module/Symfony/TranslationAssertionsTrait.php diff --git a/composer.json b/composer.json index 82fb64f3..747a5941 100644 --- a/composer.json +++ b/composer.json @@ -52,6 +52,7 @@ "symfony/security-core": "^5.4 | ^6.4 | ^7.2", "symfony/security-csrf": "^5.4 | ^6.4 | ^7.2", "symfony/security-http": "^5.4 | ^6.4 | ^7.2", + "symfony/translation": "^5.4 | ^6.4 | ^7.2", "symfony/twig-bundle": "^5.4 | ^6.4 | ^7.2", "symfony/validator": "^5.4 | ^6.4 | ^7.2", "symfony/var-exporter": "^5.4 | ^6.4 | ^7.2", diff --git a/src/Codeception/Module/Symfony.php b/src/Codeception/Module/Symfony.php index 3f7917bb..ebe6aee6 100644 --- a/src/Codeception/Module/Symfony.php +++ b/src/Codeception/Module/Symfony.php @@ -25,6 +25,7 @@ use Codeception\Module\Symfony\ServicesAssertionsTrait; use Codeception\Module\Symfony\SessionAssertionsTrait; use Codeception\Module\Symfony\TimeAssertionsTrait; +use Codeception\Module\Symfony\TranslationAssertionsTrait; use Codeception\Module\Symfony\TwigAssertionsTrait; use Codeception\Module\Symfony\ValidatorAssertionsTrait; use Codeception\TestInterface; @@ -148,6 +149,7 @@ class Symfony extends Framework implements DoctrineProvider, PartedModule use SecurityAssertionsTrait; use ServicesAssertionsTrait; use SessionAssertionsTrait; + use TranslationAssertionsTrait; use TimeAssertionsTrait; use TwigAssertionsTrait; use ValidatorAssertionsTrait; diff --git a/src/Codeception/Module/Symfony/TranslationAssertionsTrait.php b/src/Codeception/Module/Symfony/TranslationAssertionsTrait.php new file mode 100644 index 00000000..7c4c385a --- /dev/null +++ b/src/Codeception/Module/Symfony/TranslationAssertionsTrait.php @@ -0,0 +1,178 @@ +dontSeeFallbackTranslations(); + * ``` + */ + public function dontSeeFallbackTranslations(): void + { + $translationCollector = $this->grabTranslationCollector(__FUNCTION__); + $fallbacks = $translationCollector->getCountFallbacks(); + + $this->assertSame( + $fallbacks, + 0, + "Expected no fallback translations, but found {$fallbacks}." + ); + } + + /** + * Asserts that no missing translations were found. + * + * ```php + * dontSeeMissingTranslations(); + * ``` + */ + public function dontSeeMissingTranslations(): void + { + $translationCollector = $this->grabTranslationCollector(__FUNCTION__); + $missings = $translationCollector->getCountMissings(); + + $this->assertSame( + $missings, + 0, + "Expected no missing translations, but found {$missings}." + ); + } + + /** + * Grabs the count of defined translations. + * + * ```php + * grabDefinedTranslations(); + * ``` + * + * @return int The count of defined translations. + */ + public function grabDefinedTranslationsCount(): int + { + $translationCollector = $this->grabTranslationCollector(__FUNCTION__); + return $translationCollector->getCountDefines(); + } + + /** + * Asserts that there are no missing translations and no fallback translations. + * + * ```php + * seeAllTranslationsDefined(); + * ``` + */ + public function seeAllTranslationsDefined(): void + { + $this->dontSeeMissingTranslations(); + $this->dontSeeFallbackTranslations(); + } + + /** + * Asserts that the default locale is the expected one. + * + * ```php + * seeDefaultLocaleIs('en'); + * ``` + * + * @param string $expectedLocale The expected default locale + */ + public function seeDefaultLocaleIs(string $expectedLocale): void + { + $translationCollector = $this->grabTranslationCollector(__FUNCTION__); + $locale = $translationCollector->getLocale(); + + $this->assertSame( + $expectedLocale, + $locale, + "Expected default locale '{$expectedLocale}', but found '{$locale}'." + ); + } + + /** + * Asserts that the fallback locales match the expected ones. + * + * ```php + * seeFallbackLocalesAre(['es', 'fr']); + * ``` + * + * @param array $expectedLocales The expected fallback locales + */ + public function seeFallbackLocalesAre(array $expectedLocales): void + { + $translationCollector = $this->grabTranslationCollector(__FUNCTION__); + $fallbackLocales = $translationCollector->getFallbackLocales(); + + if ($fallbackLocales instanceof Data) { + $fallbackLocales = $fallbackLocales->getValue(true); + } + + $this->assertSame( + $expectedLocales, + $fallbackLocales, + "Fallback locales do not match expected." + ); + } + + /** + * Asserts that the count of fallback translations is less than the given limit. + * + * ```php + * seeFallbackTranslationsCountLessThan(10); + * ``` + * + * @param int $limit Maximum count of fallback translations + */ + public function seeFallbackTranslationsCountLessThan(int $limit): void + { + $translationCollector = $this->grabTranslationCollector(__FUNCTION__); + $fallbacks = $translationCollector->getCountFallbacks(); + + $this->assertLessThan( + $limit, + $fallbacks, + "Expected fewer than {$limit} fallback translations, but found {$fallbacks}." + ); + } + + /** + * Asserts that the count of missing translations is less than the given limit. + * + * ```php + * seeMissingTranslationsCountLessThan(5); + * ``` + * + * @param int $limit Maximum count of missing translations + */ + public function seeMissingTranslationsCountLessThan(int $limit): void + { + $translationCollector = $this->grabTranslationCollector(__FUNCTION__); + $missings = $translationCollector->getCountMissings(); + + $this->assertLessThan( + $limit, + $missings, + "Expected fewer than {$limit} missing translations, but found {$missings}." + ); + } + + protected function grabTranslationCollector(string $function): TranslationDataCollector + { + return $this->grabCollector('translation', $function); + } +} From 12fdf094fea572f8fd6e975c4f4b440d95684d44 Mon Sep 17 00:00:00 2001 From: Aaron Gustavo Nieves <64917965+TavoNiievez@users.noreply.github.com> Date: Thu, 20 Feb 2025 11:35:08 -0500 Subject: [PATCH 3/3] Added Symfony Logger assertion (dontSeeDeprecations) (#206) --- src/Codeception/Module/Symfony.php | 2 + .../Module/Symfony/LoggerAssertionsTrait.php | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 src/Codeception/Module/Symfony/LoggerAssertionsTrait.php diff --git a/src/Codeception/Module/Symfony.php b/src/Codeception/Module/Symfony.php index ebe6aee6..0e41e787 100644 --- a/src/Codeception/Module/Symfony.php +++ b/src/Codeception/Module/Symfony.php @@ -17,6 +17,7 @@ use Codeception\Module\Symfony\EventsAssertionsTrait; use Codeception\Module\Symfony\FormAssertionsTrait; use Codeception\Module\Symfony\HttpClientAssertionsTrait; +use Codeception\Module\Symfony\LoggerAssertionsTrait; use Codeception\Module\Symfony\MailerAssertionsTrait; use Codeception\Module\Symfony\MimeAssertionsTrait; use Codeception\Module\Symfony\ParameterAssertionsTrait; @@ -142,6 +143,7 @@ class Symfony extends Framework implements DoctrineProvider, PartedModule use EventsAssertionsTrait; use FormAssertionsTrait; use HttpClientAssertionsTrait; + use LoggerAssertionsTrait; use MailerAssertionsTrait; use MimeAssertionsTrait; use ParameterAssertionsTrait; diff --git a/src/Codeception/Module/Symfony/LoggerAssertionsTrait.php b/src/Codeception/Module/Symfony/LoggerAssertionsTrait.php new file mode 100644 index 00000000..4cd0266a --- /dev/null +++ b/src/Codeception/Module/Symfony/LoggerAssertionsTrait.php @@ -0,0 +1,60 @@ +amOnPage('/home'); + * $I->dontSeeDeprecations(); + * ``` + * + * @param string $message Optional custom failure message. + */ + public function dontSeeDeprecations(string $message = ''): void + { + $loggerCollector = $this->grabLoggerCollector(__FUNCTION__); + $logs = $loggerCollector->getProcessedLogs(); + + $foundDeprecations = []; + + foreach ($logs as $log) { + if (isset($log['type']) && $log['type'] === 'deprecation') { + $msg = $log['message']; + if ($msg instanceof Data) { + $msg = $msg->getValue(true); + } + if (!is_string($msg)) { + $msg = (string)$msg; + } + $foundDeprecations[] = $msg; + } + } + + $errorMessage = $message ?: sprintf( + "Found %d deprecation message%s in the log:\n%s", + count($foundDeprecations), + count($foundDeprecations) > 1 ? 's' : '', + implode("\n", array_map(static function ($msg) { + return " - " . $msg; + }, $foundDeprecations)) + ); + + $this->assertEmpty($foundDeprecations, $errorMessage); + } + + protected function grabLoggerCollector(string $function): LoggerDataCollector + { + return $this->grabCollector('logger', $function); + } +}