From f6188f31de1ddb3d8990f01760332a3bce5f5bdf Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 14 Feb 2023 15:22:27 +0100 Subject: [PATCH 1/7] Move to PHPUnit v10 --- composer.json | 2 +- src/Constraints/PageConstraint.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index cfa60c4..a46762a 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "illuminate/support": "^10.0", "illuminate/testing": "^10.0", "mockery/mockery": "^1.0", - "phpunit/phpunit": "^9.0", + "phpunit/phpunit": "^10.0", "symfony/console": "^6.2", "symfony/css-selector": "^6.2", "symfony/dom-crawler": "^6.2", diff --git a/src/Constraints/PageConstraint.php b/src/Constraints/PageConstraint.php index 05929b3..121724b 100644 --- a/src/Constraints/PageConstraint.php +++ b/src/Constraints/PageConstraint.php @@ -61,16 +61,16 @@ protected function getEscapedPattern($text) /** * Throw an exception for the given comparison and test description. * - * @param \Symfony\Component\DomCrawler\Crawler|string $crawler + * @param mixed $other * @param string $description * @param \SebastianBergmann\Comparator\ComparisonFailure|null $comparisonFailure * @return void * * @throws \PHPUnit\Framework\ExpectationFailedException */ - protected function fail($crawler, $description, ComparisonFailure $comparisonFailure = null): void + protected function fail(mixed $other, string $description, ?ComparisonFailure $comparisonFailure = null): never { - $html = $this->html($crawler); + $html = $this->html($other); $failureDescription = sprintf( "%s\n\n\nFailed asserting that %s", From b0b9a4211dde728f88ecc18495869bbe396fc7f8 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 14 Feb 2023 15:25:07 +0100 Subject: [PATCH 2/7] Update composer.json Co-authored-by: Mior Muhammad Zaki --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a46762a..71e771f 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "illuminate/support": "^10.0", "illuminate/testing": "^10.0", "mockery/mockery": "^1.0", - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^10.0.7", "symfony/console": "^6.2", "symfony/css-selector": "^6.2", "symfony/dom-crawler": "^6.2", From b13bff72357cdb2241fd1395611ab969e67c3f73 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 14 Feb 2023 15:30:14 +0100 Subject: [PATCH 3/7] wip --- .github/workflows/tests.yml | 2 +- .gitignore | 1 + phpunit.xml.dist | 21 +++++++++---------- .../Unit/InteractsWithAuthenticationTest.php | 4 ++-- tests/Unit/InteractsWithPagesTest.php | 2 +- tests/Unit/MakesHttpRequestsTest.php | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 052fb2f..52ddf42 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,4 +40,4 @@ jobs: composer update --prefer-dist --no-interaction --no-progress - name: Execute tests - run: vendor/bin/phpunit --verbose + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 660fc15..35aa09e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /vendor composer.lock /phpunit.xml +/.phpunit.cache .phpunit.result.cache diff --git a/phpunit.xml.dist b/phpunit.xml.dist index cb6898f..19d4e20 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,17 +1,16 @@ - - - - ./tests - - + + + ./tests + + diff --git a/tests/Unit/InteractsWithAuthenticationTest.php b/tests/Unit/InteractsWithAuthenticationTest.php index 0dc91c7..bc385fe 100644 --- a/tests/Unit/InteractsWithAuthenticationTest.php +++ b/tests/Unit/InteractsWithAuthenticationTest.php @@ -63,7 +63,7 @@ public function hasCredentials_return_true_if_the_credentials_are_valid() /** * @test - * @dataProvider DataHasCredentials + * @dataProvider dataHasCredentials */ public function hasCredentials_return_false_if_the_credentials_arent_valid($validateCredentials, $retrieveByCredentials) { @@ -78,7 +78,7 @@ public function hasCredentials_return_false_if_the_credentials_arent_valid($vali $this->assertFalse($this->hasCredentials($credentials)); } - public function DataHasCredentials() + public static function dataHasCredentials() { return [ 'Case 01' => [false, true], diff --git a/tests/Unit/InteractsWithPagesTest.php b/tests/Unit/InteractsWithPagesTest.php index 4cf20a2..ba24fd9 100644 --- a/tests/Unit/InteractsWithPagesTest.php +++ b/tests/Unit/InteractsWithPagesTest.php @@ -462,7 +462,7 @@ public function create_UploadedFile_for_testing($file, $uploads, $name) $this->assertSame(0, $file->getSize()); } - public function attributes_UploadedFile() + public static function attributes_UploadedFile() { return [ [ diff --git a/tests/Unit/MakesHttpRequestsTest.php b/tests/Unit/MakesHttpRequestsTest.php index c4a48a3..c432341 100644 --- a/tests/Unit/MakesHttpRequestsTest.php +++ b/tests/Unit/MakesHttpRequestsTest.php @@ -27,7 +27,7 @@ public function prepareUrlForRequest_method_return_all_url($url, $expectedUrl) ); } - public function dataUrls() + public static function dataUrls() { return [ ['', 'http://localhost'], From 01779a611483b26740c93ed61fb5e5457f2b5628 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 14 Feb 2023 15:38:05 +0100 Subject: [PATCH 4/7] Remove trait --- phpunit.xml.dist | 10 +- src/Concerns/MocksApplicationServices.php | 415 ---------------------- src/TestCase.php | 3 +- 3 files changed, 6 insertions(+), 422 deletions(-) delete mode 100644 src/Concerns/MocksApplicationServices.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 19d4e20..c98a67a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,9 +8,9 @@ cacheDirectory=".phpunit.cache" backupStaticProperties="false" > - - - ./tests - - + + + ./tests + + diff --git a/src/Concerns/MocksApplicationServices.php b/src/Concerns/MocksApplicationServices.php deleted file mode 100644 index b886a5e..0000000 --- a/src/Concerns/MocksApplicationServices.php +++ /dev/null @@ -1,415 +0,0 @@ -withoutEvents(); - - $this->beforeApplicationDestroyed(function () use ($events) { - $fired = $this->getFiredEvents($events); - - $this->assertEmpty( - $eventsNotFired = array_diff($events, $fired), - 'These expected events were not fired: ['.implode(', ', $eventsNotFired).']' - ); - }); - - return $this; - } - - /** - * Specify a list of events that should not be fired for the given operation. - * - * These events will be mocked, so that handlers will not actually be executed. - * - * @param array|string $events - * @return $this - */ - public function doesntExpectEvents($events) - { - $events = is_array($events) ? $events : func_get_args(); - - $this->withoutEvents(); - - $this->beforeApplicationDestroyed(function () use ($events) { - $this->assertEmpty( - $fired = $this->getFiredEvents($events), - 'These unexpected events were fired: ['.implode(', ', $fired).']' - ); - }); - - return $this; - } - - /** - * Mock the event dispatcher so all events are silenced and collected. - * - * @return $this - */ - protected function withoutEvents() - { - $mock = Mockery::mock('Illuminate\Contracts\Events\Dispatcher'); - - $mock->shouldReceive('fire', 'dispatch', 'getCommandHandler')->andReturnUsing(function ($called) { - $this->firedEvents[] = $called; - }); - - $this->app->instance('events', $mock); - - return $this; - } - - /** - * Specify a list of events that should be fired for the given operation. - * - * These events will be mocked, so that handlers will not actually be executed. - * - * @param string $model - * @param array|string $events - * @return $this - * - * @throws \Exception - */ - public function expectsModelEvents($model, $events) - { - $events = $this->formatModelEvents($model, $events); - - $this->withoutModelEvents(); - - $this->beforeApplicationDestroyed(function () use ($events) { - $fired = $this->getFiredModelEvents($events); - - if ($eventsNotFired = array_diff($events, $fired)) { - throw new Exception( - 'These expected Eloquent events were not fired: ['.implode(', ', $eventsNotFired).']' - ); - } - }); - - return $this; - } - - /** - * Specify a list of events that should not be fired for the given operation. - * - * These events will be mocked, so that handlers will not actually be executed. - * - * @param string $model - * @param array|string $events - * @return $this - * - * @throws \Exception - */ - public function doesntExpectModelEvents($model, $events) - { - $events = $this->formatModelEvents($model, $events); - - $this->withoutModelEvents(); - - $this->beforeApplicationDestroyed(function () use ($events) { - if ($fired = $this->getFiredModelEvents($events)) { - throw new Exception( - 'These unexpected Eloquent events were fired: ['.implode(', ', $fired).']' - ); - } - }); - - return $this; - } - - /** - * Convert a model and a list of events into the Eloquent's format. - * - * @param string $model - * @param array|string $events - * @return string[] - */ - private function formatModelEvents($model, $events) - { - $events = (array) $events; - - return array_map(function ($event) use ($model) { - return "eloquent.{$event}: {$model}"; - }, (array) $events); - } - - /** - * Mock the model event dispatcher so all Eloquent events are silenced. - * - * @return $this - */ - protected function withoutModelEvents() - { - $mock = Mockery::mock('Illuminate\Contracts\Events\Dispatcher'); - - $mock->shouldReceive('dispatch')->andReturnUsing(function ($called) { - $this->firedModelEvents[] = $called; - }); - - $mock->shouldReceive('until')->andReturnUsing(function ($called) { - $this->firedModelEvents[] = $called; - - return true; - }); - - $mock->shouldReceive('listen')->andReturnUsing(function ($event, $listener) { - // - }); - - Model::setEventDispatcher($mock); - - return $this; - } - - /** - * Specify a list of observers that will not run for the given operation. - * - * @param array|string $observers - * @return $this - */ - public function withoutObservers($observers) - { - $observers = is_array($observers) ? $observers : [$observers]; - - array_map(function ($observer) { - $this->app->bind($observer, function () use ($observer) { - return $this->getMockBuilder($observer)->disableOriginalConstructor()->getMock(); - }); - }, $observers); - - return $this; - } - - /** - * Filter the given events against the fired events. - * - * @param array $events - * @return array - */ - protected function getFiredEvents(array $events) - { - return $this->getDispatched($events, $this->firedEvents); - } - - /** - * Filter the given events against the fired events. - * - * @param array $events - * @return array - */ - protected function getFiredModelEvents(array $events) - { - return $this->getDispatched($events, $this->firedModelEvents); - } - - /** - * Specify a list of jobs that should be dispatched for the given operation. - * - * These jobs will be mocked, so that handlers will not actually be executed. - * - * @param array|string $jobs - * @return $this - */ - protected function expectsJobs($jobs) - { - $jobs = is_array($jobs) ? $jobs : func_get_args(); - - $this->withoutJobs(); - - $this->beforeApplicationDestroyed(function () use ($jobs) { - $dispatched = $this->getDispatchedJobs($jobs); - - $this->assertEmpty( - $jobsNotDispatched = array_diff($jobs, $dispatched), - 'These expected jobs were not dispatched: ['.implode(', ', $jobsNotDispatched).']' - ); - }); - - return $this; - } - - /** - * Specify a list of jobs that should not be dispatched for the given operation. - * - * These jobs will be mocked, so that handlers will not actually be executed. - * - * @param array|string $jobs - * @return $this - */ - protected function doesntExpectJobs($jobs) - { - $jobs = is_array($jobs) ? $jobs : func_get_args(); - - $this->withoutJobs(); - - $this->beforeApplicationDestroyed(function () use ($jobs) { - $this->assertEmpty( - $dispatched = $this->getDispatchedJobs($jobs), - 'These unexpected jobs were dispatched: ['.implode(', ', $dispatched).']' - ); - }); - - return $this; - } - - /** - * Mock the job dispatcher so all jobs are silenced and collected. - * - * @return $this - */ - protected function withoutJobs() - { - $mock = Mockery::mock('Illuminate\Contracts\Bus\Dispatcher'); - - $mock->shouldReceive('dispatch', 'dispatchNow', 'getCommandHandler')->andReturnUsing(function ($dispatched) { - $this->dispatchedJobs[] = $dispatched; - }); - - $this->app->instance( - 'Illuminate\Contracts\Bus\Dispatcher', $mock - ); - - return $this; - } - - /** - * Filter the given jobs against the dispatched jobs. - * - * @param array $jobs - * @return array - */ - protected function getDispatchedJobs(array $jobs) - { - return $this->getDispatched($jobs, $this->dispatchedJobs); - } - - /** - * Filter the given classes against an array of dispatched classes. - * - * @param array $classes - * @param array $dispatched - * @return array - */ - protected function getDispatched(array $classes, array $dispatched) - { - return array_filter($classes, function ($class) use ($dispatched) { - return $this->wasDispatched($class, $dispatched); - }); - } - - /** - * Check if the given class exists in an array of dispatched classes. - * - * @param string $needle - * @param array $haystack - * @return bool - */ - protected function wasDispatched($needle, array $haystack) - { - foreach ($haystack as $dispatched) { - if ((is_string($dispatched) && ($dispatched === $needle || is_subclass_of($dispatched, $needle))) || - $dispatched instanceof $needle) { - return true; - } - } - - return false; - } - - /** - * Mock the notification dispatcher so all notifications are silenced. - * - * @return $this - */ - protected function withoutNotifications() - { - $mock = Mockery::mock(NotificationDispatcher::class); - - $mock->shouldReceive('send')->andReturnUsing(function ($notifiable, $instance, $channels = []) { - $this->dispatchedNotifications[] = compact( - 'notifiable', 'instance', 'channels' - ); - }); - - $this->app->instance(NotificationDispatcher::class, $mock); - - return $this; - } - - /** - * Specify a notification that is expected to be dispatched. - * - * @param mixed $notifiable - * @param string $notification - * @return $this - */ - protected function expectsNotification($notifiable, $notification) - { - $this->withoutNotifications(); - - $this->beforeApplicationDestroyed(function () use ($notifiable, $notification) { - foreach ($this->dispatchedNotifications as $dispatched) { - $notified = $dispatched['notifiable']; - - if (($notified === $notifiable || - $notified->getKey() == $notifiable->getKey()) && - get_class($dispatched['instance']) === $notification - ) { - return $this; - } - } - - $this->fail('The following expected notification was not dispatched: ['.$notification.']'); - }); - - return $this; - } -} diff --git a/src/TestCase.php b/src/TestCase.php index f0662e9..d202711 100755 --- a/src/TestCase.php +++ b/src/TestCase.php @@ -22,8 +22,7 @@ abstract class TestCase extends BaseTestCase Concerns\InteractsWithConsole, Concerns\InteractsWithDatabase, Concerns\InteractsWithExceptionHandling, - Concerns\InteractsWithSession, - Concerns\MocksApplicationServices; + Concerns\InteractsWithSession; /** * The Illuminate application instance. From 4532b59fd2bccfbf70522874b69f5d082ceac7bc Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Tue, 14 Feb 2023 15:40:41 +0100 Subject: [PATCH 5/7] wip --- UPGRADE.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index a877926..d4be694 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,22 @@ # Upgrade Guide +## Upgrading To 7.0 From 6.x + +### Minimum Versions + +The following required dependency versions have been updated: + +- The minimum PHP version is now v8.1 +- The minimum Laravel version is now v10.0 +- The minimum PHPUnit version is now v10.0 + +### Service Mocking + +The deprecated `MocksApplicationServices` trait has been removed from the library. This trait provided testing methods such as `expectsEvents` and `expectsJobs`. + +If your application uses these methods, we recommend you transition to `Event::fake` and `Bus::fake`, respectively. You can learn more about mocking via fakes in the corresponding documentation for the component you are attempting to fake. + + ## Upgrading To 6.0 From 5.x ### Minimum Laravel Version @@ -20,6 +37,7 @@ PR: https://github.com/laravel/browser-kit-testing/pull/107 When using the `followRedirects` method, previously defined cookies will now be preserved. + ## Upgrading To 5.0 From 4.x ### PHPUnit 8 From 155dc350cab206ae5eb0338b408c2f7b20451440 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 14 Feb 2023 08:49:36 -0600 Subject: [PATCH 6/7] Update UPGRADE.md --- UPGRADE.md | 1 - 1 file changed, 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index d4be694..a301445 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -16,7 +16,6 @@ The deprecated `MocksApplicationServices` trait has been removed from the librar If your application uses these methods, we recommend you transition to `Event::fake` and `Bus::fake`, respectively. You can learn more about mocking via fakes in the corresponding documentation for the component you are attempting to fake. - ## Upgrading To 6.0 From 5.x ### Minimum Laravel Version From 4fe802ce121b24cce20afb4ba0fdb8479cf3ccd8 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 14 Feb 2023 08:49:48 -0600 Subject: [PATCH 7/7] Update UPGRADE.md --- UPGRADE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UPGRADE.md b/UPGRADE.md index a301445..d4be694 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -16,6 +16,7 @@ The deprecated `MocksApplicationServices` trait has been removed from the librar If your application uses these methods, we recommend you transition to `Event::fake` and `Bus::fake`, respectively. You can learn more about mocking via fakes in the corresponding documentation for the component you are attempting to fake. + ## Upgrading To 6.0 From 5.x ### Minimum Laravel Version