From a29fc0016b3a5121eb3eaf216bc71d6d07b03e15 Mon Sep 17 00:00:00 2001 From: Stephan Wentz Date: Tue, 11 Feb 2025 13:27:46 +0100 Subject: [PATCH 1/3] docs: Fix badges --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 02b355d..9b1b8f5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # brainbits Functional Test Helpers +[![Latest Version](https://img.shields.io/github/release/brainbits/functional-test-helpers.svg?style=flat-square)](https://github.com/brainbits/functional-test-helpers/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Build Status](https://img.shields.io/github/check-runs/brainbits/functional-test-helpers/main)](https://github.com/brainbits/functional-test-helpers/actions) +[![Coverage Status](https://img.shields.io/codecov/c/github/brainbits/functional-test-helpers)](https://app.codecov.io/gh/brainbits/functional-test-helpers) +[![Total Downloads](https://img.shields.io/packagist/dt/brainbits/functional-test-helpers.svg?style=flat-square)](https://packagist.org/packages/brainbits/functional-test-helpers) + A collection of test helper traits for symfony projects. Please look at the respective READMEs for details. From e44125c80566764e6513b71dbaa59c1a3d991d21 Mon Sep 17 00:00:00 2001 From: Stephan Wentz Date: Tue, 11 Feb 2025 15:00:10 +0100 Subject: [PATCH 2/3] fix: Remove legacy check --- tests/Request/RequestBuilderTest.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/Request/RequestBuilderTest.php b/tests/Request/RequestBuilderTest.php index bb407d8..259c1c1 100644 --- a/tests/Request/RequestBuilderTest.php +++ b/tests/Request/RequestBuilderTest.php @@ -14,7 +14,6 @@ use Symfony\Component\Security\Core\User\InMemoryUser; use function current; -use function method_exists; use function Safe\json_encode; #[CoversClass(RequestBuilder::class)] @@ -232,10 +231,6 @@ public function testAuthenticationHeadersAreSetOnAuthCall(): void public function testAuthorizationHeaderIsSetOnAuthLoginWithDeprecatedFindUser(): void { - if (!method_exists(KernelBrowser::class, 'loginUser')) { - $this->markTestSkipped('authLogin() only available for symfony/framework-bundle >= 5.1'); - } - $browser = $this->createMock(KernelBrowser::class); $browser->expects($this->once()) ->method('loginUser') @@ -253,10 +248,6 @@ public function testAuthorizationHeaderIsSetOnAuthLoginWithDeprecatedFindUser(): public function testAuthorizationHeaderIsSetOnAuthLoginCall(): void { - if (!method_exists(KernelBrowser::class, 'loginUser')) { - $this->markTestSkipped('authLogin() only available for symfony/framework-bundle >= 5.1'); - } - $browser = $this->createMock(KernelBrowser::class); $browser->expects($this->never()) ->method('loginUser'); From 47370494e22754932024bf6a572a5f88810157e5 Mon Sep 17 00:00:00 2001 From: Stephan Wentz Date: Tue, 11 Feb 2025 14:59:55 +0100 Subject: [PATCH 3/3] fix: Upgrade to phpstan 2, phpunit 12 and allow safe 3 --- composer.json | 60 +++++++++---------- phpstan.neon.dist | 12 +--- .../Matcher/CatchAllMatcher.php | 2 +- src/HttpClientMock/Matcher/ContentMatcher.php | 2 +- src/HttpClientMock/Matcher/JsonMatcher.php | 2 +- src/HttpClientMock/Matcher/MethodMatcher.php | 2 +- src/HttpClientMock/Matcher/ThatMatcher.php | 2 +- src/HttpClientMock/Matcher/UriMatcher.php | 2 +- src/HttpClientMock/Matcher/XmlMatcher.php | 2 +- src/HttpClientMock/MockRequestBuilder.php | 2 +- .../MockRequestBuilderCollection.php | 4 +- src/SevenZipContents/SevenZipArchive.php | 2 +- tests/Application/ApplicationTraitTest.php | 35 +++++++++++ tests/Console/CommandTraitTest.php | 31 ++++++++++ .../Matcher/CatchAllMatcherTest.php | 2 - tests/Request/RequestBuilderTest.php | 12 ---- tests/Request/RequestTraitTest.php | 2 - 17 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 tests/Application/ApplicationTraitTest.php create mode 100644 tests/Console/CommandTraitTest.php diff --git a/composer.json b/composer.json index 3606b24..aad8250 100644 --- a/composer.json +++ b/composer.json @@ -1,11 +1,11 @@ { "name": "brainbits/functional-test-helpers", - "type": "library", "description": "brainbits controlling functional test helpers", "license": "MIT", + "type": "library", "require": { "php": "^8.3", - "thecodingmachine/safe": "^2.0" + "thecodingmachine/safe": "^2.0 || ^3.0" }, "require-dev": { "ext-dom": "*", @@ -13,23 +13,22 @@ "ext-mbstring": "*", "ext-simplexml": "*", "ext-tidy": "*", - "brainbits/phpcs-standard": "^7.0", - "brainbits/phpstan-rules": "^3.1.2", - "dama/doctrine-test-bundle": "^8.0", - "doctrine/dbal": "^3.4", - "ergebnis/phpstan-rules": "^2.5.2", - "gemorroj/archive7z": "^5.3", - "jangregor/phpstan-prophecy": "^1.0.2", - "mikey179/vfsstream": "^1.6.11", - "monolog/monolog": "^2.3|^3.0", - "phpstan/phpstan": "^1.12.15", - "phpstan/phpstan-phpunit": "^1.4.2", - "phpstan/phpstan-symfony": "^1.4.13", - "phpunit/phpunit": "^11.4", + "brainbits/phpcs-standard": "^7.0.1", + "brainbits/phpstan-rules": "^4.0", + "dama/doctrine-test-bundle": "^8.2", + "doctrine/dbal": "^3.9", + "ergebnis/phpstan-rules": "^2.6", + "gemorroj/archive7z": "^5.7", + "mikey179/vfsstream": "^1.6.12", + "monolog/monolog": "^2.0 || ^3.0", + "phpstan/phpstan": "^2.1.4", + "phpstan/phpstan-phpunit": "^2.0.4", + "phpstan/phpstan-symfony": "^2.0.2", + "phpunit/phpunit": "^12.0.2", "psr/http-message": "^2.0", "riverline/multipart-parser": "^2.1", - "slam/phpstan-extensions": "^6.5.0", - "squizlabs/php_codesniffer": "^3.10", + "slam/phpstan-extensions": "^6.6.0", + "squizlabs/php_codesniffer": "^3.11.3", "symfony/browser-kit": "^7.0", "symfony/console": "^7.0", "symfony/dependency-injection": "^7.0", @@ -41,40 +40,30 @@ "symfony/security-core": "^7.0", "symfony/security-csrf": "^7.0", "symfony/uid": "^7.0", - "thecodingmachine/phpstan-safe-rule": "^1.2", - "thecodingmachine/phpstan-strict-rules": "^1.0" + "thecodingmachine/phpstan-safe-rule": "^1.4" }, "suggest": { "ext-dom": "For mocking xml requests", "ext-iconv": "For asserting zip files", - "ext-mbstring": "For asserting zip files", "ext-json": "For json snapshot tests", + "ext-mbstring": "For asserting zip files", "ext-simplexml": "For mocking xml requests", "ext-tidy": "For html snapshots", + "dama/doctrine-test-bundle": "For schema trait, when using DAMA Static Driver", "doctrine/dbal": "For schema trait", "doctrine/event-manager": "For schema trait", - "dama/doctrine-test-bundle": "For schema trait, when using DAMA Static Driver", "gemorroj/archive7z": "For 7z file support", "monolog/monolog": "For http client mock trait", "riverline/multipart-parser": "For multipart file uploads", "symfony/browser-kit": "For request trait", "symfony/console": "For console trait", "symfony/filesystem": "For request trait", + "symfony/framework-bundle": "For request trait, when using authLogin(). Requires version >= 7.0", "symfony/http-client": "For http client mock trait", "symfony/http-foundation": "For request trait", - "symfony/framework-bundle": "For request trait, when using authLogin(). Requires version >= 5.1", "symfony/security-core": "For request trait", "symfony/uid": "For uuid trait" }, - "config": { - "preferred-install": { - "*": "dist" - }, - "sort-packages": true, - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - }, "autoload": { "psr-4": { "Brainbits\\FunctionalTestHelpers\\": "src/" @@ -84,5 +73,14 @@ "psr-4": { "Brainbits\\FunctionalTestHelpers\\Tests\\": "tests/" } + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + }, + "preferred-install": { + "*": "dist" + }, + "sort-packages": true } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index fc381b9..1eab7fd 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,18 +1,13 @@ parameters: level: 6 + treatPhpDocTypesAsCertain: false paths: - src - tests excludePaths: - - src/Kernel.php - - tests/bootstrap.php - src/HttpClientMock/CallbackHandler.php # needed because of unknown classes when installed with monolog 2.x - - src/HttpClientMock/LegacyCallbackHandler.php # needed because of unknown classes when installed with monolog 2.x ignoreErrors: - '#Constructor in .* has parameter .* with default value#' - - '#In method "Brainbits\\FunctionalTestHelpers\\Snapshot\\IsXml::.*", caught "Throwable" must be rethrown. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception.#' - - '#In method "Brainbits\\FunctionalTestHelpers\\Tests\\Uuid\\UuidTraitTest::.*", caught "Throwable" must be rethrown. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception.#' - - '#Safe\\DateTimeImmutable#' - '#SchemaBuilder::foo\(\)#' ergebnis: noNullableReturnTypeDeclaration: @@ -31,9 +26,8 @@ parameters: includes: - %rootDir%/../../brainbits/phpstan-rules/rules.neon - %rootDir%/../../ergebnis/phpstan-rules/rules.neon - - %rootDir%/../../jangregor/phpstan-prophecy/extension.neon - %rootDir%/../../phpstan/phpstan-phpunit/extension.neon - %rootDir%/../../phpstan/phpstan-phpunit/rules.neon - %rootDir%/../../phpstan/phpstan-symfony/extension.neon - - %rootDir%/../../thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon - - %rootDir%/../../thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon +# - %rootDir%/../../thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon +# - %rootDir%/../../thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon diff --git a/src/HttpClientMock/Matcher/CatchAllMatcher.php b/src/HttpClientMock/Matcher/CatchAllMatcher.php index fbfa3a6..0750a1c 100644 --- a/src/HttpClientMock/Matcher/CatchAllMatcher.php +++ b/src/HttpClientMock/Matcher/CatchAllMatcher.php @@ -8,7 +8,7 @@ final readonly class CatchAllMatcher implements Matcher { - public function __invoke(RealRequest $realRequest): Hit|Mismatch|Missing + public function __invoke(RealRequest $realRequest): Hit { return Hit::catchAll(); } diff --git a/src/HttpClientMock/Matcher/ContentMatcher.php b/src/HttpClientMock/Matcher/ContentMatcher.php index 4f5fa11..42e3dbd 100644 --- a/src/HttpClientMock/Matcher/ContentMatcher.php +++ b/src/HttpClientMock/Matcher/ContentMatcher.php @@ -18,7 +18,7 @@ public function __construct(string|callable $content) $this->content = $content; } - public function __invoke(RealRequest $realRequest): Hit|Mismatch|Missing + public function __invoke(RealRequest $realRequest): Hit|Mismatch { $expectedContent = $this->content; $realContent = $realRequest->getContent(); diff --git a/src/HttpClientMock/Matcher/JsonMatcher.php b/src/HttpClientMock/Matcher/JsonMatcher.php index 4e8a3d2..7487b6a 100644 --- a/src/HttpClientMock/Matcher/JsonMatcher.php +++ b/src/HttpClientMock/Matcher/JsonMatcher.php @@ -21,7 +21,7 @@ public function __construct(array|callable $json) $this->json = $json; } - public function __invoke(RealRequest $realRequest): Hit|Mismatch|Missing + public function __invoke(RealRequest $realRequest): Hit|Mismatch { $expectedJson = $this->json; $realJson = $realRequest->getJson(); diff --git a/src/HttpClientMock/Matcher/MethodMatcher.php b/src/HttpClientMock/Matcher/MethodMatcher.php index 570d626..6f52fbe 100644 --- a/src/HttpClientMock/Matcher/MethodMatcher.php +++ b/src/HttpClientMock/Matcher/MethodMatcher.php @@ -19,7 +19,7 @@ public function __construct(string|callable $method) $this->method = $method; } - public function __invoke(RealRequest $realRequest): Hit|Mismatch|Missing + public function __invoke(RealRequest $realRequest): Hit|Mismatch { $expectedMethod = $this->method; $realMethod = $realRequest->getMethod(); diff --git a/src/HttpClientMock/Matcher/ThatMatcher.php b/src/HttpClientMock/Matcher/ThatMatcher.php index f9b062d..8cf7148 100644 --- a/src/HttpClientMock/Matcher/ThatMatcher.php +++ b/src/HttpClientMock/Matcher/ThatMatcher.php @@ -15,7 +15,7 @@ public function __construct(callable $that) $this->that = $that; } - public function __invoke(RealRequest $realRequest): Hit|Mismatch|Missing + public function __invoke(RealRequest $realRequest): Hit|Mismatch { if (($this->that)($realRequest) === false) { return Mismatch::mismatchingThat('returned false'); diff --git a/src/HttpClientMock/Matcher/UriMatcher.php b/src/HttpClientMock/Matcher/UriMatcher.php index c63978e..7d63373 100644 --- a/src/HttpClientMock/Matcher/UriMatcher.php +++ b/src/HttpClientMock/Matcher/UriMatcher.php @@ -24,7 +24,7 @@ public function __construct(string|callable $uri, private UriParams $uriParams) $this->uri = $uri; } - public function __invoke(RealRequest $realRequest): Hit|Mismatch|Missing + public function __invoke(RealRequest $realRequest): Hit|Mismatch { $realUri = $realRequest->getUri(); diff --git a/src/HttpClientMock/Matcher/XmlMatcher.php b/src/HttpClientMock/Matcher/XmlMatcher.php index 92fba97..e00754b 100644 --- a/src/HttpClientMock/Matcher/XmlMatcher.php +++ b/src/HttpClientMock/Matcher/XmlMatcher.php @@ -28,7 +28,7 @@ public function __construct(string|callable $xml) $this->xml = $xml; } - public function __invoke(RealRequest $realRequest): Hit|Mismatch|Missing + public function __invoke(RealRequest $realRequest): Hit|Mismatch { $expectedXml = $this->xml; $realXml = $realRequest->getContent(); diff --git a/src/HttpClientMock/MockRequestBuilder.php b/src/HttpClientMock/MockRequestBuilder.php index 9f6730c..841f024 100644 --- a/src/HttpClientMock/MockRequestBuilder.php +++ b/src/HttpClientMock/MockRequestBuilder.php @@ -306,7 +306,7 @@ public function hasResponse(): bool return !$this->responses->isEmpty(); } - public function nextResponse(): MockResponseBuilder|Throwable|null + public function nextResponse(): MockResponseBuilder|Throwable { try { return $this->responses->next(); diff --git a/src/HttpClientMock/MockRequestBuilderCollection.php b/src/HttpClientMock/MockRequestBuilderCollection.php index a539d5c..7422794 100644 --- a/src/HttpClientMock/MockRequestBuilderCollection.php +++ b/src/HttpClientMock/MockRequestBuilderCollection.php @@ -36,7 +36,7 @@ public function __invoke(string $method, string $url, array $options): ResponseI $requestBuilder->assert($realRequest); $requestBuilder->called($realRequest); - if ($requestBuilder->onMatch && is_callable($requestBuilder->onMatch)) { // @phpstan-ignore-line + if ($requestBuilder->onMatch && is_callable($requestBuilder->onMatch)) { ($requestBuilder->onMatch)($realRequest); } @@ -58,7 +58,7 @@ public function getCallStack(): CallStack return CallStack::fromCallStacks(...$callStacks); } - /** @return Traversable|MockRequestBuilder[] */ + /** @return Traversable */ public function getIterator(): Traversable { yield from $this->requestBuilders; diff --git a/src/SevenZipContents/SevenZipArchive.php b/src/SevenZipContents/SevenZipArchive.php index 66ef984..ec184b8 100644 --- a/src/SevenZipContents/SevenZipArchive.php +++ b/src/SevenZipContents/SevenZipArchive.php @@ -31,7 +31,7 @@ private static function getBinary7zFromPath(): string $binary7z = null; foreach (self::EXECUTABLES as $executable) { $resultCode = 0; - $binary7z = exec('which ' . escapeshellarg($executable), result_code: $resultCode); // @phpstan-ignore-line + $binary7z = exec('which ' . escapeshellarg($executable), result_code: $resultCode); if ($resultCode === 0 && is_string($binary7z) && $binary7z !== '' && file_exists($binary7z)) { break; diff --git a/tests/Application/ApplicationTraitTest.php b/tests/Application/ApplicationTraitTest.php new file mode 100644 index 0000000..dd6448b --- /dev/null +++ b/tests/Application/ApplicationTraitTest.php @@ -0,0 +1,35 @@ +set('event_dispatcher', new EventDispatcher()); + + self::$kernel = $this->createMock(KernelInterface::class); + self::$kernel->expects($this->atLeastOnce()) + ->method('getContainer') + ->willReturn($container); + + $tester = $this->runApplication(['help']); + + $this->assertApplicationOutputContains('help', $tester); + + self::$kernel->shutdown(); + } +} diff --git a/tests/Console/CommandTraitTest.php b/tests/Console/CommandTraitTest.php new file mode 100644 index 0000000..080f498 --- /dev/null +++ b/tests/Console/CommandTraitTest.php @@ -0,0 +1,31 @@ +createMock(KernelInterface::class); + self::$kernel->expects($this->atLeastOnce()) + ->method('getContainer') + ->willReturn($container); + + $tester = $this->runCommand('help'); + + $this->assertCommandOutputContains('help', $tester); + } +} diff --git a/tests/HttpClientMock/Matcher/CatchAllMatcherTest.php b/tests/HttpClientMock/Matcher/CatchAllMatcherTest.php index c45bcf7..ed5304d 100644 --- a/tests/HttpClientMock/Matcher/CatchAllMatcherTest.php +++ b/tests/HttpClientMock/Matcher/CatchAllMatcherTest.php @@ -5,7 +5,6 @@ namespace Brainbits\FunctionalTestHelpers\Tests\HttpClientMock\Matcher; use Brainbits\FunctionalTestHelpers\HttpClientMock\Matcher\CatchAllMatcher; -use Brainbits\FunctionalTestHelpers\HttpClientMock\Matcher\Hit; use Brainbits\FunctionalTestHelpers\Tests\HttpClientMock\RealRequestTrait; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -24,7 +23,6 @@ public function testMatchContent(): void $result = $matcher($realRequest); - self::assertInstanceOf(Hit::class, $result); self::assertScore(1, $result); self::assertMatcher('catchAll', $result); } diff --git a/tests/Request/RequestBuilderTest.php b/tests/Request/RequestBuilderTest.php index 259c1c1..cb586a3 100644 --- a/tests/Request/RequestBuilderTest.php +++ b/tests/Request/RequestBuilderTest.php @@ -19,18 +19,6 @@ #[CoversClass(RequestBuilder::class)] final class RequestBuilderTest extends TestCase { - public function testItCanBeCreated(): void - { - $builder = RequestBuilder::create( - static fn (...$params) => $params, - static fn (...$params) => $params, - 'POST', - '/test', - ); - - $this->assertInstanceOf(RequestBuilder::class, $builder); - } - public function testMethodIsReturned(): void { $builder = $this->createRequestBuilder('POST'); diff --git a/tests/Request/RequestTraitTest.php b/tests/Request/RequestTraitTest.php index 636324e..2fe7cf1 100644 --- a/tests/Request/RequestTraitTest.php +++ b/tests/Request/RequestTraitTest.php @@ -4,7 +4,6 @@ namespace Brainbits\FunctionalTestHelpers\Tests\Request; -use Brainbits\FunctionalTestHelpers\Request\RequestBuilder; use Brainbits\FunctionalTestHelpers\Request\RequestTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\BrowserKit\HttpBrowser; @@ -19,7 +18,6 @@ public function testBuildCreatesBuilder(): void { $builder = $this->build('POST', 'http://foo'); - $this->assertInstanceOf(RequestBuilder::class, $builder); $this->assertSame('POST', $builder->getMethod()); $this->assertSame('http://foo', $builder->getUri()); }