migrant-web/tests/Feature/NotificationApiTest.php
2026-07-07 01:19:50 +05:30

309 lines
12 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\Worker;
use App\Notifications\DocumentExpiryNotification;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class NotificationApiTest extends TestCase
{
use RefreshDatabase;
private function createTestWorker(array $overrides = []): Worker
{
return Worker::create(array_merge([
'name' => 'John Worker',
'email' => 'worker@example.com',
'password' => bcrypt('password'),
'phone' => '971500000001',
'nationality' => 'Indian',
'status' => 'active',
'api_token' => 'worker_api_token',
'age' => 25,
'salary' => 2000,
'availability' => 'Immediate',
'experience' => '2 Years',
'religion' => 'Christian',
'bio' => 'Helper info',
'passport_status' => 'valid',
], $overrides));
}
private function createTestEmployer(array $overrides = []): User
{
return User::create(array_merge([
'name' => 'Alice Employer',
'email' => 'employer@example.com',
'password' => bcrypt('password'),
'role' => 'employer',
'api_token' => 'employer_api_token',
'subscription_status' => 'active',
], $overrides));
}
public function test_worker_can_list_notifications_with_filters()
{
$worker = $this->createTestWorker();
// Send two notifications
$worker->notify(new DocumentExpiryNotification('Passport', '2026-12-31', 30, '30_days'));
$worker->notify(new DocumentExpiryNotification('Visa', '2026-12-31', 7, '7_days'));
// Mark the Passport notification as read deterministically
$passportNotification = $worker->unreadNotifications()->where('data->document_type', 'Passport')->first();
$passportNotification->markAsRead();
// 1. Fetch all notifications
$response = $this->getJson('/api/workers/notifications', [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$response->assertJsonCount(2, 'data.notifications');
// 2. Fetch unread notifications
$response = $this->getJson('/api/workers/notifications?filter=unread', [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonCount(1, 'data.notifications');
$response->assertJsonPath('data.notifications.0.data.document_type', 'Visa');
// 3. Fetch read notifications
$response = $this->getJson('/api/workers/notifications?filter=read', [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonCount(1, 'data.notifications');
$response->assertJsonPath('data.notifications.0.data.document_type', 'Passport');
}
public function test_worker_can_mark_single_and_all_notifications_as_read()
{
$worker = $this->createTestWorker();
// Send two notifications
$worker->notify(new DocumentExpiryNotification('Passport', '2026-12-31', 30, '30_days'));
$worker->notify(new DocumentExpiryNotification('Visa', '2026-12-31', 7, '7_days'));
$unread = $worker->unreadNotifications;
$this->assertEquals(2, $unread->count());
// 1. Mark single notification as read
$notificationId = $unread->first()->id;
$response = $this->putJson("/api/workers/notifications/{$notificationId}/read", [], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(1, $worker->fresh()->unreadNotifications->count());
// 2. Mark all notifications as read
$response = $this->putJson('/api/workers/notifications/read', [], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(0, $worker->fresh()->unreadNotifications->count());
}
public function test_worker_can_delete_single_and_all_notifications()
{
$worker = $this->createTestWorker();
// Send two notifications
$worker->notify(new DocumentExpiryNotification('Passport', '2026-12-31', 30, '30_days'));
$worker->notify(new DocumentExpiryNotification('Visa', '2026-12-31', 7, '7_days'));
$this->assertEquals(2, $worker->notifications()->count());
// 1. Delete single notification
$notificationId = $worker->notifications->first()->id;
$response = $this->deleteJson("/api/workers/notifications/{$notificationId}", [], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(1, $worker->fresh()->notifications()->count());
// 2. Delete all notifications
$response = $this->deleteJson('/api/workers/notifications', [], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(0, $worker->fresh()->notifications()->count());
}
public function test_employer_can_list_notifications_with_filters()
{
$employer = $this->createTestEmployer();
// Send two notifications
$employer->notify(new DocumentExpiryNotification('Emirates ID', '2026-12-31', 30, '30_days'));
$employer->notify(new DocumentExpiryNotification('Trade License', '2026-12-31', 7, '7_days'));
// Mark the Emirates ID notification as read deterministically
$emiratesIdNotification = $employer->unreadNotifications()->where('data->document_type', 'Emirates ID')->first();
$emiratesIdNotification->markAsRead();
// 1. Fetch all notifications
$response = $this->getJson('/api/employers/notifications', [
'Authorization' => 'Bearer employer_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$response->assertJsonCount(2, 'data.notifications');
// 2. Fetch unread notifications
$response = $this->getJson('/api/employers/notifications?filter=unread', [
'Authorization' => 'Bearer employer_api_token'
]);
$response->assertStatus(200);
$response->assertJsonCount(1, 'data.notifications');
$response->assertJsonPath('data.notifications.0.data.document_type', 'Trade License');
// 3. Fetch read notifications
$response = $this->getJson('/api/employers/notifications?filter=read', [
'Authorization' => 'Bearer employer_api_token'
]);
$response->assertStatus(200);
$response->assertJsonCount(1, 'data.notifications');
$response->assertJsonPath('data.notifications.0.data.document_type', 'Emirates ID');
}
public function test_employer_can_mark_single_and_all_notifications_as_read()
{
$employer = $this->createTestEmployer();
// Send two notifications
$employer->notify(new DocumentExpiryNotification('Emirates ID', '2026-12-31', 30, '30_days'));
$employer->notify(new DocumentExpiryNotification('Trade License', '2026-12-31', 7, '7_days'));
$unread = $employer->unreadNotifications;
$this->assertEquals(2, $unread->count());
// 1. Mark single notification as read
$notificationId = $unread->first()->id;
$response = $this->putJson("/api/employers/notifications/{$notificationId}/read", [], [
'Authorization' => 'Bearer employer_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(1, $employer->fresh()->unreadNotifications->count());
// 2. Mark all notifications as read
$response = $this->putJson('/api/employers/notifications/read', [], [
'Authorization' => 'Bearer employer_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(0, $employer->fresh()->unreadNotifications->count());
}
public function test_employer_can_delete_single_and_all_notifications()
{
$employer = $this->createTestEmployer();
// Send two notifications
$employer->notify(new DocumentExpiryNotification('Emirates ID', '2026-12-31', 30, '30_days'));
$employer->notify(new DocumentExpiryNotification('Trade License', '2026-12-31', 7, '7_days'));
$this->assertEquals(2, $employer->notifications()->count());
// 1. Delete single notification
$notificationId = $employer->notifications->first()->id;
$response = $this->deleteJson("/api/employers/notifications/{$notificationId}", [], [
'Authorization' => 'Bearer employer_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(1, $employer->fresh()->notifications()->count());
// 2. Delete all notifications
$response = $this->deleteJson('/api/employers/notifications', [], [
'Authorization' => 'Bearer employer_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$this->assertEquals(0, $employer->fresh()->notifications()->count());
}
public function test_push_notification_sent_when_job_status_changes()
{
$worker = $this->createTestWorker();
$employer = $this->createTestEmployer();
$jobPost = \App\Models\JobPost::create([
'employer_id' => $employer->id,
'title' => 'Test Maid Job',
'main_profession' => 'Housekeeper',
'workers_needed' => 1,
'job_type' => 'Full Time',
'location' => 'Dubai',
'salary' => 2000,
'start_date' => now()->addDays(7),
'description' => 'Test description',
'status' => 'active',
]);
\App\Models\JobApplication::create([
'worker_id' => $worker->id,
'job_id' => $jobPost->id,
'status' => 'applied'
]);
$this->assertEquals(0, $worker->notifications()->count());
// Update JobPost status
$jobPost->update(['status' => 'closed']);
$notifications = $worker->fresh()->notifications;
$this->assertEquals(1, $notifications->count());
$notification = $notifications->first();
$this->assertEquals('Job Status Changed', $notification->data['title']);
$this->assertEquals('job_status_change', $notification->data['type']);
$this->assertEquals($jobPost->id, $notification->data['job_id']);
$this->assertEquals('active', $notification->data['old_status']);
$this->assertEquals('closed', $notification->data['new_status']);
}
public function test_push_notification_sent_when_worker_status_changes()
{
$worker = $this->createTestWorker([
'status' => 'active'
]);
$this->assertEquals(0, $worker->notifications()->count());
// Update Worker status
$worker->update(['status' => 'Hired']);
$notifications = $worker->fresh()->notifications;
$this->assertEquals(1, $notifications->count());
$notification = $notifications->first();
$this->assertEquals('Profile Status Update', $notification->data['title']);
$this->assertEquals('worker_status_change', $notification->data['type']);
$this->assertEquals($worker->id, $notification->data['worker_id']);
$this->assertEquals('active', $notification->data['old_status']);
$this->assertEquals('Hired', $notification->data['new_status']);
}
}