From b1203019eb04a566be4fbe355bea09d047c13639 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Sat, 17 Feb 2024 10:00:25 +0000 Subject: [PATCH] feat: adds `--without-exception-handling` and `without-deprecation-handling` --- .github/workflows/tests.yml | 6 +- composer.json | 19 +++-- phpunit.xml | 8 +- src/Authentication.php | 18 ++-- src/Container.php | 6 +- src/Database.php | 16 ++-- src/Http.php | 2 +- src/Plugin.php | 89 ++++++++++++++++++++ tests/Options/WithoutDeprecationHandling.php | 13 +++ tests/Options/WithoutExceptionHandling.php | 13 +++ 10 files changed, 158 insertions(+), 32 deletions(-) create mode 100644 src/Plugin.php create mode 100644 tests/Options/WithoutDeprecationHandling.php create mode 100644 tests/Options/WithoutExceptionHandling.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8d46d6f..79b5089 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,10 +10,11 @@ jobs: matrix: os: [ubuntu-latest] php: ['8.1', '8.2', '8.3'] + laravel: ['10', '11'] dependency-version: [prefer-lowest, prefer-stable] parallel: ['', '--parallel'] - name: PHP ${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }} - ${{ matrix.parallel }} + name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - ${{ matrix.os }} - ${{ matrix.dependency-version }} - ${{ matrix.parallel }} steps: - name: Checkout @@ -37,3 +38,6 @@ jobs: - name: Unit Tests run: composer test:unit + + - name: Unit Options Tests + run: composer test:unit:options diff --git a/composer.json b/composer.json index 87792b5..9086a82 100644 --- a/composer.json +++ b/composer.json @@ -13,8 +13,8 @@ "license": "MIT", "require": { "php": "^8.1.0", - "laravel/framework": "^10.27.0|^11.0", - "pestphp/pest": "^2.22.0" + "laravel/framework": "^10.44.0|^11.0", + "pestphp/pest": "^2.33.6" }, "autoload": { "psr-4": { @@ -30,8 +30,8 @@ } }, "require-dev": { - "laravel/dusk": "^7.11.1", - "orchestra/testbench": "^8.13.0", + "laravel/dusk": "^7.12.3", + "orchestra/testbench": "^8.21.1|^9.0.0", "pestphp/pest-dev-tools": "^2.16.0" }, "minimum-stability": "dev", @@ -48,15 +48,22 @@ "providers": [ "Pest\\Laravel\\PestServiceProvider" ] + }, + "pest": { + "plugins": [ + "Pest\\Laravel\\Plugin" + ] } }, "scripts": { "lint": "pint", "test:lint": "pint --test", - "test:unit": "pest --colors=always", + "test:unit": "pest --colors=always --exclude-group=options", + "test:unit:options": "pest --colors=always --group=options --without-exception-handling --without-deprecation-handling", "test": [ "@test:lint", - "@test:unit" + "@test:unit", + "@test:unit:options" ] } } diff --git a/phpunit.xml b/phpunit.xml index 368f6bd..5936497 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -8,9 +8,9 @@ ./tests - - + + ./src - - + + diff --git a/src/Authentication.php b/src/Authentication.php index 3d46a2a..aa4166f 100644 --- a/src/Authentication.php +++ b/src/Authentication.php @@ -12,7 +12,7 @@ * * @return TestCase */ -function actingAs(Authenticatable $user, string $driver = null) +function actingAs(Authenticatable $user, ?string $driver = null) { return test()->actingAs(...func_get_args()); } @@ -22,7 +22,7 @@ function actingAs(Authenticatable $user, string $driver = null) * * @return TestCase */ -function be(Authenticatable $user, string $driver = null) +function be(Authenticatable $user, ?string $driver = null) { return test()->be(...func_get_args()); } @@ -32,7 +32,7 @@ function be(Authenticatable $user, string $driver = null) * * @return TestCase */ -function assertAuthenticated(string $guard = null) +function assertAuthenticated(?string $guard = null) { return test()->assertAuthenticated(...func_get_args()); } @@ -42,7 +42,7 @@ function assertAuthenticated(string $guard = null) * * @return TestCase */ -function assertGuest(string $guard = null) +function assertGuest(?string $guard = null) { return test()->assertGuest(...func_get_args()); } @@ -52,7 +52,7 @@ function assertGuest(string $guard = null) * * @return bool */ -function isAuthenticated(string $guard = null) +function isAuthenticated(?string $guard = null) { return test()->isAuthenticated(...func_get_args()); } @@ -62,7 +62,7 @@ function isAuthenticated(string $guard = null) * * @return TestCase */ -function assertAuthenticatedAs(Authenticatable $user, string $guard = null) +function assertAuthenticatedAs(Authenticatable $user, ?string $guard = null) { return test()->assertAuthenticatedAs(...func_get_args()); } @@ -72,7 +72,7 @@ function assertAuthenticatedAs(Authenticatable $user, string $guard = null) * * @return TestCase */ -function assertCredentials(array $credentials, string $guard = null) +function assertCredentials(array $credentials, ?string $guard = null) { return test()->assertCredentials(...func_get_args()); } @@ -82,7 +82,7 @@ function assertCredentials(array $credentials, string $guard = null) * * @return TestCase */ -function assertInvalidCredentials(array $credentials, string $guard = null) +function assertInvalidCredentials(array $credentials, ?string $guard = null) { return test()->assertInvalidCredentials(...func_get_args()); } @@ -90,7 +90,7 @@ function assertInvalidCredentials(array $credentials, string $guard = null) /** * Return true if the credentials are valid, false otherwise. */ -function hasCredentials(array $credentials, string $guard = null): bool +function hasCredentials(array $credentials, ?string $guard = null): bool { return test()->hasCredentials(...func_get_args()); } diff --git a/src/Container.php b/src/Container.php index 65a1f50..486a775 100644 --- a/src/Container.php +++ b/src/Container.php @@ -27,7 +27,7 @@ function instance(string $abstract, object $instance): object /** * Mock an instance of an object in the container. */ -function mock(string $abstract, Closure $mock = null): MockInterface +function mock(string $abstract, ?Closure $mock = null): MockInterface { return test()->mock(...func_get_args()); } @@ -35,7 +35,7 @@ function mock(string $abstract, Closure $mock = null): MockInterface /** * Mock a partial instance of an object in the container. */ -function partialMock(string $abstract, Closure $mock = null): MockInterface +function partialMock(string $abstract, ?Closure $mock = null): MockInterface { return test()->partialMock(...func_get_args()); } @@ -43,7 +43,7 @@ function partialMock(string $abstract, Closure $mock = null): MockInterface /** * Spy an instance of an object in the container. */ -function spy(string $abstract, Closure $mock = null): MockInterface +function spy(string $abstract, ?Closure $mock = null): MockInterface { return test()->spy(...func_get_args()); } diff --git a/src/Database.php b/src/Database.php index 33f251c..3662946 100644 --- a/src/Database.php +++ b/src/Database.php @@ -13,7 +13,7 @@ * * @return TestCase */ -function assertDatabaseHas(string $table, array $data, string $connection = null) +function assertDatabaseHas(string $table, array $data, ?string $connection = null) { return test()->assertDatabaseHas(...func_get_args()); } @@ -23,7 +23,7 @@ function assertDatabaseHas(string $table, array $data, string $connection = null * * @return TestCase */ -function assertDatabaseMissing(string $table, array $data, string $connection = null) +function assertDatabaseMissing(string $table, array $data, ?string $connection = null) { return test()->assertDatabaseMissing(...func_get_args()); } @@ -33,7 +33,7 @@ function assertDatabaseMissing(string $table, array $data, string $connection = * * @return TestCase */ -function assertDatabaseEmpty(string $table, string $connection = null) +function assertDatabaseEmpty(string $table, ?string $connection = null) { return test()->assertDatabaseEmpty(...func_get_args()); } @@ -63,7 +63,7 @@ function assertModelMissing(Model $model) * * @return TestCase */ -function assertDatabaseCount(string $table, int $count, string $connection = null) +function assertDatabaseCount(string $table, int $count, ?string $connection = null) { return test()->assertDatabaseCount(...func_get_args()); } @@ -74,7 +74,7 @@ function assertDatabaseCount(string $table, int $count, string $connection = nul * @param Model|string $table * @return TestCase */ -function assertSoftDeleted($table, array $data = [], string $connection = null, string $deletedAtColumn = 'deleted_at') +function assertSoftDeleted($table, array $data = [], ?string $connection = null, string $deletedAtColumn = 'deleted_at') { return test()->assertSoftDeleted(...func_get_args()); } @@ -85,7 +85,7 @@ function assertSoftDeleted($table, array $data = [], string $connection = null, * @param Model|string $table * @return TestCase */ -function assertNotSoftDeleted($table, array $data = [], string $connection = null, string $deletedAtColumn = 'deleted_at') +function assertNotSoftDeleted($table, array $data = [], ?string $connection = null, string $deletedAtColumn = 'deleted_at') { return test()->assertNotSoftDeleted(...func_get_args()); } @@ -103,7 +103,7 @@ function isSoftDeletableModel($model): bool /** * Get the database connection. */ -function getConnection(string $connection = null): Connection +function getConnection(?string $connection = null): Connection { return test()->getConnection(...func_get_args()); } @@ -123,7 +123,7 @@ function seed(array|string $class = 'Database\\Seeders\\DatabaseSeeder') * * @return TestCase */ -function expectsDatabaseQueryCount(int $excepted, string $connection = null) +function expectsDatabaseQueryCount(int $excepted, ?string $connection = null) { return test()->expectsDatabaseQueryCount(...func_get_args()); } diff --git a/src/Http.php b/src/Http.php index a9b4cf0..04a8d76 100644 --- a/src/Http.php +++ b/src/Http.php @@ -324,7 +324,7 @@ function json(string $method, string $uri, array $data = [], array $headers = [] * * @return TestResponse */ -function call(string $method, string $uri, array $parameters = [], array $cookies = [], array $files = [], array $server = [], string $content = null) +function call(string $method, string $uri, array $parameters = [], array $cookies = [], array $files = [], array $server = [], ?string $content = null) { return test()->call(...func_get_args()); } diff --git a/src/Plugin.php b/src/Plugin.php new file mode 100644 index 0000000..029c468 --- /dev/null +++ b/src/Plugin.php @@ -0,0 +1,89 @@ +hasArgument('--with-exception-handling', $arguments)) { + $arguments = $this->popArgument('--with-exception-handling', $arguments); + + $interactsWithExceptionHandling = function (TestCase $testCase): bool { + return function_exists('trait_uses_recursive') && trait_uses_recursive($testCase, InteractsWithExceptionHandling::class); + }; + + uses()->beforeEach(function () use ($interactsWithExceptionHandling) { + /** @var TestCase $this */ + if ($interactsWithExceptionHandling($this)) { + /** @var TestCase&InteractsWithExceptionHandling $this */ + $this->withExceptionHandling(); + } + })->in(TestSuite::getInstance()->rootPath); + } + + if ($this->hasArgument('--without-exception-handling', $arguments)) { + $arguments = $this->popArgument('--without-exception-handling', $arguments); + + $interactsWithExceptionHandling = function (TestCase $testCase): bool { + return function_exists('trait_uses_recursive') && trait_uses_recursive($testCase, InteractsWithExceptionHandling::class); + }; + + uses()->beforeEach(function () use ($interactsWithExceptionHandling) { + /** @var TestCase $this */ + if ($interactsWithExceptionHandling($this)) { + /** @var TestCase&InteractsWithExceptionHandling $this */ + $this->withoutExceptionHandling(); + } + })->in(TestSuite::getInstance()->rootPath); + } + + if ($this->hasArgument('--with-deprecation-handling', $arguments)) { + $arguments = $this->popArgument('--with-deprecation-handling', $arguments); + + $interactsWithDeprecationHandling = function (TestCase $testCase): bool { + return function_exists('trait_uses_recursive') && trait_uses_recursive($testCase, InteractsWithDeprecationHandling::class); + }; + + uses()->beforeEach(function () use ($interactsWithDeprecationHandling) { + /** @var TestCase $this */ + if ($interactsWithDeprecationHandling($this)) { + /** @var TestCase&InteractsWithDeprecationHandling $this */ + $this->withDeprecationHandling(); + } + })->in(TestSuite::getInstance()->rootPath); + } + + if ($this->hasArgument('--without-deprecation-handling', $arguments)) { + $arguments = $this->popArgument('--without-deprecation-handling', $arguments); + + $interactsWithDeprecationHandling = function (TestCase $testCase): bool { + return function_exists('trait_uses_recursive') && trait_uses_recursive($testCase, InteractsWithDeprecationHandling::class); + }; + + uses()->beforeEach(function () use ($interactsWithDeprecationHandling) { + /** @var TestCase $this */ + if ($interactsWithDeprecationHandling($this)) { + /** @var TestCase&InteractsWithDeprecationHandling $this */ + $this->withoutDeprecationHandling(); + } + })->in(TestSuite::getInstance()->rootPath); + } + + return $arguments; + } +} diff --git a/tests/Options/WithoutDeprecationHandling.php b/tests/Options/WithoutDeprecationHandling.php new file mode 100644 index 0000000..7c9f570 --- /dev/null +++ b/tests/Options/WithoutDeprecationHandling.php @@ -0,0 +1,13 @@ +group('options'); + +test('--without-deprecation-handling', function () { + Route::get('/exception', function () { + str_replace(null, null, null); + }); + + $this->get('/exception'); +})->throws(Exception::class, 'str_replace(): Passing null to parameter #1 ($search) of type array|string is deprecated'); diff --git a/tests/Options/WithoutExceptionHandling.php b/tests/Options/WithoutExceptionHandling.php new file mode 100644 index 0000000..d19ed20 --- /dev/null +++ b/tests/Options/WithoutExceptionHandling.php @@ -0,0 +1,13 @@ +group('options'); + +test('--without-exception-handling', function () { + Route::get('/exception', function () { + throw new Exception('Exception message'); + }); + + $this->get('/exception'); +})->throws(Exception::class, 'Exception message');