diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 3bc2731..a07a506 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -13,19 +13,12 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest] - php: [8.1, 8.2] - laravel: [9.*, 10.*, 11.*] + php: [8.2, 8.3] + laravel: [11.*] stability: [prefer-stable] include: - - laravel: 9.* - testbench: ^7.0 - - laravel: 10.* - testbench: ^8.0 - laravel: 11.* testbench: ^9.0 - exclude: - - laravel: 11.* - php: 8.1 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} diff --git a/composer.json b/composer.json index bfad46c..ff757d2 100644 --- a/composer.json +++ b/composer.json @@ -18,17 +18,17 @@ "require": { "php": "^8.1", "filament/filament": "^3.0", - "laravel/horizon": "^5.21", - "laravel/telescope": "^4.16|^5.0", - "spatie/laravel-package-tools": "^1.9.2" + "illuminate/contracts": "^11.0", + "spatie/laravel-package-tools": "^1.16.0" }, "require-dev": { - "laravel/pint": "^1.13", - "nunomaduro/collision": "^5.11|^6.4|^7.0|^8.0", - "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0", - "pestphp/pest": "^1.4|^2.24", - "pestphp/pest-plugin-laravel": "^1.22|^2.2", - "phpunit/phpunit": "^9.0|^10.0" + "laravel/pint": "^1.17", + "nunomaduro/collision": "^8.0", + "orchestra/testbench": "^9.0", + "pestphp/pest": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0", + "pestphp/pest-plugin-livewire": "^3.0", + "phpunit/phpunit": "^11.0" }, "autoload": { "psr-4": { diff --git a/config/filament-debugger.php b/config/filament-debugger.php deleted file mode 100644 index be41402..0000000 --- a/config/filament-debugger.php +++ /dev/null @@ -1,22 +0,0 @@ - [ - 'horizon', - 'telescope', - ], - - 'authorization' => false, - - 'permissions' => [ - 'horizon' => 'horizon.view', - 'telescope' => 'telescope.view', - ], - - 'group' => 'Debugger', - - 'url' => [ - 'horizon' => env('HORIZON_PATH', 'horizon'), - 'telescope' => env('TELESCOPE_PATH', 'telescope'), - ], -]; diff --git a/pint.json b/pint.json index c3238c9..1cfcc92 100644 --- a/pint.json +++ b/pint.json @@ -1,4 +1,16 @@ { + "preset": "laravel", + "rules": { + "blank_line_before_statement": true, + "concat_space": { + "spacing": "one" + }, + "method_argument_space": true, + "single_trait_insert_per_statement": true, + "types_spaces": { + "space": "single" + } + }, "exclude": [ "build" ] diff --git a/src/Commands/DebuggerCommand.php b/src/Commands/DebuggerCommand.php deleted file mode 100644 index 799b8f7..0000000 --- a/src/Commands/DebuggerCommand.php +++ /dev/null @@ -1,44 +0,0 @@ -installHorizon(); - - $this->installTelescope(); - - $this->publishConfig(); - - $this->info('Filament Debugger Installed.'); - - return self::SUCCESS; - } - - public function publishConfig() - { - $this->call('vendor:publish', ['--tag' => 'filament-debugger-config']); - } - - public function installHorizon() - { - $this->callSilent('horizon:install'); - - $this->info('Laravel Horizon installed.'); - } - - public function installTelescope() - { - $this->callSilent('telescope:install'); - - $this->info('Laravel Telescope installed.'); - } -} diff --git a/src/DebuggerPlugin.php b/src/DebuggerPlugin.php index 5fc2f12..a27e5b6 100755 --- a/src/DebuggerPlugin.php +++ b/src/DebuggerPlugin.php @@ -4,31 +4,19 @@ use Filament\Contracts\Plugin; use Filament\Panel; -use Stephenjude\FilamentDebugger\Traits\HasDebuggers; +use Stephenjude\FilamentDebugger\Traits\HasAuthorization; +use Stephenjude\FilamentDebugger\Traits\HasGroup; +use Stephenjude\FilamentDebugger\Traits\HasHorizon; +use Stephenjude\FilamentDebugger\Traits\HasPulse; +use Stephenjude\FilamentDebugger\Traits\HasTelescope; class DebuggerPlugin implements Plugin { - use HasDebuggers; - - public function getId(): string - { - return 'filament-debugger'; - } - - public function register(Panel $panel): void {} - - public function boot(Panel $panel): void - { - $panel->navigationItems( - collect([ - 'horizon' => $this->horizon(), - 'telescope' => $this->telescope(), - ]) - ->only(config('filament-debugger.debuggers')) - ->values() - ->toArray() - ); - } + use HasAuthorization; + use HasGroup; + use HasHorizon; + use HasPulse; + use HasTelescope; public static function make(): static { @@ -42,4 +30,24 @@ public static function get(): static return $plugin; } + + public function getId(): string + { + return 'filament-debugger'; + } + + public function register(Panel $panel): void + { + if ($this->authorized() === false) { + return; + } + + $panel->navigationItems(array_filter([ + $this->hasHorizon() ? $this->getHorizonNavigation() : null, + $this->hasPulse() ? $this->getPulseNavigation() : null, + $this->hasTelescope() ? $this->getTelescopeNavigation() : null, + ])); + } + + public function boot(Panel $panel): void {} } diff --git a/src/DebuggerServiceProvider.php b/src/DebuggerServiceProvider.php index faf83cb..b4d5d01 100644 --- a/src/DebuggerServiceProvider.php +++ b/src/DebuggerServiceProvider.php @@ -4,15 +4,12 @@ use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; -use Stephenjude\FilamentDebugger\Commands\DebuggerCommand; class DebuggerServiceProvider extends PackageServiceProvider { public function configurePackage(Package $package): void { $package - ->name('filament-debugger') - ->hasConfigFile() - ->hasCommand(DebuggerCommand::class); + ->name('filament-debugger'); } } diff --git a/src/Traits/HasAuthorization.php b/src/Traits/HasAuthorization.php new file mode 100755 index 0000000..7b7c132 --- /dev/null +++ b/src/Traits/HasAuthorization.php @@ -0,0 +1,25 @@ +authorized = $condition; + + return $this; + } + + public function authorized(): bool + { + return $this->evaluate($this->authorized) === true; + } +} diff --git a/src/Traits/HasDebuggers.php b/src/Traits/HasDebuggers.php deleted file mode 100755 index e5537f9..0000000 --- a/src/Traits/HasDebuggers.php +++ /dev/null @@ -1,37 +0,0 @@ -user()?->can($ability); - } - - return true; - } - - public static function telescope(): NavigationItem - { - return NavigationItem::make() - ->visible(self::authorized(config('filament-debugger.permissions.telescope'))) - ->group(config('filament-debugger.group')) - ->url(url: url()->to(config('filament-debugger.url.telescope')), shouldOpenInNewTab: true) - ->icon('heroicon-o-sparkles') - ->label('Telescope'); - } - - public static function horizon(): NavigationItem - { - return NavigationItem::make() - ->visible(self::authorized(config('filament-debugger.permissions.horizon'))) - ->group(config('filament-debugger.group')) - ->icon('heroicon-o-globe-europe-africa') - ->url(url: url()->to(config('filament-debugger.url.horizon')), shouldOpenInNewTab: true) - ->label('Horizon'); - } -} diff --git a/src/Traits/HasGroup.php b/src/Traits/HasGroup.php new file mode 100755 index 0000000..3f74159 --- /dev/null +++ b/src/Traits/HasGroup.php @@ -0,0 +1,34 @@ +groupNavigation = $condition; + + $this->groupNavigationLabel = $label; + + return $this; + } + + public function hasGroupNavigation(): bool + { + return $this->evaluate($this->groupNavigation) === true; + } + + public function getGroupNavigationLabel(): string + { + return $this->groupNavigationLabel; + } +} diff --git a/src/Traits/HasHorizon.php b/src/Traits/HasHorizon.php new file mode 100755 index 0000000..724c2c1 --- /dev/null +++ b/src/Traits/HasHorizon.php @@ -0,0 +1,76 @@ +group($this->hasGroupNavigation() ? $this->getGroupNavigationLabel() : null) + ->url(url: $this->getHorizonUrl(), shouldOpenInNewTab: $this->getHorizonOpenInNewTab()) + ->icon(icon: $this->getHorizonIcon()) + ->label(label: $this->getHorizonLabel()); + } + + public function horizonNavigation( + Closure | bool $condition = true, + string $label = 'Horizon', + string $icon = 'heroicon-o-globe-europe-africa', + string $url = 'horizon', + Closure | bool $openInNewTab = true + ): static { + $this->hasHorizon = $condition; + + $this->horizonLabel = $label; + + $this->horizonIcon = $icon; + + $this->horizonUrl = $url; + + $this->horizonOpenInNewTab = $openInNewTab; + + return $this; + } + + public function hasHorizon(): bool + { + return $this->evaluate($this->hasHorizon ?? false) === true; + } + + public function getHorizonIcon(): string + { + return $this->horizonIcon ?? 'heroicon-o-globe-europe-africa'; + } + + public function getHorizonUrl(): string + { + return $this->horizonUrl ?? url('horizon'); + } + + public function getHorizonLabel(): string + { + return $this->horizonLabel ?? 'Horizon'; + } + + public function getHorizonOpenInNewTab(): bool + { + return $this->evaluate($this->horizonOpenInNewTab ?? true) === true; + } +} diff --git a/src/Traits/HasPulse.php b/src/Traits/HasPulse.php new file mode 100755 index 0000000..8c360fa --- /dev/null +++ b/src/Traits/HasPulse.php @@ -0,0 +1,76 @@ +hasPulse = $condition; + + $this->pulseLabel = $label; + + $this->pulseIcon = $icon; + + $this->pulseUrl = $url; + + $this->pulseOpenInNewTab = $openInNewTab; + + return $this; + } + + public function hasPulse(): bool + { + return $this->evaluate($this->hasPulse ?? false) === true; + } + + private function getPulseNavigation(): NavigationItem + { + return NavigationItem::make() + ->group($this->hasGroupNavigation() ? $this->getGroupNavigationLabel() : null) + ->url(url: $this->getPulseUrl(), shouldOpenInNewTab: $this->getPulseOpenInNewTab()) + ->icon(icon: $this->getPulseIcon()) + ->label(label: $this->getPulseLabel()); + } + + public function getPulseUrl(): string + { + return $this->pulseUrl ?? url('pulse'); + } + + public function getPulseOpenInNewTab(): bool + { + return $this->evaluate($this->pulseOpenInNewTab ?? true) === true; + } + + public function getPulseIcon(): string + { + return $this->pulseIcon ?? 'heroicon-o-bolt'; + } + + public function getPulseLabel(): string + { + return $this->pulseLabel ?? 'Pulse'; + } +} diff --git a/src/Traits/HasTelescope.php b/src/Traits/HasTelescope.php new file mode 100755 index 0000000..e39d265 --- /dev/null +++ b/src/Traits/HasTelescope.php @@ -0,0 +1,71 @@ +hasTelescope = $condition; + + $this->telescopeLabel = $label; + + $this->telescopeIcon = $icon; + + $this->telescopeUrl = $url; + + $this->telescopeOpenInNewTab = $openInNewTab; + + return $this; + } + + public function hasTelescope(): bool + { + return $this->evaluate($this->hasTelescope ?? true) === true; + } + + private function getTelescopeNavigation(): NavigationItem + { + return NavigationItem::make() + ->group($this->hasGroupNavigation() ? $this->getGroupNavigationLabel() : null) + ->url(url: $this->getTelescopeUrl(), shouldOpenInNewTab: $this->getTelescopeOpenInNewTab()) + ->icon(icon: $this->getTelescopeIcon()) + ->label(label: $this->getTelescopeLabel()); + } + + public function getTelescopeUrl(): string + { + return $this->telescopeUrl ?? url('telescope'); + } + + public function getTelescopeOpenInNewTab(): bool + { + return $this->evaluate($this->telescopeOpenInNewTab) === true; + } + + public function getTelescopeIcon(): string + { + return $this->telescopeIcon ?? 'heroicon-o-sparkles'; + } + + public function getTelescopeLabel(): string + { + return $this->telescopeLabel ?? 'Telescope'; + } +} diff --git a/tests/Common/AdminPanelProvider.php b/tests/Common/AdminPanelProvider.php new file mode 100644 index 0000000..5afeb83 --- /dev/null +++ b/tests/Common/AdminPanelProvider.php @@ -0,0 +1,42 @@ +default() + ->id('admin') + ->path('admin') + ->login() + ->middleware([ + EncryptCookies::class, + AddQueuedCookiesToResponse::class, + StartSession::class, + AuthenticateSession::class, + ShareErrorsFromSession::class, + VerifyCsrfToken::class, + SubstituteBindings::class, + DisableBladeIconComponents::class, + DispatchServingFilamentEvent::class, + ]) + ->authMiddleware([ + Authenticate::class, + ]); + } +} diff --git a/tests/DebuggerTest.php b/tests/DebuggerTest.php index c4f0601..1ca0a67 100644 --- a/tests/DebuggerTest.php +++ b/tests/DebuggerTest.php @@ -3,18 +3,129 @@ use Filament\Navigation\NavigationItem; use Stephenjude\FilamentDebugger\DebuggerPlugin; -it('can install configurations', function () { - $this->artisan('filament-debugger:install') - ->expectsOutput('Laravel Horizon installed.') - ->expectsOutput('Laravel Telescope installed.') - ->expectsOutput('Filament Debugger Installed.') - ->assertExitCode(0); +it('will not use debugging functions') + ->expect(['dd', 'dump', 'ddd']) + ->each->not->toBeUsed(); + +it('registers plugin', function () { + $panel = filament()->getCurrentPanel()->plugin(DebuggerPlugin::make()); + + expect($panel->getPlugin('filament-debugger')) + ->not() + ->toThrow(Exception::class); + + expect($panel->getNavigationItems())->toHaveCount(3); + + $plugin = $panel->getPlugin('filament-debugger'); + + expect($plugin)->hasHorizon()->toBeTrue(); + + expect($plugin)->hasTelescope()->toBeTrue(); + + expect($plugin)->hasPulse()->toBeTrue(); }); -it('can open horizon', function () { - expect(DebuggerPlugin::horizon())->toBeInstanceOf(NavigationItem::class); +it('authorizes plugin', function () { + $panel = filament()->getCurrentPanel()->plugin(DebuggerPlugin::make()->authorize(false)); + + expect($panel->getNavigationItems())->toHaveCount(0); }); -it('can open telescope', function () { - expect(DebuggerPlugin::telescope())->toBeInstanceOf(NavigationItem::class); +it('groups plugin navigation items', function () { + $panel = filament()->getCurrentPanel() + ->plugin( + DebuggerPlugin::make()->groupNavigation( + condition: fn () => true, + label: 'Laravel Debuggers' + ) + ); + + collect($panel->getNavigationItems()) + ->each( + fn (NavigationItem $navigationItem) => expect($navigationItem)->getGroup()->toBe('Laravel Debuggers') + ); +}); + +it('customizes telescope navigation', function () { + $panel = filament()->getCurrentPanel()->plugin( + DebuggerPlugin::make() + ->horizonNavigation(false) + ->pulseNavigation(false) + ->telescopeNavigation( + condition: fn () => true, + label: 'Laravel Telescope', + icon: 'heroicon-o-users', + url: 'telescope/requests', + openInNewTab: fn () => false + ) + ); + + expect($panel->getNavigationItems())->toHaveCount(1); + + /** @var NavigationItem $navigationItem */ + $navigationItem = $panel->getNavigationItems()[0]; + + expect($navigationItem)->getLabel()->toBe('Laravel Telescope'); + + expect($navigationItem)->getIcon()->toBe('heroicon-o-users'); + + expect($navigationItem)->getUrl()->toBe('telescope/requests'); + + expect($navigationItem)->shouldOpenUrlInNewTab()->toBeFalse(); +}); + +it('customizes horizon navigation', function () { + $panel = filament()->getCurrentPanel()->plugin( + DebuggerPlugin::make() + ->telescopeNavigation(false) + ->pulseNavigation(false) + ->horizonNavigation( + condition: fn () => true, + label: 'Laravel Horizon', + icon: 'heroicon-o-users', + url: url('horizon/requests'), + openInNewTab: fn () => false + ) + ); + + expect($panel->getNavigationItems())->toHaveCount(1); + + /** @var NavigationItem $navigationItem */ + $navigationItem = $panel->getNavigationItems()[0]; + + expect($navigationItem)->getLabel()->toBe('Laravel Horizon'); + + expect($navigationItem)->getIcon()->toBe('heroicon-o-users'); + + expect($navigationItem)->getUrl()->toBe(url('horizon/requests')); + + expect($navigationItem)->shouldOpenUrlInNewTab()->toBeFalse(); +}); + +it('customizes pulse navigation', function () { + $panel = filament()->getCurrentPanel()->plugin( + DebuggerPlugin::make() + ->horizonNavigation(false) + ->telescopeNavigation(false) + ->pulseNavigation( + condition: fn () => true, + label: 'Laravel Pulse', + icon: 'heroicon-o-users', + url: 'pulse/requests', + openInNewTab: fn () => false + ) + ); + + expect($panel->getNavigationItems())->toHaveCount(1); + + /** @var NavigationItem $navigationItem */ + $navigationItem = $panel->getNavigationItems()[0]; + + expect($navigationItem)->getLabel()->toBe('Laravel Pulse'); + + expect($navigationItem)->getIcon()->toBe('heroicon-o-users'); + + expect($navigationItem)->getUrl()->toBe('pulse/requests'); + + expect($navigationItem)->shouldOpenUrlInNewTab()->toBeFalse(); }); diff --git a/tests/TestCase.php b/tests/TestCase.php index e929a91..6bb273b 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -5,11 +5,10 @@ use BladeUI\Heroicons\BladeHeroiconsServiceProvider; use BladeUI\Icons\BladeIconsServiceProvider; use Filament\FilamentServiceProvider; -use Laravel\Horizon\HorizonServiceProvider; -use Laravel\Telescope\TelescopeServiceProvider; use Livewire\LivewireServiceProvider; use Orchestra\Testbench\TestCase as Orchestra; use Stephenjude\FilamentDebugger\DebuggerServiceProvider; +use Stephenjude\FilamentDebugger\Tests\Common\AdminPanelProvider; class TestCase extends Orchestra { @@ -25,9 +24,8 @@ protected function getPackageProviders($app) BladeIconsServiceProvider::class, FilamentServiceProvider::class, LivewireServiceProvider::class, - TelescopeServiceProvider::class, - HorizonServiceProvider::class, DebuggerServiceProvider::class, + AdminPanelProvider::class, ]; }