Repository: laravel/framework (php)

Issue:
shouldSend does not get called or change outcome of "assertNotSent" or other notification assertions
<!-- DO NOT THROW THIS AWAY -->
<!-- Fill out the FULL versions with patch versions -->

- Laravel Version: 8.61.0
- PHP Version: 8.0.3
- Database Driver & Version: mysql 5.7

### Description:
It looks like the PR:

https://github.com/laravel/framework/pull/37930#issue-684438049

that gave us `shouldSend()` on `Notification` does not give us that behavior when checking assertions like `assertNotSent`. 

### Steps To Reproduce:
- Create a new notification
- Set `shouldSend` to return false
- Create a test where that notification should send without `shouldSend` and try to assertNotSent based on `shouldSend`.
- Test fails because notification is sent regardless of shouldSend


Pull request:
[8.x] Notification assertions respect `shouldSend` method on notification
Support for notification's `shouldSend` method were added in PR #37930. This method allows users to add some logic to cancel sending notification based on given notifiable and channel.


#### Problem

However, testing methods `assertSentTo` and `assertNotSentTo` weren't aware about this feature and didn't behave as expected (reported here as well https://github.com/laravel/framework/issues/38909). 

For example, take this code:
```php
// somewhere in user's code
Notification::send($user, new SomeNotification);

// implementation
class SomeNotification extends Notification
{
    public function via($notifiable)
    {
        return ['mail'];
    }

    public function shouldSend($notifiable, $channel)
    {
        return false;
    }
}
```

Now, when testing whether notification hasn't been sent, we won't get expected assertion result:

```php
Notification::fake();

// some code triggering notification send

Notification::assertNotSentTo($user, SomeNotification::class); // will fail, but should pass
```

#### Solution

This PR adds support of `shouldSend` to notification's `assertSentTo` and `assertNotSentTo` methods. So now when `shouldSend` is presented on notification class and returns false for some notifiable,  `assertSentTo` and `assertNotSentTo` can be used to check that behavior.

Fixes #38909

Patch:
diff --git a/src/Illuminate/Database/Console/PruneCommand.php b/src/Illuminate/Database/Console/PruneCommand.php
index 9aa9f62923..d84b0a0151 100644
--- a/src/Illuminate/Database/Console/PruneCommand.php
+++ b/src/Illuminate/Database/Console/PruneCommand.php
@@ -87,7 +87,7 @@ protected function models()
             return collect($models);
         }
 
-        return collect((new Finder)->in(app_path('Models'))->files())
+        return collect((new Finder)->in(app_path('Models'))->files()->name('*.php'))
             ->map(function ($model) {
                 $namespace = $this->laravel->getNamespace();
 
diff --git a/src/Illuminate/Foundation/Console/stubs/pest.stub b/src/Illuminate/Foundation/Console/stubs/pest.stub
new file mode 100644
index 0000000000..b46239fd0e
--- /dev/null
+++ b/src/Illuminate/Foundation/Console/stubs/pest.stub
@@ -0,0 +1,7 @@
+<?php
+
+test('example', function () {
+    $response = $this->get('/');
+
+    $response->assertStatus(200);
+});
diff --git a/src/Illuminate/Foundation/Console/stubs/pest.unit.stub b/src/Illuminate/Foundation/Console/stubs/pest.unit.stub
new file mode 100644
index 0000000000..61cd84c327
--- /dev/null
+++ b/src/Illuminate/Foundation/Console/stubs/pest.unit.stub
@@ -0,0 +1,5 @@
+<?php
+
+test('example', function () {
+    expect(true)->toBeTrue();
+});


Test patch:
diff --git a/src/Illuminate/Foundation/Console/TestMakeCommand.php b/src/Illuminate/Foundation/Console/TestMakeCommand.php
index 10814a0b09..eced47b918 100644
--- a/src/Illuminate/Foundation/Console/TestMakeCommand.php
+++ b/src/Illuminate/Foundation/Console/TestMakeCommand.php
@@ -36,9 +36,11 @@ class TestMakeCommand extends GeneratorCommand
      */
     protected function getStub()
     {
-        return $this->option('unit')
-                    ? $this->resolveStubPath('/stubs/test.unit.stub')
-                    : $this->resolveStubPath('/stubs/test.stub');
+        $suffix = $this->option('unit') ? '.unit.stub' : '.stub';
+
+        return $this->option('pest')
+            ? $this->resolveStubPath('/stubs/pest'.$suffix)
+            : $this->resolveStubPath('/stubs/test'.$suffix);
     }
 
     /**
@@ -101,6 +103,7 @@ protected function getOptions()
     {
         return [
             ['unit', 'u', InputOption::VALUE_NONE, 'Create a unit test.'],
+            ['pest', 'p', InputOption::VALUE_NONE, 'Create a Pest test.'],
         ];
     }
 }
diff --git a/src/Illuminate/Support/Testing/Fakes/NotificationFake.php b/src/Illuminate/Support/Testing/Fakes/NotificationFake.php
index 28526d5925..e136a5438a 100644
--- a/src/Illuminate/Support/Testing/Fakes/NotificationFake.php
+++ b/src/Illuminate/Support/Testing/Fakes/NotificationFake.php
@@ -232,9 +232,24 @@ public function sendNow($notifiables, $notification, array $channels = null)
                 $notification->id = Str::uuid()->toString();
             }
 
+            $notifiableChannels = $channels ?: $notification->via($notifiable);
+
+            if (method_exists($notification, 'shouldSend')) {
+                $notifiableChannels = array_filter(
+                    $notifiableChannels,
+                    function ($channel) use ($notification, $notifiable) {
+                        return $notification->shouldSend($notifiable, $channel) !== false;
+                    }
+                );
+
+                if (empty($notifiableChannels)) {
+                    continue;
+                }
+            }
+
             $this->notifications[get_class($notifiable)][$notifiable->getKey()][get_class($notification)][] = [
                 'notification' => $notification,
-                'channels' => $channels ?: $notification->via($notifiable),
+                'channels' => $notifiableChannels,
                 'notifiable' => $notifiable,
                 'locale' => $notification->locale ?? $this->locale ?? value(function () use ($notifiable) {
                     if ($notifiable instanceof HasLocalePreference) {
diff --git a/tests/Support/SupportTestingNotificationFakeTest.php b/tests/Support/SupportTestingNotificationFakeTest.php
index 0774d442f4..8c0038d3d6 100644
--- a/tests/Support/SupportTestingNotificationFakeTest.php
+++ b/tests/Support/SupportTestingNotificationFakeTest.php
@@ -144,6 +144,15 @@ public function testAssertSentToWhenNotifiableHasPreferredLocale()
             return $notifiable === $user && $locale === 'au';
         });
     }
+
+    public function testAssertSentToWhenNotifiableHasFalsyShouldSend()
+    {
+        $user = new LocalizedUserStub;
+
+        $this->fake->send($user, new NotificationWithFalsyShouldSendStub);
+
+        $this->fake->assertNotSentTo($user, NotificationWithFalsyShouldSendStub::class);
+    }
 }
 
 class NotificationStub extends Notification
@@ -154,6 +163,19 @@ public function via($notifiable)
     }
 }
 
+class NotificationWithFalsyShouldSendStub extends Notification
+{
+    public function via($notifiable)
+    {
+        return ['mail'];
+    }
+
+    public function shouldSend($notifiable, $channel)
+    {
+        return false;
+    }
+}
+
 class UserStub extends User
 {
     //