282 lines
9.4 KiB
PHP
282 lines
9.4 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\User;
|
|
use App\Models\Worker;
|
|
use App\Models\Sponsor;
|
|
use App\Models\WorkerDocument;
|
|
use App\Models\EmployerProfile;
|
|
use App\Models\JobPost;
|
|
use App\Models\JobApplication;
|
|
use App\Models\JobOffer;
|
|
use App\Models\ReminderLog;
|
|
use App\Notifications\DocumentExpiryNotification;
|
|
use App\Notifications\HireConfirmationNotification;
|
|
use App\Notifications\JoiningConfirmationNotification;
|
|
use App\Notifications\PendingConfirmationNotification;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Tests\TestCase;
|
|
|
|
class AutomatedReminderTest 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',
|
|
'age' => 25,
|
|
'salary' => 2000,
|
|
'availability' => 'Immediate',
|
|
'experience' => '2 Years',
|
|
'religion' => 'Christian',
|
|
'bio' => 'Helper info',
|
|
'passport_status' => 'valid',
|
|
], $overrides));
|
|
}
|
|
|
|
public function test_document_expiry_reminders()
|
|
{
|
|
Notification::fake();
|
|
|
|
// 1. Create a Worker with a document expiring in exactly 7 days
|
|
$worker = $this->createTestWorker();
|
|
|
|
$doc = WorkerDocument::create([
|
|
'worker_id' => $worker->id,
|
|
'type' => 'passport',
|
|
'number' => 'PASS123',
|
|
'expiry_date' => now()->addDays(7)->toDateString(),
|
|
]);
|
|
|
|
// 2. Create an Employer (User) with Emirates ID expiring in exactly 3 days
|
|
$employer = User::create([
|
|
'name' => 'Alice Employer',
|
|
'email' => 'employer@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
]);
|
|
|
|
$employerProfile = EmployerProfile::create([
|
|
'user_id' => $employer->id,
|
|
'phone' => '971500000002',
|
|
'address' => 'Dubai',
|
|
'emirates_id_expiry' => now()->addDays(3)->toDateString(),
|
|
]);
|
|
|
|
// 3. Create a Sponsor with Emirates ID expiring in exactly 1 day
|
|
$sponsor = Sponsor::create([
|
|
'full_name' => 'Sponsor Bob',
|
|
'email' => 'sponsor@example.com',
|
|
'mobile' => '971500000003',
|
|
'password' => bcrypt('password'),
|
|
'emirates_id_expiry' => now()->addDays(1)->toDateString(),
|
|
]);
|
|
|
|
// Run the command
|
|
Artisan::call('app:send-reminders');
|
|
|
|
// Assert Worker got Passport expiry 7 days notification
|
|
Notification::assertSentTo(
|
|
$worker,
|
|
DocumentExpiryNotification::class,
|
|
function ($notification) {
|
|
return $notification->documentType === 'Passport' &&
|
|
$notification->daysRemaining === 7 &&
|
|
$notification->reminderLevel === '7_days';
|
|
}
|
|
);
|
|
|
|
// Assert Employer got Emirates ID expiry 3 days notification
|
|
Notification::assertSentTo(
|
|
$employer,
|
|
DocumentExpiryNotification::class,
|
|
function ($notification) {
|
|
return $notification->documentType === 'Emirates ID' &&
|
|
$notification->daysRemaining === 3 &&
|
|
$notification->reminderLevel === '3_days';
|
|
}
|
|
);
|
|
|
|
// Assert Sponsor got Emirates ID expiry 1 day notification
|
|
Notification::assertSentTo(
|
|
$sponsor,
|
|
DocumentExpiryNotification::class,
|
|
function ($notification) {
|
|
return $notification->documentType === 'Emirates ID' &&
|
|
$notification->daysRemaining === 1 &&
|
|
$notification->reminderLevel === '1_day';
|
|
}
|
|
);
|
|
|
|
// Assert reminder logs were created
|
|
$this->assertDatabaseHas('reminder_logs', [
|
|
'user_type' => get_class($worker),
|
|
'user_id' => $worker->id,
|
|
'event_type' => 'document_expiry',
|
|
'reminder_level' => '7_days',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('reminder_logs', [
|
|
'user_type' => get_class($employer),
|
|
'user_id' => $employer->id,
|
|
'event_type' => 'document_expiry',
|
|
'reminder_level' => '3_days',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('reminder_logs', [
|
|
'user_type' => get_class($sponsor),
|
|
'user_id' => $sponsor->id,
|
|
'event_type' => 'document_expiry_emirates',
|
|
'reminder_level' => '1_day',
|
|
]);
|
|
|
|
// Run the command again to ensure duplicate is prevented
|
|
Notification::fake();
|
|
Artisan::call('app:send-reminders');
|
|
|
|
Notification::assertNothingSent();
|
|
}
|
|
|
|
public function test_hire_and_joining_confirmations_reminders()
|
|
{
|
|
Notification::fake();
|
|
|
|
// Create Employer
|
|
$employer = User::create([
|
|
'name' => 'Alice Employer',
|
|
'email' => 'employer@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
]);
|
|
|
|
// Create Worker
|
|
$worker = $this->createTestWorker();
|
|
|
|
// Create a Job Post starting in 7 days
|
|
$job = JobPost::create([
|
|
'employer_id' => $employer->id,
|
|
'title' => 'Housekeeper',
|
|
'location' => 'Dubai',
|
|
'salary' => 2000,
|
|
'workers_needed' => 1,
|
|
'job_type' => 'Full Time',
|
|
'start_date' => now()->addDays(7)->toDateString(),
|
|
'description' => 'Test job',
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// Create a Job Application with status 'selected' (needs Hire Confirmation)
|
|
$appSelected = JobApplication::create([
|
|
'job_id' => $job->id,
|
|
'worker_id' => $worker->id,
|
|
'status' => 'selected',
|
|
]);
|
|
|
|
// Create another Job Post starting in 3 days
|
|
$jobHired = JobPost::create([
|
|
'employer_id' => $employer->id,
|
|
'title' => 'Nanny',
|
|
'location' => 'Dubai',
|
|
'salary' => 2500,
|
|
'workers_needed' => 1,
|
|
'job_type' => 'Full Time',
|
|
'start_date' => now()->addDays(3)->toDateString(),
|
|
'description' => 'Test job hired',
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// Create a Job Application with status 'hired' (needs Joining Confirmation)
|
|
$appHired = JobApplication::create([
|
|
'job_id' => $jobHired->id,
|
|
'worker_id' => $worker->id,
|
|
'status' => 'hired',
|
|
]);
|
|
|
|
// Run the command
|
|
Artisan::call('app:send-reminders');
|
|
|
|
// Assert Employer got Hire Confirmation 7 days notification
|
|
Notification::assertSentTo(
|
|
$employer,
|
|
HireConfirmationNotification::class,
|
|
function ($notification) use ($appSelected) {
|
|
return $notification->jobTitle === 'Housekeeper' &&
|
|
$notification->workerName === 'John Worker' &&
|
|
$notification->daysRemaining === 7 &&
|
|
$notification->applicationId === $appSelected->id;
|
|
}
|
|
);
|
|
|
|
// Assert Worker got Joining Confirmation 3 days notification
|
|
Notification::assertSentTo(
|
|
$worker,
|
|
JoiningConfirmationNotification::class,
|
|
function ($notification) use ($appHired) {
|
|
return $notification->jobTitle === 'Nanny' &&
|
|
$notification->employerName === 'Alice Employer' &&
|
|
$notification->daysRemaining === 3 &&
|
|
$notification->applicationId === $appHired->id;
|
|
}
|
|
);
|
|
|
|
// Verify duplicate prevention
|
|
Notification::fake();
|
|
Artisan::call('app:send-reminders');
|
|
Notification::assertNothingSent();
|
|
}
|
|
|
|
public function test_pending_direct_job_offer_reminders()
|
|
{
|
|
Notification::fake();
|
|
|
|
// Create Employer
|
|
$employer = User::create([
|
|
'name' => 'Alice Employer',
|
|
'email' => 'employer@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
]);
|
|
|
|
// Create Worker
|
|
$worker = $this->createTestWorker();
|
|
|
|
// Create pending direct Job Offer starting in 1 day
|
|
$offer = JobOffer::create([
|
|
'employer_id' => $employer->id,
|
|
'worker_id' => $worker->id,
|
|
'work_date' => now()->addDays(1)->toDateString(),
|
|
'location' => 'Dubai Marina',
|
|
'salary' => 3000,
|
|
'status' => 'pending',
|
|
]);
|
|
|
|
// Run the command
|
|
Artisan::call('app:send-reminders');
|
|
|
|
// Assert Worker got Pending Direct Job Offer 1 day notification
|
|
Notification::assertSentTo(
|
|
$worker,
|
|
PendingConfirmationNotification::class,
|
|
function ($notification) use ($offer) {
|
|
return $notification->actionType === 'accept_offer' &&
|
|
$notification->daysRemaining === 1 &&
|
|
$notification->entityId === $offer->id;
|
|
}
|
|
);
|
|
|
|
// Verify duplicate prevention
|
|
Notification::fake();
|
|
Artisan::call('app:send-reminders');
|
|
Notification::assertNothingSent();
|
|
}
|
|
}
|