false]); Queue::fake(); $post = new ForumPost(); $post->id = 42; $queued = app(ForumModerationService::class)->dispatchAsyncScan($post); expect($queued)->toBeFalse(); Queue::assertNotPushed(AnalyzeForumPostJob::class); }); it('dispatches AnalyzeForumPostJob when AI queue dispatch is enabled', function () { config(['skinbase_ai_moderation.queue.dispatch_enabled' => true]); Queue::fake(); $post = new ForumPost(); $post->id = 43; $queued = app(ForumModerationService::class)->dispatchAsyncScan($post); expect($queued)->toBeTrue(); Queue::assertPushedOn( (string) config('skinbase_ai_moderation.queue.name', 'forum-moderation'), AnalyzeForumPostJob::class, ); }); it('does not dispatch BotActivityMonitor when security queue dispatch is disabled', function () { config(['forum_security.queues.dispatch_enabled' => false]); Queue::fake(); $this->artisan('forum:bot-scan')->assertSuccessful(); Queue::assertNotPushed(BotActivityMonitor::class); }); it('dispatches BotActivityMonitor when security queue dispatch is enabled', function () { config(['forum_security.queues.dispatch_enabled' => true]); Queue::fake(); $this->artisan('forum:bot-scan')->assertSuccessful(); Queue::assertPushed(BotActivityMonitor::class); }); it('does not dispatch FirewallActivityMonitor when security queue dispatch is disabled', function () { config(['forum_security.queues.dispatch_enabled' => false]); Queue::fake(); $this->artisan('forum:firewall-scan')->assertSuccessful(); Queue::assertNotPushed(FirewallActivityMonitor::class); }); it('dispatches FirewallActivityMonitor when security queue dispatch is enabled', function () { config(['forum_security.queues.dispatch_enabled' => true]); Queue::fake(); $this->artisan('forum:firewall-scan')->assertSuccessful(); Queue::assertPushed(FirewallActivityMonitor::class); }); it('runs forum bot scan synchronously without queueing when --sync is passed', function () { config(['forum_security.queues.dispatch_enabled' => false]); Queue::fake(); $this->mock(BotProtectionService::class, function ($mock): void { $mock->shouldReceive('scanRecentActivity')->once()->andReturn(['processed' => 0]); }); $this->artisan('forum:bot-scan --sync')->assertSuccessful(); Queue::assertNothingPushed(); }); it('runs forum firewall scan synchronously without queueing when --sync is passed', function () { config(['forum_security.queues.dispatch_enabled' => false]); Queue::fake(); $this->mock(ForumSecurityFirewallService::class, function ($mock): void { $mock->shouldReceive('scanRecentThreats')->once()->andReturn(['processed' => 0]); }); $this->artisan('forum:firewall-scan --sync')->assertSuccessful(); Queue::assertNothingPushed(); }); it('does not enqueue AnalyzeForumPostJob from forum:ai-scan without --sync when dispatch is disabled', function () { config(['skinbase_ai_moderation.queue.dispatch_enabled' => false]); Queue::fake(); $this->artisan('forum:ai-scan')->assertSuccessful(); Queue::assertNotPushed(AnalyzeForumPostJob::class); }); it('keeps synchronous forum:scan-posts on the schedule and omits async forum enqueue commands when dispatch is disabled', function () { $this->artisan('schedule:list') ->expectsOutputToContain('forum:scan-posts') ->doesntExpectOutputToContain('forum:ai-scan') ->doesntExpectOutputToContain('forum:bot-scan') ->doesntExpectOutputToContain('forum:firewall-scan') ->assertSuccessful(); });