167 lines
5.4 KiB
PHP
167 lines
5.4 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Tests\Feature;
|
||
|
|
|
||
|
|
use App\Enums\NotificationSeverityEnum;
|
||
|
|
use App\Enums\NotificationTypeEnum;
|
||
|
|
use App\Models\Feed;
|
||
|
|
use App\Models\Notification;
|
||
|
|
use App\Services\Notification\NotificationService;
|
||
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
|
|
use Tests\TestCase;
|
||
|
|
|
||
|
|
class NotificationTest extends TestCase
|
||
|
|
{
|
||
|
|
use RefreshDatabase;
|
||
|
|
|
||
|
|
private NotificationService $service;
|
||
|
|
|
||
|
|
protected function setUp(): void
|
||
|
|
{
|
||
|
|
parent::setUp();
|
||
|
|
$this->service = new NotificationService;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_send_creates_notification_with_all_fields(): void
|
||
|
|
{
|
||
|
|
$notification = $this->service->send(
|
||
|
|
NotificationTypeEnum::FEED_STALE,
|
||
|
|
NotificationSeverityEnum::WARNING,
|
||
|
|
'Feed is stale',
|
||
|
|
'Feed "VRT" has not returned new articles in 24 hours.',
|
||
|
|
data: ['hours_stale' => 24],
|
||
|
|
);
|
||
|
|
|
||
|
|
$this->assertDatabaseHas('notifications', [
|
||
|
|
'type' => 'feed_stale',
|
||
|
|
'severity' => 'warning',
|
||
|
|
'title' => 'Feed is stale',
|
||
|
|
]);
|
||
|
|
$this->assertEquals(['hours_stale' => 24], $notification->data);
|
||
|
|
$this->assertNull($notification->read_at);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_info_convenience_method(): void
|
||
|
|
{
|
||
|
|
$notification = $this->service->info('Test title', 'Test message');
|
||
|
|
|
||
|
|
$this->assertEquals(NotificationTypeEnum::GENERAL, $notification->type);
|
||
|
|
$this->assertEquals(NotificationSeverityEnum::INFO, $notification->severity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_warning_convenience_method(): void
|
||
|
|
{
|
||
|
|
$notification = $this->service->warning('Warning title', 'Warning message');
|
||
|
|
|
||
|
|
$this->assertEquals(NotificationSeverityEnum::WARNING, $notification->severity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_error_convenience_method(): void
|
||
|
|
{
|
||
|
|
$notification = $this->service->error('Error title', 'Error message');
|
||
|
|
|
||
|
|
$this->assertEquals(NotificationSeverityEnum::ERROR, $notification->severity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_mark_as_read(): void
|
||
|
|
{
|
||
|
|
$notification = Notification::factory()->unread()->create();
|
||
|
|
|
||
|
|
$this->assertFalse($notification->isRead());
|
||
|
|
|
||
|
|
$notification->markAsRead();
|
||
|
|
|
||
|
|
$this->assertTrue($notification->fresh()->isRead());
|
||
|
|
$this->assertNotNull($notification->fresh()->read_at);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_mark_all_as_read(): void
|
||
|
|
{
|
||
|
|
Notification::factory()->count(3)->unread()->create();
|
||
|
|
Notification::factory()->count(2)->read()->create();
|
||
|
|
|
||
|
|
$this->assertEquals(3, Notification::unread()->count());
|
||
|
|
|
||
|
|
Notification::markAllAsRead();
|
||
|
|
|
||
|
|
$this->assertEquals(0, Notification::unread()->count());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_unread_scope(): void
|
||
|
|
{
|
||
|
|
Notification::factory()->count(2)->unread()->create();
|
||
|
|
Notification::factory()->count(3)->read()->create();
|
||
|
|
|
||
|
|
$this->assertEquals(2, Notification::unread()->count());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_recent_scope_limits_to_50(): void
|
||
|
|
{
|
||
|
|
Notification::factory()->count(60)->create();
|
||
|
|
|
||
|
|
$this->assertCount(50, Notification::recent()->get());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_enums_cast_correctly(): void
|
||
|
|
{
|
||
|
|
$notification = Notification::factory()->create([
|
||
|
|
'type' => NotificationTypeEnum::PUBLISH_FAILED,
|
||
|
|
'severity' => NotificationSeverityEnum::ERROR,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$fresh = Notification::find($notification->id);
|
||
|
|
$this->assertInstanceOf(NotificationTypeEnum::class, $fresh->type);
|
||
|
|
$this->assertInstanceOf(NotificationSeverityEnum::class, $fresh->severity);
|
||
|
|
$this->assertEquals(NotificationTypeEnum::PUBLISH_FAILED, $fresh->type);
|
||
|
|
$this->assertEquals(NotificationSeverityEnum::ERROR, $fresh->severity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_notifiable_morph_to_relationship(): void
|
||
|
|
{
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
|
||
|
|
$notification = $this->service->send(
|
||
|
|
NotificationTypeEnum::FEED_STALE,
|
||
|
|
NotificationSeverityEnum::WARNING,
|
||
|
|
'Feed stale',
|
||
|
|
'No new articles',
|
||
|
|
notifiable: $feed,
|
||
|
|
);
|
||
|
|
|
||
|
|
$fresh = Notification::find($notification->id);
|
||
|
|
$this->assertInstanceOf(Feed::class, $fresh->notifiable);
|
||
|
|
$this->assertEquals($feed->id, $fresh->notifiable->id);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_notification_without_notifiable(): void
|
||
|
|
{
|
||
|
|
$notification = $this->service->info('General notice', 'Something happened');
|
||
|
|
|
||
|
|
$this->assertNull($notification->notifiable_type);
|
||
|
|
$this->assertNull($notification->notifiable_id);
|
||
|
|
$this->assertNull($notification->notifiable);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_notification_type_enum_labels(): void
|
||
|
|
{
|
||
|
|
$this->assertEquals('General', NotificationTypeEnum::GENERAL->label());
|
||
|
|
$this->assertEquals('Feed Stale', NotificationTypeEnum::FEED_STALE->label());
|
||
|
|
$this->assertEquals('Publish Failed', NotificationTypeEnum::PUBLISH_FAILED->label());
|
||
|
|
$this->assertEquals('Credential Expired', NotificationTypeEnum::CREDENTIAL_EXPIRED->label());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_data_stores_null_when_empty(): void
|
||
|
|
{
|
||
|
|
$notification = $this->service->info('Title', 'Message');
|
||
|
|
|
||
|
|
$this->assertNull($notification->data);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_data_stores_array_when_provided(): void
|
||
|
|
{
|
||
|
|
$notification = $this->service->info('Title', 'Message', data: ['key' => 'value']);
|
||
|
|
|
||
|
|
$this->assertEquals(['key' => 'value'], $notification->data);
|
||
|
|
}
|
||
|
|
}
|