From abefd181cc66686d8b766877c2b506e4bb562fb2 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Tue, 3 Dec 2024 08:06:46 +0800 Subject: [PATCH 1/3] wip Signed-off-by: Mior Muhammad Zaki --- src/Concerns/InteractsWithWorkbench.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Concerns/InteractsWithWorkbench.php b/src/Concerns/InteractsWithWorkbench.php index e8208996..20730924 100644 --- a/src/Concerns/InteractsWithWorkbench.php +++ b/src/Concerns/InteractsWithWorkbench.php @@ -64,7 +64,7 @@ protected function getPackageBootstrappersUsingWorkbench($app): ?array * Get package providers. * * @param \Illuminate\Foundation\Application $app - * @return array|null + * @return array>|null */ protected function getPackageProvidersUsingWorkbench($app): ?array { From bbe3b5c23067db564547f88cf4ae33b5b9d61a92 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Wed, 4 Dec 2024 15:11:07 +0800 Subject: [PATCH 2/3] [7.x] Add new `Orchestra\Testbench\laravel_or_fail()` function (#270) * [7.x] Add new `ApplicationNotAvailableException::validate()` method Signed-off-by: Mior Muhammad Zaki * wip Signed-off-by: Mior Muhammad Zaki * wip Signed-off-by: Mior Muhammad Zaki * wip Signed-off-by: Mior Muhammad Zaki * wip Signed-off-by: Mior Muhammad Zaki * wip Signed-off-by: Mior Muhammad Zaki --------- Signed-off-by: Mior Muhammad Zaki --- src/Concerns/HandlesDatabases.php | 11 ++++----- src/Concerns/InteractsWithMigrations.php | 27 ++++++++------------- src/Concerns/InteractsWithTestCase.php | 13 ++++------ src/Concerns/WithFactories.php | 9 +++---- src/Foundation/Application.php | 7 ++++++ src/functions.php | 30 ++++++++++++++++++++++++ tests/HelpersTest.php | 13 ++++++++++ 7 files changed, 71 insertions(+), 39 deletions(-) diff --git a/src/Concerns/HandlesDatabases.php b/src/Concerns/HandlesDatabases.php index e6728455..fd04bab4 100644 --- a/src/Concerns/HandlesDatabases.php +++ b/src/Concerns/HandlesDatabases.php @@ -6,9 +6,10 @@ use Illuminate\Database\Events\DatabaseRefreshed; use Orchestra\Testbench\Attributes\DefineDatabase; use Orchestra\Testbench\Attributes\WithMigration; -use Orchestra\Testbench\Exceptions\ApplicationNotAvailableException; use Orchestra\Testbench\Features\TestingFeature; +use function Orchestra\Testbench\laravel_or_fail; + /** * @internal */ @@ -21,9 +22,7 @@ trait HandlesDatabases */ protected function setUpDatabaseRequirements(Closure $callback): void { - if (\is_null($app = $this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } + $app = laravel_or_fail($this->app); $app['events']->listen(DatabaseRefreshed::class, function () { $this->defineDatabaseMigrationsAfterDatabaseRefreshed(); @@ -63,9 +62,7 @@ protected function setUpDatabaseRequirements(Closure $callback): void */ protected function usesSqliteInMemoryDatabaseConnection(?string $connection = null): bool { - if (\is_null($app = $this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } + $app = laravel_or_fail($this->app); /** @var \Illuminate\Contracts\Config\Repository $config */ $config = $app->make('config'); diff --git a/src/Concerns/InteractsWithMigrations.php b/src/Concerns/InteractsWithMigrations.php index 5f74afdc..75ceb3b1 100644 --- a/src/Concerns/InteractsWithMigrations.php +++ b/src/Concerns/InteractsWithMigrations.php @@ -7,9 +7,9 @@ use InvalidArgumentException; use Orchestra\Testbench\Attributes\ResetRefreshDatabaseState; use Orchestra\Testbench\Database\MigrateProcessor; -use Orchestra\Testbench\Exceptions\ApplicationNotAvailableException; use function Orchestra\Testbench\default_migration_path; +use function Orchestra\Testbench\laravel_or_fail; use function Orchestra\Testbench\load_migration_paths; /** @@ -62,18 +62,17 @@ protected function tearDownInteractsWithMigrations(): void */ protected function loadMigrationsFrom($paths): void { + $app = laravel_or_fail($this->app); + if ( (\is_string($paths) || Arr::isList($paths)) && static::usesRefreshDatabaseTestingConcern() && RefreshDatabaseState::$migrated === false && RefreshDatabaseState::$lazilyRefreshed === false ) { - if (\is_null($this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } /** @var array|string $paths */ - load_migration_paths($this->app, $paths); + load_migration_paths($app, $paths); return; } @@ -92,16 +91,14 @@ protected function loadMigrationsFrom($paths): void */ protected function loadMigrationsWithoutRollbackFrom($paths): void { - if (\is_null($this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } + $app = laravel_or_fail($this->app); $migrator = new MigrateProcessor($this, $this->resolvePackageMigrationsOptions($paths)); $migrator->up(); array_unshift($this->cachedTestMigratorProcessors, $migrator); - $this->resetApplicationArtisanCommands($this->app); + $this->resetApplicationArtisanCommands($app); } /** @@ -146,9 +143,7 @@ protected function loadLaravelMigrations($database = []): void */ protected function loadLaravelMigrationsWithoutRollback($database = []): void { - if (\is_null($this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } + $app = laravel_or_fail($this->app); $options = $this->resolveLaravelMigrationsOptions($database); $options['--path'] = default_migration_path(); @@ -159,7 +154,7 @@ protected function loadLaravelMigrationsWithoutRollback($database = []): void array_unshift($this->cachedTestMigratorProcessors, $migrator); - $this->resetApplicationArtisanCommands($this->app); + $this->resetApplicationArtisanCommands($app); } /** @@ -183,16 +178,14 @@ protected function runLaravelMigrations($database = []): void */ protected function runLaravelMigrationsWithoutRollback($database = []): void { - if (\is_null($this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } + $app = laravel_or_fail($this->app); $migrator = new MigrateProcessor($this, $this->resolveLaravelMigrationsOptions($database)); $migrator->up(); array_unshift($this->cachedTestMigratorProcessors, $migrator); - $this->resetApplicationArtisanCommands($this->app); + $this->resetApplicationArtisanCommands($app); } /** diff --git a/src/Concerns/InteractsWithTestCase.php b/src/Concerns/InteractsWithTestCase.php index cf5d1226..a3684709 100644 --- a/src/Concerns/InteractsWithTestCase.php +++ b/src/Concerns/InteractsWithTestCase.php @@ -10,9 +10,10 @@ use Orchestra\Testbench\Contracts\Attributes\BeforeAll as BeforeAllContract; use Orchestra\Testbench\Contracts\Attributes\BeforeEach as BeforeEachContract; use Orchestra\Testbench\Contracts\Attributes\Resolvable as ResolvableContract; -use Orchestra\Testbench\Exceptions\ApplicationNotAvailableException; use Orchestra\Testbench\PHPUnit\AttributeParser; +use function Orchestra\Testbench\laravel_or_fail; + /** * @internal * @@ -124,10 +125,7 @@ abstract protected static function resolvePhpUnitAttributesForMethod(string $cla */ protected function setUpTheTestEnvironmentUsingTestCase(): void { - /** @phpstan-ignore-next-line */ - if (\is_null($app = $this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } + $app = laravel_or_fail($this->app); $this->resolvePhpUnitAttributes() ->flatten() @@ -144,10 +142,7 @@ protected function setUpTheTestEnvironmentUsingTestCase(): void */ protected function tearDownTheTestEnvironmentUsingTestCase(): void { - /** @phpstan-ignore-next-line */ - if (\is_null($app = $this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } + $app = laravel_or_fail($this->app); $this->resolvePhpUnitAttributes() ->flatten() diff --git a/src/Concerns/WithFactories.php b/src/Concerns/WithFactories.php index 6091c425..b23fe742 100644 --- a/src/Concerns/WithFactories.php +++ b/src/Concerns/WithFactories.php @@ -4,7 +4,8 @@ use Exception; use Illuminate\Database\Eloquent\Factory as ModelFactory; -use Orchestra\Testbench\Exceptions\ApplicationNotAvailableException; + +use function Orchestra\Testbench\laravel_or_fail; /** * @api @@ -25,11 +26,7 @@ trait WithFactories */ protected function withFactories(string $path) { - if (\is_null($this->app)) { - throw ApplicationNotAvailableException::make(__METHOD__); - } - - return $this->loadFactoriesUsing($this->app, $path); + return $this->loadFactoriesUsing(laravel_or_fail($this->app), $path); } /** diff --git a/src/Foundation/Application.php b/src/Foundation/Application.php index f0fe3583..2d966c52 100644 --- a/src/Foundation/Application.php +++ b/src/Foundation/Application.php @@ -35,6 +35,13 @@ class Application resolveApplicationConfiguration as protected resolveApplicationConfigurationFromTrait; } + /** + * The Illuminate application instance. + * + * @var \Illuminate\Foundation\Application|null + */ + protected $app; + /** * The application base path. * diff --git a/src/functions.php b/src/functions.php index 01bb9f99..2fe36af5 100644 --- a/src/functions.php +++ b/src/functions.php @@ -444,3 +444,33 @@ function join_paths(?string $basePath, string ...$paths): string return $basePath.implode('', $paths); } + +/** + * Ensure the provided `$app` return an instance of Laravel application or throw an exception. + * + * @internal + * + * @param \Illuminate\Foundation\Application|null $app + * @param string|null $caller + * @return \Illuminate\Foundation\Application + * + * @throws \Orchestra\Testbench\Exceptions\ApplicationNotAvailableException + */ +function laravel_or_fail($app, ?string $caller = null): Application +{ + if ($app instanceof Application) { + return $app; + } + + if (\is_null($caller)) { + $caller = transform(debug_backtrace()[1], function ($debug) { + if (isset($debug['class']) && isset($debug['function'])) { + return \sprintf('%s::%s', $debug['class'], $debug['function']); + } + + return $debug['function']; + }); + } + + throw Exceptions\ApplicationNotAvailableException::make($caller ?? debug_backtrace()[1]['function']); +} diff --git a/tests/HelpersTest.php b/tests/HelpersTest.php index e32a689c..55ca9e5f 100644 --- a/tests/HelpersTest.php +++ b/tests/HelpersTest.php @@ -3,9 +3,11 @@ namespace Orchestra\Testbench\Tests; use Illuminate\Foundation\Application; +use Orchestra\Testbench\Exceptions\ApplicationNotAvailableException; use Orchestra\Testbench\TestCase; use PHPUnit\Runner\Version; +use function Orchestra\Testbench\laravel_or_fail; use function Orchestra\Testbench\laravel_version_compare; use function Orchestra\Testbench\phpunit_version_compare; @@ -24,4 +26,15 @@ public function it_can_compare_phpunit_version() $this->assertSame(0, phpunit_version_compare(Version::id())); $this->assertTrue(phpunit_version_compare(Version::id(), '==')); } + + /** + * @test + */ + public function it_can_throw_application_not_available_application_when_app_is_not_laravel() + { + $this->expectException(ApplicationNotAvailableException::class); + $this->expectExceptionMessage(\sprintf('Application is not available to run [%s]', __METHOD__)); + + laravel_or_fail(null); + } } From 768ffc88eeab4a3dda8ccc70306534bf94c2c714 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Wed, 4 Dec 2024 17:15:02 +0800 Subject: [PATCH 3/3] wip Signed-off-by: Mior Muhammad Zaki --- src/functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/functions.php b/src/functions.php index 8bf837da..39cea299 100644 --- a/src/functions.php +++ b/src/functions.php @@ -474,6 +474,7 @@ function laravel_or_fail($app, ?string $caller = null): Application if (\is_null($caller)) { $caller = transform(debug_backtrace()[1], function ($debug) { + /** @phpstan-ignore isset.offset */ if (isset($debug['class']) && isset($debug['function'])) { return \sprintf('%s::%s', $debug['class'], $debug['function']); } @@ -482,5 +483,5 @@ function laravel_or_fail($app, ?string $caller = null): Application }); } - throw Exceptions\ApplicationNotAvailableException::make($caller ?? debug_backtrace()[1]['function']); + throw Exceptions\ApplicationNotAvailableException::make($caller); }