diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 566c8e376..7bb4d0cf7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -23,7 +23,7 @@ jobs: strategy: fail-fast: true matrix: - php: [8.1, 8.2, 8.3, 8.4] + php: [8.1, 8.2, 8.3, 8.4, 8.5] laravel: [10, 11, 12] include: - php: 8.2 @@ -39,6 +39,10 @@ jobs: exclude: - php: 8.4 laravel: 10 + - php: 8.5 + laravel: 10 + - php: 8.5 + laravel: 11 - php: 8.1 laravel: 11 - php: 8.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 255300272..43f214555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,28 @@ # Release Notes -## [Unreleased](https://github.com/laravel/telescope/compare/v5.12.0...5.x) +## [Unreleased](https://github.com/laravel/telescope/compare/v5.15.1...5.x) + +## [v5.15.1](https://github.com/laravel/telescope/compare/v5.15.0...v5.15.1) - 2025-11-25 + +* [5.x] PHP 8.5 Compatibility by [@crynobone](https://github.com/crynobone) in https://github.com/laravel/telescope/pull/1658 + +## [v5.15.0](https://github.com/laravel/telescope/compare/v5.14.1...v5.15.0) - 2025-10-23 + +* Bump vite from 5.4.20 to 5.4.21 by [@dependabot](https://github.com/dependabot)[bot] in https://github.com/laravel/telescope/pull/1649 +* feat: add shouldIgnoreHosts method to filter HTTP client requests by host by [@artengin](https://github.com/artengin) in https://github.com/laravel/telescope/pull/1650 + +## [v5.14.1](https://github.com/laravel/telescope/compare/v5.14.0...v5.14.1) - 2025-10-12 + +* Fix: Record IncomingExceptionEntry with binary content by [@jlswanson28694](https://github.com/jlswanson28694) in https://github.com/laravel/telescope/pull/1646 +* [5.x] Simplify control flow by [@AhmedAlaa4611](https://github.com/AhmedAlaa4611) in https://github.com/laravel/telescope/pull/1645 + +## [v5.14.0](https://github.com/laravel/telescope/compare/v5.13.0...v5.14.0) - 2025-10-06 + +* [5.x] chunk on number of tags rather than number of entries by [@cosmastech](https://github.com/cosmastech) in https://github.com/laravel/telescope/pull/1644 + +## [v5.13.0](https://github.com/laravel/telescope/compare/v5.12.0...v5.13.0) - 2025-09-30 + +* [5.x] Introduce pre-package uninstall listener by [@cosmastech](https://github.com/cosmastech) in https://github.com/laravel/telescope/pull/1641 ## [v5.12.0](https://github.com/laravel/telescope/compare/v5.11.4...v5.12.0) - 2025-09-18 diff --git a/composer.json b/composer.json index a827a714b..a5bfc3784 100644 --- a/composer.json +++ b/composer.json @@ -23,10 +23,9 @@ "require-dev": { "ext-gd": "*", "guzzlehttp/guzzle": "^6.0|^7.0", - "laravel/octane": "^1.4|^2.0|dev-develop", - "orchestra/testbench": "^6.40|^7.37|^8.17|^9.0|^10.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.0|^10.5|^11.5" + "laravel/octane": "^1.4|^2.0", + "orchestra/testbench": "^6.47.1|^7.55|^8.36|^9.15|^10.8", + "phpstan/phpstan": "^1.10" }, "autoload": { "psr-4": { @@ -49,7 +48,10 @@ } }, "config": { - "sort-packages": true + "sort-packages": true, + "audit": { + "block-insecure": false + } }, "scripts": { "post-autoload-dump": "@composer run prepare", diff --git a/config/telescope.php b/config/telescope.php index 1c9438fc3..a241a348e 100644 --- a/config/telescope.php +++ b/config/telescope.php @@ -143,7 +143,10 @@ 'ignore' => [], ], - Watchers\ClientRequestWatcher::class => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true), + Watchers\ClientRequestWatcher::class => [ + 'enabled' => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true), + 'ignore_hosts' => [], + ], Watchers\CommandWatcher::class => [ 'enabled' => env('TELESCOPE_COMMAND_WATCHER', true), diff --git a/package-lock.json b/package-lock.json index eec7ff874..2be099fa1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "popper.js": "^1.16", "sass": "^1.74.1", "sql-formatter": "^15.6.2", - "vite": "^5.4.20", + "vite": "^5.4.21", "vue": "^2.7.16", "vue-copy-to-clipboard": "^1.0.3", "vue-json-pretty": "^1.6.2", @@ -1965,9 +1965,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.4.20", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz", - "integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==", + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 979ad0751..424a40dc9 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "popper.js": "^1.16", "sass": "^1.74.1", "sql-formatter": "^15.6.2", - "vite": "^5.4.20", + "vite": "^5.4.21", "vue": "^2.7.16", "vue-copy-to-clipboard": "^1.0.3", "vue-json-pretty": "^1.6.2", diff --git a/src/Actions/UninstallAction.php b/src/Actions/UninstallAction.php index 048206a49..6e613f3d0 100644 --- a/src/Actions/UninstallAction.php +++ b/src/Actions/UninstallAction.php @@ -8,9 +8,8 @@ class UninstallAction { public function handle(): void { - if (method_exists(ServiceProvider::class, 'removeProviderFromBootstrapFile') && - ServiceProvider::removeProviderFromBootstrapFile('TelescopeServiceProvider')) { - return; + if (method_exists(ServiceProvider::class, 'removeProviderFromBootstrapFile')) { + ServiceProvider::removeProviderFromBootstrapFile('TelescopeServiceProvider'); } } } diff --git a/src/Storage/DatabaseEntriesRepository.php b/src/Storage/DatabaseEntriesRepository.php index a5cc8a5a2..2313e4177 100644 --- a/src/Storage/DatabaseEntriesRepository.php +++ b/src/Storage/DatabaseEntriesRepository.php @@ -41,7 +41,7 @@ class DatabaseEntriesRepository implements Contract, ClearableRepository, Prunab * Create a new database repository. * * @param string $connection - * @param int $chunkSize + * @param int|null $chunkSize * @return void */ public function __construct(string $connection, ?int $chunkSize = null) @@ -126,7 +126,7 @@ protected function countExceptionOccurences(IncomingEntry $exception) /** * Store the given array of entries. * - * @param \Illuminate\Support\Collection|\Laravel\Telescope\IncomingEntry[] $entries + * @param \Illuminate\Support\Collection $entries * @return void */ public function store(Collection $entries) @@ -155,7 +155,7 @@ public function store(Collection $entries) /** * Store the given array of exception entries. * - * @param \Illuminate\Support\Collection|\Laravel\Telescope\IncomingEntry[] $exceptions + * @param \Illuminate\Support\Collection $exceptions * @return void */ protected function storeExceptions(Collection $exceptions) @@ -172,9 +172,10 @@ protected function storeExceptions(Collection $exceptions) return array_merge($exception->toArray(), [ 'family_hash' => $exception->familyHash(), - 'content' => json_encode(array_merge( - $exception->content, ['occurrences' => $occurrences + 1] - )), + 'content' => json_encode( + array_merge($exception->content, ['occurrences' => $occurrences + 1]), + JSON_INVALID_UTF8_SUBSTITUTE + ), ]); })->toArray()); }); @@ -185,25 +186,45 @@ protected function storeExceptions(Collection $exceptions) /** * Store the tags for the given entries. * - * @param \Illuminate\Support\Collection $results + * @param \Illuminate\Support\Collection> $results * @return void */ protected function storeTags(Collection $results) { - $results->chunk($this->chunkSize)->each(function ($chunked) { - try { - $this->table('telescope_entries_tags')->insert($chunked->flatMap(function ($tags, $uuid) { - return collect($tags)->map(function ($tag) use ($uuid) { - return [ - 'entry_uuid' => $uuid, - 'tag' => $tag, - ]; - }); - })->all()); - } catch (UniqueConstraintViolationException $e) { - // Ignore tags that already exist... + $toInsert = []; + + foreach ($results as $uuid => $tags) { + foreach ($tags as $tag) { + $toInsert[] = [ + 'entry_uuid' => $uuid, + 'tag' => $tag, + ]; + + if (count($toInsert) >= $this->chunkSize) { + $this->insertChunkOfTags($toInsert); + $toInsert = []; + } } - }); + } + + if ($toInsert !== []) { + $this->insertChunkOfTags($toInsert); + } + } + + /** + * Insert a chunk of tags, ignoring unique constraint violations. + * + * @param array $tags + * @return void + */ + protected function insertChunkOfTags($tags) + { + try { + $this->table('telescope_entries_tags')->insert($tags); + } catch (UniqueConstraintViolationException $e) { + // Ignore tags that already exist... + } } /** diff --git a/src/Watchers/ClientRequestWatcher.php b/src/Watchers/ClientRequestWatcher.php index 00c61cda8..9cffca4fb 100644 --- a/src/Watchers/ClientRequestWatcher.php +++ b/src/Watchers/ClientRequestWatcher.php @@ -57,7 +57,8 @@ public function recordFailedRequest(ConnectionFailed $event) */ public function recordResponse(ResponseReceived $event) { - if (! Telescope::isRecording()) { + if (! Telescope::isRecording() || + $this->shouldIgnoreHost($event)) { return; } @@ -76,6 +77,19 @@ public function recordResponse(ResponseReceived $event) ); } + /** + * Determine whether to ignore this request based on its host. + * + * @param mixed $event + * @return bool + */ + protected function shouldIgnoreHost($event) + { + $host = $event->request->toPsrRequest()->getUri()->getHost(); + + return in_array($host, Arr::get($this->options, 'ignore_hosts', [])); + } + /** * Determine if the content is within the set limits. * diff --git a/tests/FeatureTestCase.php b/tests/FeatureTestCase.php index 17f0040fe..58b8e10ac 100644 --- a/tests/FeatureTestCase.php +++ b/tests/FeatureTestCase.php @@ -10,14 +10,19 @@ use Laravel\Telescope\Storage\EntryModel; use Laravel\Telescope\Telescope; use Laravel\Telescope\TelescopeServiceProvider; -use Orchestra\Testbench\Concerns\WithLaravelMigrations; +use Orchestra\Testbench\Attributes\WithConfig; +use Orchestra\Testbench\Attributes\WithMigration; use Orchestra\Testbench\Concerns\WithWorkbench; use Orchestra\Testbench\TestCase; +#[WithMigration] +#[WithConfig('logging.default', 'errorlog')] class FeatureTestCase extends TestCase { - use WithWorkbench, RefreshDatabase, WithLaravelMigrations; + use WithWorkbench, RefreshDatabase; + /** {@inheritdoc} */ + #[\Override] protected function setUp(): void { parent::setUp(); @@ -28,6 +33,8 @@ protected function setUp(): void Telescope::$afterStoringHooks = []; } + /** {@inheritdoc} */ + #[\Override] protected function tearDown(): void { Telescope::flushEntries(); @@ -38,6 +45,8 @@ protected function tearDown(): void parent::tearDown(); } + /** {@inheritdoc} */ + #[\Override] protected function getPackageProviders($app) { return [ @@ -45,11 +54,15 @@ protected function getPackageProviders($app) ]; } + /** {@inheritdoc} */ + #[\Override] public function ignorePackageDiscoveriesFrom() { return ['*', 'spatie/laravel-ray']; } + /** {@inheritdoc} */ + #[\Override] protected function resolveApplicationCore($app) { parent::resolveApplicationCore($app); @@ -59,26 +72,19 @@ protected function resolveApplicationCore($app) }); } - /** - * @param \Illuminate\Foundation\Application $app - * @return void - */ - protected function getEnvironmentSetUp($app) + /** {@inheritdoc} */ + #[\Override] + protected function defineEnvironment($app) { - $config = $app->get('config'); - - $config->set('logging.default', 'errorlog'); - - $config->set('database.default', 'testbench'); - - $config->set('telescope.storage.database.connection', 'testbench'); - - $config->set('queue.batching.database', 'testbench'); - - $config->set('database.connections.testbench', [ - 'driver' => 'sqlite', - 'database' => ':memory:', - 'prefix' => '', + $app->make('config')->set([ + 'database.default' => 'testbench', + 'telescope.storage.database.connection' => 'testbench', + 'queue.batching.database' => 'testbench', + 'database.connections.testbench' => [ + 'driver' => 'sqlite', + 'database' => ':memory:', + 'prefix' => '', + ], ]); $app->when(DatabaseEntriesRepository::class) diff --git a/tests/Http/AuthorizationTest.php b/tests/Http/AuthorizationTest.php index c79d11d19..0957d6375 100644 --- a/tests/Http/AuthorizationTest.php +++ b/tests/Http/AuthorizationTest.php @@ -13,6 +13,8 @@ class AuthorizationTest extends FeatureTestCase { + /** {@inheritdoc} */ + #[\Override] protected function getPackageProviders($app) { return array_merge( @@ -21,6 +23,8 @@ protected function getPackageProviders($app) ); } + /** {@inheritdoc} */ + #[\Override] protected function setUp(): void { parent::setUp(); @@ -29,6 +33,8 @@ protected function setUp(): void $this->withoutMiddleware([ValidateCsrfToken::class]); } + /** {@inheritdoc} */ + #[\Override] protected function tearDown(): void { parent::tearDown(); diff --git a/tests/Http/AvatarTest.php b/tests/Http/AvatarTest.php index 500cc8149..c6fa92c48 100644 --- a/tests/Http/AvatarTest.php +++ b/tests/Http/AvatarTest.php @@ -9,10 +9,17 @@ use Laravel\Telescope\Telescope; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\LogWatcher; +use Orchestra\Testbench\Attributes\WithConfig; use Psr\Log\LoggerInterface; +#[WithConfig('logging.default', 'syslog')] +#[WithConfig('telescope.watchers', [ + LogWatcher::class => true, +])] class AvatarTest extends FeatureTestCase { + /** {@inheritdoc} */ + #[\Override] protected function setUp(): void { parent::setUp(); @@ -20,21 +27,7 @@ protected function setUp(): void $this->withoutMiddleware(Authorize::class); } - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('logging.default', 'syslog'); - - $app->get('config')->set('telescope.watchers', [ - LogWatcher::class => true, - ]); - } - - /** - * @test - */ - public function it_can_generate_avatar_url() + public function test_it_can_generate_avatar_url() { $user = null; @@ -70,10 +63,7 @@ public function it_can_generate_avatar_url() ]); } - /** - * @test - */ - public function it_can_register_custom_avatar_path() + public function test_it_can_register_custom_avatar_path() { $user = null; @@ -113,10 +103,7 @@ public function it_can_register_custom_avatar_path() ]); } - /** - * @test - */ - public function it_can_read_custom_avatar_path_on_null_email() + public function test_it_can_read_custom_avatar_path_on_null_email() { $user = null; diff --git a/tests/Http/RouteTest.php b/tests/Http/RouteTest.php index cc0b5cad5..ec885ed78 100644 --- a/tests/Http/RouteTest.php +++ b/tests/Http/RouteTest.php @@ -10,9 +10,12 @@ use Laravel\Telescope\Tests\FeatureTestCase; use Orchestra\Testbench\Http\Middleware\VerifyCsrfToken; use PHPUnit\Framework\Assert as PHPUnit; +use PHPUnit\Framework\Attributes\DataProvider; class RouteTest extends FeatureTestCase { + /** {@inheritdoc} */ + #[\Override] protected function setUp(): void { parent::setUp(); @@ -46,7 +49,8 @@ public static function telescopeIndexRoutesProvider() /** * @dataProvider telescopeIndexRoutesProvider */ - public function test_route($endpoint) + #[DataProvider('telescopeIndexRoutesProvider')] + public function test_route($endpoint, $entryType) { $this->post($endpoint) ->assertSuccessful() @@ -56,6 +60,7 @@ public function test_route($endpoint) /** * @dataProvider telescopeIndexRoutesProvider */ + #[DataProvider('telescopeIndexRoutesProvider')] public function test_simple_list_of_entries($endpoint, $entryType) { $entry = EntryModelFactory::new()->create(['type' => $entryType]); diff --git a/tests/Storage/DatabaseEntriesRepositoryTest.php b/tests/Storage/DatabaseEntriesRepositoryTest.php index 517c8f852..1e41088d7 100644 --- a/tests/Storage/DatabaseEntriesRepositoryTest.php +++ b/tests/Storage/DatabaseEntriesRepositoryTest.php @@ -2,8 +2,12 @@ namespace Laravel\Telescope\Tests\Storage; +use Illuminate\Support\Str; use Laravel\Telescope\Database\Factories\EntryModelFactory; +use Laravel\Telescope\EntryType; use Laravel\Telescope\EntryUpdate; +use Laravel\Telescope\IncomingEntry; +use Laravel\Telescope\IncomingExceptionEntry; use Laravel\Telescope\Storage\DatabaseEntriesRepository; use Laravel\Telescope\Tests\FeatureTestCase; @@ -42,4 +46,30 @@ public function test_update() $this->assertCount(1, $failedUpdates); $this->assertSame('missing-id', $failedUpdates->first()->uuid); } + + public function test_store_binary_content() + { + $batchId = Str::uuid(); + $exception = new \Exception('message'); + + $entries = collect([ + (new IncomingEntry(['message' => gzcompress('message')]))->batchId($batchId)->type(EntryType::LOG), + (new IncomingExceptionEntry($exception, [ + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'message' => gzcompress($exception->getMessage()), + ]))->batchId($batchId)->type(EntryType::EXCEPTION), + ]); + + $repository = new DatabaseEntriesRepository('testbench'); + + $repository->store($entries); + + $entries->each(function ($entry) { + $this->assertDatabaseMissing('telescope_entries', [ + 'uuid' => $entry->uuid, + 'content' => false, + ]); + }); + } } diff --git a/tests/Telescope/ExtractTagTest.php b/tests/Telescope/ExtractTagTest.php index 9b5ab6f41..ad39f4a3f 100644 --- a/tests/Telescope/ExtractTagTest.php +++ b/tests/Telescope/ExtractTagTest.php @@ -10,9 +10,6 @@ class ExtractTagTest extends FeatureTestCase { - /** - * @test - */ public function test_extract_tag_from_array_containing_flat_collection() { $flat_collection = EntryModelFactory::new()->create(); @@ -23,9 +20,6 @@ public function test_extract_tag_from_array_containing_flat_collection() $this->assertSame($tag, $extracted_tag[0]); } - /** - * @test - */ public function test_extract_tag_from_array_containing_deep_collection() { $deep_collection = EntryModelFactory::times(1)->create()->groupBy('type'); @@ -36,9 +30,6 @@ public function test_extract_tag_from_array_containing_deep_collection() $this->assertSame($tag, $extracted_tag[0]); } - /** - * @test - */ public function test_extract_tag_from_mailable() { $deep_collection = EntryModelFactory::times(1)->create()->groupBy('type'); diff --git a/tests/Telescope/TelescopeTest.php b/tests/Telescope/TelescopeTest.php index 10b2d601e..b08abe244 100644 --- a/tests/Telescope/TelescopeTest.php +++ b/tests/Telescope/TelescopeTest.php @@ -9,23 +9,20 @@ use Laravel\Telescope\Telescope; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\QueryWatcher; - +use Orchestra\Testbench\Attributes\WithConfig; + +#[WithConfig('telescope.watchers', [ + QueryWatcher::class => [ + 'enabled' => true, + 'slow' => 0.9, + ], +])] class TelescopeTest extends FeatureTestCase { private $count = 0; - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - QueryWatcher::class => [ - 'enabled' => true, - 'slow' => 0.9, - ], - ]); - } - + /** {@inheritdoc} */ + #[\Override] protected function tearDown(): void { Telescope::$afterRecordingHook = null; @@ -33,10 +30,7 @@ protected function tearDown(): void parent::tearDown(); } - /** - * @test - */ - public function run_after_recording_callback() + public function test_run_after_recording_callback() { Telescope::afterRecording(function (Telescope $telescope, IncomingEntry $entry) { $this->count++; @@ -49,10 +43,7 @@ public function run_after_recording_callback() $this->assertSame(2, $this->count); } - /** - * @test - */ - public function after_recording_callback_can_store_and_flush() + public function test_after_recording_callback_can_store_and_flush() { Telescope::afterRecording(function (Telescope $telescope, IncomingEntry $entry) { if (count($telescope::$entriesQueue) > 1) { @@ -74,10 +65,7 @@ public function after_recording_callback_can_store_and_flush() $this->assertCount(1, Telescope::$entriesQueue); } - /** - * @test - */ - public function run_after_store_callback() + public function test_run_after_store_callback() { $storedEntries = null; $storedBatchId = null; diff --git a/tests/Watchers/BatchWatcherTest.php b/tests/Watchers/BatchWatcherTest.php index 3eaf13ff0..0fc16c9d3 100644 --- a/tests/Watchers/BatchWatcherTest.php +++ b/tests/Watchers/BatchWatcherTest.php @@ -12,30 +12,16 @@ use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\BatchWatcher; use Laravel\Telescope\Watchers\JobWatcher; - +use Orchestra\Testbench\Attributes\WithConfig; + +#[WithConfig('logging.default', 'syslog')] +#[WithConfig('queue.failed.database', 'testbench')] +#[WithConfig('telescope.watchers', [ + JobWatcher::class => true, + BatchWatcher::class => true, +])] class BatchWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - JobWatcher::class => true, - BatchWatcher::class => true, - ]); - - $app->get('config')->set('queue.failed.database', 'testbench'); - - $app->get('config')->set('logging.default', 'syslog'); - } - - protected function setUp(): void - { - parent::setUp(); - - $this->createJobsTable(); - } - public function test_job_dispatch_registers_entries() { $batch = $this->app->get(QueueingDispatcher::class)->batch([ @@ -76,7 +62,8 @@ public function test_job_dispatch_registers_entries() $this->assertSame('on-demand', $entries[2]->content['queue']); } - private function createJobsTable(): void + /** {@inheritdoc} */ + protected function afterRefreshingDatabase() { if (! Schema::hasTable('jobs')) { Schema::create('jobs', function (Blueprint $table) { diff --git a/tests/Watchers/CacheWatcherTest.php b/tests/Watchers/CacheWatcherTest.php index 01c094006..552b40b38 100644 --- a/tests/Watchers/CacheWatcherTest.php +++ b/tests/Watchers/CacheWatcherTest.php @@ -7,27 +7,22 @@ use Laravel\Telescope\Telescope; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\CacheWatcher; - +use Orchestra\Testbench\Attributes\WithConfig; + +#[WithConfig('telescope.watchers', [ + CacheWatcher::class => [ + 'enabled' => true, + 'hidden' => [ + 'my-hidden-value-key', + ], + 'ignore' => [ + 'laravel:pulse:*', + 'ignored-key', + ], + ], +])] class CacheWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - CacheWatcher::class => [ - 'enabled' => true, - 'hidden' => [ - 'my-hidden-value-key', - ], - 'ignore' => [ - 'laravel:pulse:*', - 'ignored-key', - ], - ], - ]); - } - public function test_cache_watcher_registers_missed_entries() { $this->app->get(Repository::class)->get('empty-key'); diff --git a/tests/Watchers/ClientRequestWatcherTest.php b/tests/Watchers/ClientRequestWatcherTest.php index aba55a55d..d9df01d09 100644 --- a/tests/Watchers/ClientRequestWatcherTest.php +++ b/tests/Watchers/ClientRequestWatcherTest.php @@ -8,20 +8,20 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\ClientRequestWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('telescope.watchers', [ + ClientRequestWatcher::class => true, +])] class ClientRequestWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) + /** {@inheritdoc} */ + #[\Override] + protected function defineEnvironment($app) { - parent::getEnvironmentSetUp($app); + $this->markTestSkippedUnless(class_exists(\GuzzleHttp\Client::class), 'The "guzzlehttp/guzzle" composer package is required for this test.'); - if (! class_exists(\GuzzleHttp\Client::class)) { - $this->markTestSkipped('The "guzzlehttp/guzzle" composer package is required for this test.'); - } - - $app->get('config')->set('telescope.watchers', [ - ClientRequestWatcher::class => true, - ]); + parent::defineEnvironment($app); } public function test_client_request_watcher_registers_succesful_client_request_and_response() diff --git a/tests/Watchers/CommandWatcherTest.php b/tests/Watchers/CommandWatcherTest.php index 2c0194c7a..71fbb22a8 100644 --- a/tests/Watchers/CommandWatcherTest.php +++ b/tests/Watchers/CommandWatcherTest.php @@ -7,18 +7,13 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\CommandWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('telescope.watchers', [ + CommandWatcher::class => true, +])] class CommandWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - CommandWatcher::class => true, - ]); - } - public function test_command_watcher_register_entry() { $this->app->get(Kernel::class)->registerCommand(new MyCommand); diff --git a/tests/Watchers/DumpWatcherTest.php b/tests/Watchers/DumpWatcherTest.php index f6d8904f1..31c4eb726 100644 --- a/tests/Watchers/DumpWatcherTest.php +++ b/tests/Watchers/DumpWatcherTest.php @@ -6,18 +6,20 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\DumpWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('telescope.watchers', [ + DumpWatcher::class => true, +])] class DumpWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) + /** {@inheritdoc} */ + #[\Override] + protected function defineEnvironment($app) { - parent::getEnvironmentSetUp($app); + parent::defineEnvironment($app); $app->make(Repository::class)->forever('telescope:dump-watcher', true); - - $app->get('config')->set('telescope.watchers', [ - DumpWatcher::class => true, - ]); } public function test_dump_watcher_register_entry() diff --git a/tests/Watchers/EventWatcherTest.php b/tests/Watchers/EventWatcherTest.php index b7cbd8b3b..78f5eecec 100644 --- a/tests/Watchers/EventWatcherTest.php +++ b/tests/Watchers/EventWatcherTest.php @@ -13,23 +13,19 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\EventWatcher; - +use Orchestra\Testbench\Attributes\WithConfig; +use PHPUnit\Framework\Attributes\DataProvider; + +#[WithConfig('telescope.watchers', [ + EventWatcher::class => [ + 'enabled' => true, + 'ignore' => [ + IgnoredEvent::class, + ], + ], +])] class EventWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - EventWatcher::class => [ - 'enabled' => true, - 'ignore' => [ - IgnoredEvent::class, - ], - ], - ]); - } - public function test_event_watcher_registers_any_events() { Event::listen(DummyEvent::class, function ($payload) { @@ -125,6 +121,7 @@ public function test_event_watcher_ignore_event() /** * @dataProvider formatListenersProvider */ + #[DataProvider('formatListenersProvider')] public function test_format_listeners($listener, $formatted) { Event::listen(DummyEvent::class, $listener); diff --git a/tests/Watchers/ExceptionWatcherTest.php b/tests/Watchers/ExceptionWatcherTest.php index e66d5eda5..49bff9742 100644 --- a/tests/Watchers/ExceptionWatcherTest.php +++ b/tests/Watchers/ExceptionWatcherTest.php @@ -9,21 +9,15 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\ExceptionWatcher; +use Orchestra\Testbench\Attributes\WithConfig; use ParseError; +#[WithConfig('logging.default', 'syslog')] +#[WithConfig('telescope.watchers', [ + ExceptionWatcher::class => true, +])] class ExceptionWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('logging.default', 'syslog'); - - $app->get('config')->set('telescope.watchers', [ - ExceptionWatcher::class => true, - ]); - } - public function test_exception_watcher_register_entries() { $handler = $this->app->get(ExceptionHandler::class); @@ -37,7 +31,7 @@ public function test_exception_watcher_register_entries() $this->assertSame(EntryType::EXCEPTION, $entry->type); $this->assertSame(BananaException::class, $entry->content['class']); $this->assertSame(__FILE__, $entry->content['file']); - $this->assertSame(31, $entry->content['line']); + $this->assertSame(25, $entry->content['line']); $this->assertSame('Something went bananas.', $entry->content['message']); $this->assertArrayHasKey('trace', $entry->content); } @@ -55,7 +49,7 @@ public function test_exception_watcher_register_throwable_entries() $this->assertSame(EntryType::EXCEPTION, $entry->type); $this->assertSame(BananaError::class, $entry->content['class']); $this->assertSame(__FILE__, $entry->content['file']); - $this->assertSame(49, $entry->content['line']); + $this->assertSame(43, $entry->content['line']); $this->assertSame('Something went bananas.', $entry->content['message']); $this->assertArrayHasKey('trace', $entry->content); } diff --git a/tests/Watchers/GateWatcherTest.php b/tests/Watchers/GateWatcherTest.php index 3fcfa1f1c..e315394ae 100644 --- a/tests/Watchers/GateWatcherTest.php +++ b/tests/Watchers/GateWatcherTest.php @@ -9,16 +9,16 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\GateWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('telescope.watchers', [ + GateWatcher::class => true, +])] class GateWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) + protected function defineEnvironment($app) { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - GateWatcher::class => true, - ]); + parent::defineEnvironment($app); Gate::define('potato', function (User $user) { return $user->email === 'allow'; diff --git a/tests/Watchers/JobWatcherTest.php b/tests/Watchers/JobWatcherTest.php index 55f6de440..46fb28a9f 100644 --- a/tests/Watchers/JobWatcherTest.php +++ b/tests/Watchers/JobWatcherTest.php @@ -14,26 +14,19 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\JobWatcher; +use Orchestra\Testbench\Attributes\WithConfig; use Orchestra\Testbench\Attributes\WithMigration; use Orchestra\Testbench\Factories\UserFactory; use Throwable; #[WithMigration('queue')] +#[WithConfig('queue.failed.database', 'testbench')] +#[WithConfig('logging.default', 'syslog')] +#[WithConfig('telescope.watchers', [ + JobWatcher::class => true, +])] class JobWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - JobWatcher::class => true, - ]); - - $app->get('config')->set('queue.failed.database', 'testbench'); - - $app->get('config')->set('logging.default', 'syslog'); - } - public function test_job_registers_entry() { $this->app->get(Dispatcher::class)->dispatch(new MyDatabaseJob('Awesome Laravel')); diff --git a/tests/Watchers/LogWatcherTest.php b/tests/Watchers/LogWatcherTest.php index 1dcdb82dc..df0943944 100644 --- a/tests/Watchers/LogWatcherTest.php +++ b/tests/Watchers/LogWatcherTest.php @@ -5,44 +5,15 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\LogWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +use PHPUnit\Framework\Attributes\DataProvider; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use stdClass; +#[WithConfig('logging.default', 'syslog')] class LogWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('logging.default', 'syslog'); - - $config = match (method_exists($this, 'name') ? $this->name() : $this->getName(false)) { - 'test_log_watcher_registers_entry_for_any_level_by_default' => true, - 'test_log_watcher_only_registers_entries_for_the_specified_error_level_priority' => [ - 'enabled' => true, - 'level' => 'error', - ], - 'test_log_watcher_only_registers_entries_for_the_specified_debug_level_priority' => [ - 'level' => 'debug', - ], - 'test_log_watcher_do_not_registers_entry_when_disabled_on_the_boolean_format' => false, - 'test_log_watcher_do_not_registers_entry_when_disabled_on_the_array_format' => [ - 'enabled' => false, - 'level' => 'error', - ], - 'test_log_watcher_registers_entry_with_exception_key' => true, - 'test_log_watcher_interpolates_message' => [ - 'enabled' => true, - 'level' => 'info', - ], - }; - - $app->get('config')->set('telescope.watchers', [ - LogWatcher::class => $config, - ]); - } - public static function logLevelProvider() { return [ @@ -60,6 +31,10 @@ public static function logLevelProvider() /** * @dataProvider logLevelProvider */ + #[DataProvider('logLevelProvider')] + #[WithConfig('telescope.watchers', [ + LogWatcher::class => true, + ])] public function test_log_watcher_registers_entry_for_any_level_by_default($level) { $logger = $this->app->get(LoggerInterface::class); @@ -81,6 +56,13 @@ public function test_log_watcher_registers_entry_for_any_level_by_default($level /** * @dataProvider logLevelProvider */ + #[DataProvider('logLevelProvider')] + #[WithConfig(['telescope.watchers', [ + LogWatcher::class => [ + 'enabled' => true, + 'level' => 'error', + ], + ]])] public function test_log_watcher_only_registers_entries_for_the_specified_error_level_priority($level) { $logger = $this->app->get(LoggerInterface::class); @@ -106,6 +88,12 @@ public function test_log_watcher_only_registers_entries_for_the_specified_error_ /** * @dataProvider logLevelProvider */ + #[DataProvider('logLevelProvider')] + #[WithConfig('telescope.watchers', [ + LogWatcher::class => [ + 'level' => 'debug', + ], + ])] public function test_log_watcher_only_registers_entries_for_the_specified_debug_level_priority($level) { $logger = $this->app->get(LoggerInterface::class); @@ -127,6 +115,10 @@ public function test_log_watcher_only_registers_entries_for_the_specified_debug_ /** * @dataProvider logLevelProvider */ + #[DataProvider('logLevelProvider')] + #[WithConfig('telescope.watchers', [ + LogWatcher::class => false, + ])] public function test_log_watcher_do_not_registers_entry_when_disabled_on_the_boolean_format($level) { $logger = $this->app->get(LoggerInterface::class); @@ -144,6 +136,13 @@ public function test_log_watcher_do_not_registers_entry_when_disabled_on_the_boo /** * @dataProvider logLevelProvider */ + #[DataProvider('logLevelProvider')] + #[WithConfig('telescope.watchers', [ + LogWatcher::class => [ + 'enabled' => false, + 'level' => 'error', + ], + ])] public function test_log_watcher_do_not_registers_entry_when_disabled_on_the_array_format($level) { $logger = $this->app->get(LoggerInterface::class); @@ -158,6 +157,7 @@ public function test_log_watcher_do_not_registers_entry_when_disabled_on_the_arr $this->assertNull($entry); } + #[WithConfig('telescope.watchers', [LogWatcher::class => true])] public function test_log_watcher_registers_entry_with_exception_key() { $logger = $this->app->get(LoggerInterface::class); @@ -226,6 +226,13 @@ public function __toString() /** * @dataProvider interpolationProvider */ + #[DataProvider('interpolationProvider')] + #[WithConfig('telescope.watchers', [ + LogWatcher::class => [ + 'enabled' => true, + 'level' => 'info', + ], + ])] public function test_log_watcher_interpolates_message($message, $context, $expectedMessage) { $logger = $this->app->get(LoggerInterface::class); diff --git a/tests/Watchers/MailNotificationTest.php b/tests/Watchers/MailNotificationTest.php index eaac84cf5..861cc863c 100644 --- a/tests/Watchers/MailNotificationTest.php +++ b/tests/Watchers/MailNotificationTest.php @@ -10,21 +10,15 @@ use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\MailWatcher; use Laravel\Telescope\Watchers\NotificationWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('mail.driver', 'array')] +#[WithConfig('telescope.watchers', [ + MailWatcher::class => true, + NotificationWatcher::class => true, +])] class MailNotificationTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - MailWatcher::class => true, - NotificationWatcher::class => true, - ]); - - $app->get('config')->set('mail.driver', 'array'); - } - public function test_mail_watcher_registers_valid_html() { Notification::route('mail', 'to@laravel.com') diff --git a/tests/Watchers/MailWatcherTest.php b/tests/Watchers/MailWatcherTest.php index 660970ab7..32be823d0 100644 --- a/tests/Watchers/MailWatcherTest.php +++ b/tests/Watchers/MailWatcherTest.php @@ -7,20 +7,14 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\MailWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('mail.driver', 'array')] +#[WithConfig('telescope.watchers', [ + MailWatcher::class => true, +])] class MailWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - MailWatcher::class => true, - ]); - - $app->get('config')->set('mail.driver', 'array'); - } - public function test_mail_watcher_registers_entry() { Mail::raw('Telescope is amazing!', function ($message) { diff --git a/tests/Watchers/ModelWatcherTest.php b/tests/Watchers/ModelWatcherTest.php index ca06868c2..aab3c3225 100644 --- a/tests/Watchers/ModelWatcherTest.php +++ b/tests/Watchers/ModelWatcherTest.php @@ -8,22 +8,17 @@ use Laravel\Telescope\Telescope; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\ModelWatcher; - +use Orchestra\Testbench\Attributes\WithConfig; + +#[WithConfig('telescope.watchers', [ + ModelWatcher::class => [ + 'enabled' => true, + 'events' => ['eloquent.created*', 'eloquent.updated*', 'eloquent.retrieved*'], + 'hydrations' => true, + ], +])] class ModelWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - ModelWatcher::class => [ - 'enabled' => true, - 'events' => ['eloquent.created*', 'eloquent.updated*', 'eloquent.retrieved*'], - 'hydrations' => true, - ], - ]); - } - public function test_model_watcher_registers_entry() { Telescope::withoutRecording(function () { diff --git a/tests/Watchers/NotificationWatcherTest.php b/tests/Watchers/NotificationWatcherTest.php index a1ee064d2..54b57e604 100644 --- a/tests/Watchers/NotificationWatcherTest.php +++ b/tests/Watchers/NotificationWatcherTest.php @@ -8,20 +8,14 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\NotificationWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('mail.driver', 'array')] +#[WithConfig('telescope.watchers', [ + NotificationWatcher::class => true, +])] class NotificationWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - NotificationWatcher::class => true, - ]); - - $app->get('config')->set('mail.driver', 'array'); - } - public function test_notification_watcher_registers_entry() { $this->performNotificationAssertions('mail', 'telescope@laravel.com'); diff --git a/tests/Watchers/QueryWatcherTest.php b/tests/Watchers/QueryWatcherTest.php index e8a422163..f48f3de95 100644 --- a/tests/Watchers/QueryWatcherTest.php +++ b/tests/Watchers/QueryWatcherTest.php @@ -10,21 +10,16 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\QueryWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('telescope.watchers', [ + QueryWatcher::class => [ + 'enabled' => true, + 'slow' => 0.2, + ], +])] class QueryWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) - { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - QueryWatcher::class => [ - 'enabled' => true, - 'slow' => 0.2, - ], - ]); - } - public function test_query_watcher_registers_database_queries() { $this->app->get('db')->table('telescope_entries')->count(); diff --git a/tests/Watchers/RedisWatcherTest.php b/tests/Watchers/RedisWatcherTest.php index c55c4f80d..5dd1c8a45 100644 --- a/tests/Watchers/RedisWatcherTest.php +++ b/tests/Watchers/RedisWatcherTest.php @@ -8,24 +8,25 @@ use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\RedisWatcher; use Mockery; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('database.redis.client', 'phpredis')] +#[WithConfig('telescope.watchers', [ + RedisWatcher::class => true, +])] class RedisWatcherTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) + /** {@inheritdoc} */ + #[\Override] + protected function defineEnvironment($app) { - parent::getEnvironmentSetUp($app); + $this->markTestSkippedUnless(extension_loaded('redis'), 'The phpredis extension is required for this test.'); - if (! extension_loaded('redis')) { - $this->markTestSkipped('The phpredis extension is required for this test.'); - } + parent::defineEnvironment($app); $app->get('config')->set('database.redis.client', 'phpredis'); $app['redis']->enableEvents(); - - $app->get('config')->set('telescope.watchers', [ - RedisWatcher::class => true, - ]); } public function test_redis_watcher_registers_entries() diff --git a/tests/Watchers/RequestWatchersTest.php b/tests/Watchers/RequestWatchersTest.php index 4c9c49b7e..67939d3cf 100644 --- a/tests/Watchers/RequestWatchersTest.php +++ b/tests/Watchers/RequestWatchersTest.php @@ -9,16 +9,18 @@ use Laravel\Telescope\EntryType; use Laravel\Telescope\Tests\FeatureTestCase; use Laravel\Telescope\Watchers\RequestWatcher; +use Orchestra\Testbench\Attributes\WithConfig; +#[WithConfig('telescope.watchers', [ + RequestWatcher::class => true, +])] class RequestWatchersTest extends FeatureTestCase { - protected function getEnvironmentSetUp($app) + /** {@inheritdoc} */ + #[\Override] + protected function defineEnvironment($app) { - parent::getEnvironmentSetUp($app); - - $app->get('config')->set('telescope.watchers', [ - RequestWatcher::class => true, - ]); + parent::defineEnvironment($app); if (! defined('LARAVEL_START')) { define('LARAVEL_START', microtime(true)); diff --git a/tests/Watchers/ViewWatcherTest.php b/tests/Watchers/ViewWatcherTest.php index ebdbfdd04..019534c92 100644 --- a/tests/Watchers/ViewWatcherTest.php +++ b/tests/Watchers/ViewWatcherTest.php @@ -11,9 +11,11 @@ class ViewWatcherTest extends FeatureTestCase { protected $viewsDirectory = __DIR__.'/../stubs/views'; - protected function getEnvironmentSetUp($app) + /** {@inheritdoc} */ + #[\Override] + protected function defineEnvironment($app) { - parent::getEnvironmentSetUp($app); + parent::defineEnvironment($app); Event::subscribe(GenericListener::class);