diff --git a/app/Jobs/SendNewPluginNotifications.php b/app/Jobs/SendNewPluginNotifications.php new file mode 100644 index 00000000..a0877a18 --- /dev/null +++ b/app/Jobs/SendNewPluginNotifications.php @@ -0,0 +1,27 @@ +where('receives_new_plugin_notifications', true) + ->where('id', '!=', $this->plugin->user_id) + ->get(); + + Notification::send($recipients, new NewPluginAvailable($this->plugin)); + } +} diff --git a/app/Models/Plugin.php b/app/Models/Plugin.php index 7311195d..e16510f2 100644 --- a/app/Models/Plugin.php +++ b/app/Models/Plugin.php @@ -7,7 +7,7 @@ use App\Enums\PluginTier; use App\Enums\PluginType; use App\Enums\PriceTier; -use App\Notifications\NewPluginAvailable; +use App\Jobs\SendNewPluginNotifications; use App\Notifications\PluginApproved; use App\Notifications\PluginRejected; use App\Services\PluginSyncService; @@ -21,7 +21,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; -use Illuminate\Support\Facades\Notification; class Plugin extends Model { @@ -568,12 +567,7 @@ public function approve(int $approvedById): void $this->user->notify(new PluginApproved($this)); if ($isFirstApproval) { - $recipients = User::query() - ->where('receives_new_plugin_notifications', true) - ->where('id', '!=', $this->user_id) - ->get(); - - Notification::send($recipients, new NewPluginAvailable($this)); + SendNewPluginNotifications::dispatch($this); } resolve(PluginSyncService::class)->sync($this); diff --git a/tests/Feature/Jobs/SendNewPluginNotificationsTest.php b/tests/Feature/Jobs/SendNewPluginNotificationsTest.php new file mode 100644 index 00000000..5f656b38 --- /dev/null +++ b/tests/Feature/Jobs/SendNewPluginNotificationsTest.php @@ -0,0 +1,44 @@ +create(); + $optedIn = User::factory()->create(['receives_new_plugin_notifications' => true]); + $optedOut = User::factory()->create(['receives_new_plugin_notifications' => false]); + + $plugin = Plugin::factory()->approved()->for($author)->create(); + + (new SendNewPluginNotifications($plugin))->handle(); + + Notification::assertSentTo($optedIn, NewPluginAvailable::class); + Notification::assertNotSentTo($optedOut, NewPluginAvailable::class); + } + + public function test_job_does_not_notify_plugin_author(): void + { + Notification::fake(); + + $author = User::factory()->create(['receives_new_plugin_notifications' => true]); + $plugin = Plugin::factory()->approved()->for($author)->create(); + + (new SendNewPluginNotifications($plugin))->handle(); + + Notification::assertNotSentTo($author, NewPluginAvailable::class); + } +} diff --git a/tests/Feature/Notifications/NewPluginAvailableTest.php b/tests/Feature/Notifications/NewPluginAvailableTest.php index 7581a0f2..1ff1389c 100644 --- a/tests/Feature/Notifications/NewPluginAvailableTest.php +++ b/tests/Feature/Notifications/NewPluginAvailableTest.php @@ -2,12 +2,13 @@ namespace Tests\Feature\Notifications; +use App\Jobs\SendNewPluginNotifications; use App\Models\Plugin; use App\Models\User; use App\Notifications\NewPluginAvailable; use App\Services\PluginSyncService; use Illuminate\Foundation\Testing\RefreshDatabase; -use Illuminate\Support\Facades\Notification; +use Illuminate\Support\Facades\Bus; use Tests\TestCase; class NewPluginAvailableTest extends TestCase @@ -23,31 +24,26 @@ protected function setUp(): void }); } - public function test_notification_is_sent_to_opted_in_users_on_first_approval(): void + public function test_notification_job_is_dispatched_on_first_approval(): void { - Notification::fake(); + Bus::fake(SendNewPluginNotifications::class); $author = User::factory()->create(); - $optedIn = User::factory()->create(['receives_new_plugin_notifications' => true]); - $optedOut = User::factory()->create(['receives_new_plugin_notifications' => false]); - $plugin = Plugin::factory()->pending()->for($author)->create(); $admin = User::factory()->create(); $plugin->approve($admin->id); - Notification::assertSentTo($optedIn, NewPluginAvailable::class); - Notification::assertNotSentTo($optedOut, NewPluginAvailable::class); - Notification::assertNotSentTo($author, NewPluginAvailable::class); + Bus::assertDispatched(SendNewPluginNotifications::class, function ($job) use ($plugin) { + return $job->plugin->id === $plugin->id; + }); } - public function test_notification_is_not_sent_on_re_approval(): void + public function test_notification_job_is_not_dispatched_on_re_approval(): void { - Notification::fake(); + Bus::fake(SendNewPluginNotifications::class); $author = User::factory()->create(); - $optedIn = User::factory()->create(['receives_new_plugin_notifications' => true]); - $plugin = Plugin::factory()->pending()->for($author)->create([ 'approved_at' => now()->subDay(), ]); @@ -55,7 +51,7 @@ public function test_notification_is_not_sent_on_re_approval(): void $plugin->approve($admin->id); - Notification::assertNotSentTo($optedIn, NewPluginAvailable::class); + Bus::assertNotDispatched(SendNewPluginNotifications::class); } public function test_via_returns_empty_array_when_user_opted_out(): void