192 lines
5.9 KiB
PHP
192 lines
5.9 KiB
PHP
<?php
|
|
|
|
use App\Contracts\ShouldNotifyAdmin;
|
|
use App\Notifications\SystemErrorNotification;
|
|
use App\Services\AdminNotificationService;
|
|
use Illuminate\Notifications\AnonymousNotifiable;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Notification;
|
|
|
|
beforeEach(function () {
|
|
config([
|
|
'libra.notifications.system_notifications_enabled' => true,
|
|
'libra.notifications.admin_email' => 'admin@libra.ps',
|
|
'libra.notifications.throttle_minutes' => 15,
|
|
]);
|
|
Cache::flush();
|
|
});
|
|
|
|
test('critical exception triggers admin notification via service', function () {
|
|
Notification::fake();
|
|
|
|
$exception = new class('Critical payment error') extends Exception implements ShouldNotifyAdmin {};
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
if ($service->shouldNotifyAdmin($exception)) {
|
|
$service->notifyError($exception);
|
|
}
|
|
|
|
Notification::assertSentOnDemand(
|
|
SystemErrorNotification::class,
|
|
function ($notification, $channels, $notifiable) {
|
|
return $notifiable->routes['mail'] === config('libra.notifications.admin_email');
|
|
}
|
|
);
|
|
});
|
|
|
|
test('validation exception does not trigger admin notification', function () {
|
|
Notification::fake();
|
|
|
|
try {
|
|
validator([], ['email' => 'required'])->validate();
|
|
} catch (\Illuminate\Validation\ValidationException $e) {
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
if ($service->shouldNotifyAdmin($e)) {
|
|
$service->notifyError($e);
|
|
}
|
|
}
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
test('authentication exception does not trigger admin notification', function () {
|
|
Notification::fake();
|
|
|
|
$exception = new \Illuminate\Auth\AuthenticationException;
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
if ($service->shouldNotifyAdmin($exception)) {
|
|
$service->notifyError($exception);
|
|
}
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
test('authorization exception does not trigger admin notification', function () {
|
|
Notification::fake();
|
|
|
|
$exception = new \Illuminate\Auth\Access\AuthorizationException;
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
if ($service->shouldNotifyAdmin($exception)) {
|
|
$service->notifyError($exception);
|
|
}
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
test('model not found exception does not trigger admin notification', function () {
|
|
Notification::fake();
|
|
|
|
$exception = new \Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
if ($service->shouldNotifyAdmin($exception)) {
|
|
$service->notifyError($exception);
|
|
}
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
test('http 404 exception does not trigger admin notification', function () {
|
|
Notification::fake();
|
|
|
|
$exception = new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
if ($service->shouldNotifyAdmin($exception)) {
|
|
$service->notifyError($exception);
|
|
}
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
test('system error notification contains required information', function () {
|
|
$exception = new RuntimeException('Test error message');
|
|
$notification = new SystemErrorNotification($exception);
|
|
|
|
$mail = $notification->toMail(new AnonymousNotifiable);
|
|
|
|
expect($mail->subject)->toContain('[URGENT]');
|
|
expect($mail->subject)->toContain('RuntimeException');
|
|
expect($mail->subject)->toContain('Libra Law Firm');
|
|
});
|
|
|
|
test('system error notification includes environment', function () {
|
|
$exception = new RuntimeException('Test error');
|
|
$notification = new SystemErrorNotification($exception);
|
|
|
|
$mail = $notification->toMail(new AnonymousNotifiable);
|
|
|
|
expect($mail->subject)->toContain('['.app()->environment().']');
|
|
});
|
|
|
|
test('system error notification sent immediately not queued', function () {
|
|
Notification::fake();
|
|
|
|
$exception = new class('Critical error') extends Exception implements ShouldNotifyAdmin {};
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
$service->notifyError($exception);
|
|
|
|
Notification::assertSentOnDemand(SystemErrorNotification::class);
|
|
});
|
|
|
|
test('rate limiting prevents duplicate notifications within throttle period', function () {
|
|
Notification::fake();
|
|
|
|
$exception = new class('Critical error') extends Exception implements ShouldNotifyAdmin {};
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
$service->notifyError($exception);
|
|
$service->notifyError($exception);
|
|
$service->notifyError($exception);
|
|
|
|
Notification::assertSentOnDemandTimes(SystemErrorNotification::class, 1);
|
|
});
|
|
|
|
test('different exceptions are not rate limited together', function () {
|
|
Notification::fake();
|
|
|
|
$exception1 = new class('Error 1') extends Exception implements ShouldNotifyAdmin {};
|
|
$exception2 = new class('Error 2') extends Exception implements ShouldNotifyAdmin {};
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
|
|
$service->notifyError($exception1);
|
|
$service->notifyError($exception2);
|
|
|
|
Notification::assertSentOnDemandTimes(SystemErrorNotification::class, 2);
|
|
});
|
|
|
|
test('notification not sent when system notifications disabled', function () {
|
|
Notification::fake();
|
|
config(['libra.notifications.system_notifications_enabled' => false]);
|
|
|
|
$exception = new class('Critical error') extends Exception implements ShouldNotifyAdmin {};
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
$service->notifyError($exception);
|
|
|
|
Notification::assertNothingSent();
|
|
});
|
|
|
|
test('notification not sent when admin email not configured', function () {
|
|
Notification::fake();
|
|
config(['libra.notifications.admin_email' => null]);
|
|
|
|
$exception = new class('Critical error') extends Exception implements ShouldNotifyAdmin {};
|
|
|
|
$service = app(AdminNotificationService::class);
|
|
$service->notifyError($exception);
|
|
|
|
Notification::assertNothingSent();
|
|
});
|