true, 'libra.notifications.admin_email' => 'admin@libra.ps', 'libra.notifications.throttle_minutes' => 15, ]); }); test('queue failure notification contains job information', function () { $job = Mockery::mock(Job::class); $job->shouldReceive('resolveName')->andReturn('App\\Jobs\\SendEmailJob'); $job->shouldReceive('getQueue')->andReturn('default'); $job->shouldReceive('attempts')->andReturn(3); $exception = new RuntimeException('Job processing failed'); $event = new JobFailed('database', $job, $exception); $notification = new QueueFailureNotification($event); $mail = $notification->toMail(new AnonymousNotifiable); expect($mail->subject)->toContain('[URGENT]'); expect($mail->subject)->toContain('Queue Job Failed'); expect($mail->subject)->toContain('SendEmailJob'); expect($mail->subject)->toContain('Libra Law Firm'); }); test('queue failure notification includes environment', function () { $job = Mockery::mock(Job::class); $job->shouldReceive('resolveName')->andReturn('TestJob'); $job->shouldReceive('getQueue')->andReturn('default'); $job->shouldReceive('attempts')->andReturn(1); $exception = new RuntimeException('Failed'); $event = new JobFailed('database', $job, $exception); $notification = new QueueFailureNotification($event); $mail = $notification->toMail(new AnonymousNotifiable); expect($mail->subject)->toContain('['.app()->environment().']'); }); test('queue failure notification array contains required data', function () { $job = Mockery::mock(Job::class); $job->shouldReceive('resolveName')->andReturn('App\\Jobs\\TestJob'); $job->shouldReceive('getQueue')->andReturn('emails'); $job->shouldReceive('attempts')->andReturn(2); $exception = new RuntimeException('Test failure'); $event = new JobFailed('database', $job, $exception); $notification = new QueueFailureNotification($event); $array = $notification->toArray(new AnonymousNotifiable); expect($array)->toHaveKey('type', 'queue_failure'); expect($array)->toHaveKey('job', 'App\\Jobs\\TestJob'); expect($array)->toHaveKey('queue', 'emails'); }); test('queue failure listener sends notification when enabled', function () { Notification::fake(); $job = Mockery::mock(Job::class); $job->shouldReceive('resolveName')->andReturn('TestJob'); $job->shouldReceive('getQueue')->andReturn('default'); $job->shouldReceive('attempts')->andReturn(1); $exception = new RuntimeException('Failed'); $event = new JobFailed('database', $job, $exception); event($event); Notification::assertSentOnDemand( QueueFailureNotification::class, function ($notification, $channels, $notifiable) { return $notifiable->routes['mail'] === config('libra.notifications.admin_email'); } ); }); test('queue failure listener does not send notification when disabled', function () { Notification::fake(); config(['libra.notifications.system_notifications_enabled' => false]); $job = Mockery::mock(Job::class); $job->shouldReceive('resolveName')->andReturn('TestJob'); $job->shouldReceive('getQueue')->andReturn('default'); $job->shouldReceive('attempts')->andReturn(1); $exception = new RuntimeException('Failed'); $event = new JobFailed('database', $job, $exception); event($event); Notification::assertNothingSent(); }); test('queue failure listener does not send notification when admin email not configured', function () { Notification::fake(); config(['libra.notifications.admin_email' => null]); $job = Mockery::mock(Job::class); $job->shouldReceive('resolveName')->andReturn('TestJob'); $job->shouldReceive('getQueue')->andReturn('default'); $job->shouldReceive('attempts')->andReturn(1); $exception = new RuntimeException('Failed'); $event = new JobFailed('database', $job, $exception); event($event); Notification::assertNothingSent(); });