600 lines
22 KiB
PHP
600 lines
22 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
use App\Models\Worker;
|
|
use App\Models\WorkerDocument;
|
|
use App\Models\User;
|
|
use App\Models\JobOffer;
|
|
use App\Models\EmployerProfile;
|
|
|
|
class WorkerEmployersApiTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_worker_dashboard_current_employer_detail()
|
|
{
|
|
// Create worker
|
|
$worker = Worker::create([
|
|
'name' => 'Rahul Sharma',
|
|
'email' => 'rahul@example.com',
|
|
'phone' => '+971501234567',
|
|
'language' => 'HI',
|
|
'password' => bcrypt('password'),
|
|
'nationality' => 'Indian',
|
|
'age' => 25,
|
|
'salary' => 1500,
|
|
'availability' => 'Immediate',
|
|
'experience' => 'Not Specified',
|
|
'religion' => 'Not Specified',
|
|
'bio' => 'Test',
|
|
'verified' => true,
|
|
'status' => 'active',
|
|
'api_token' => 'worker-test-token',
|
|
]);
|
|
|
|
// Create passport document to prevent pending 404
|
|
WorkerDocument::create([
|
|
'worker_id' => $worker->id,
|
|
'type' => 'passport',
|
|
'number' => '123456',
|
|
'file_path' => 'passports/test.pdf',
|
|
]);
|
|
|
|
// Create an employer
|
|
$employer = User::create([
|
|
'name' => 'Employer One',
|
|
'email' => 'emp1@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
]);
|
|
|
|
EmployerProfile::create([
|
|
'user_id' => $employer->id,
|
|
'company_name' => 'Ahmad Tech Ltd',
|
|
'nationality' => 'UAE',
|
|
'city' => 'Dubai',
|
|
]);
|
|
|
|
// Create an accepted job offer (current employer)
|
|
JobOffer::create([
|
|
'employer_id' => $employer->id,
|
|
'worker_id' => $worker->id,
|
|
'work_date' => now()->subDays(10),
|
|
'location' => 'Dubai',
|
|
'salary' => 2500,
|
|
'status' => 'accepted',
|
|
'notes' => 'Current Active Job',
|
|
]);
|
|
|
|
// Hit the worker dashboard API
|
|
$response = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-test-token',
|
|
])->getJson('/api/workers/dashboard');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'success' => true,
|
|
'data' => [
|
|
'current_employer' => [
|
|
'id' => $employer->id,
|
|
'name' => 'Employer One',
|
|
'company_name' => 'Ahmad Tech Ltd',
|
|
'city' => 'Dubai',
|
|
'nationality' => 'UAE',
|
|
],
|
|
'currently_working_sponsor' => [
|
|
'id' => $employer->id,
|
|
'name' => 'Employer One',
|
|
'company_name' => 'Ahmad Tech Ltd',
|
|
'city' => 'Dubai',
|
|
'nationality' => 'UAE',
|
|
]
|
|
]
|
|
]);
|
|
}
|
|
|
|
public function test_worker_employers_list_pagination_and_sorting()
|
|
{
|
|
// Create worker
|
|
$worker = Worker::create([
|
|
'name' => 'Rahul Sharma',
|
|
'email' => 'rahul@example.com',
|
|
'phone' => '+971501234567',
|
|
'language' => 'HI',
|
|
'password' => bcrypt('password'),
|
|
'nationality' => 'Indian',
|
|
'age' => 25,
|
|
'salary' => 1500,
|
|
'availability' => 'Immediate',
|
|
'experience' => 'Not Specified',
|
|
'religion' => 'Not Specified',
|
|
'bio' => 'Test',
|
|
'verified' => true,
|
|
'status' => 'active',
|
|
'api_token' => 'worker-test-token',
|
|
]);
|
|
|
|
WorkerDocument::create([
|
|
'worker_id' => $worker->id,
|
|
'type' => 'passport',
|
|
'number' => '123456',
|
|
'file_path' => 'passports/test.pdf',
|
|
]);
|
|
|
|
// Create 3 employers
|
|
$emp1 = User::create([
|
|
'name' => 'Employer One',
|
|
'email' => 'emp1@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer'
|
|
]);
|
|
EmployerProfile::create(['user_id' => $emp1->id, 'company_name' => 'Tech One']);
|
|
|
|
$emp2 = User::create([
|
|
'name' => 'Employer Two',
|
|
'email' => 'emp2@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer'
|
|
]);
|
|
EmployerProfile::create(['user_id' => $emp2->id, 'company_name' => 'Tech Two']);
|
|
|
|
$emp3 = User::create([
|
|
'name' => 'Employer Three',
|
|
'email' => 'emp3@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer'
|
|
]);
|
|
EmployerProfile::create(['user_id' => $emp3->id, 'company_name' => 'Tech Three']);
|
|
|
|
// Create JobOffers:
|
|
// Offer 1: Completed status, joining 20 days ago
|
|
JobOffer::create([
|
|
'employer_id' => $emp1->id,
|
|
'worker_id' => $worker->id,
|
|
'work_date' => now()->subDays(20),
|
|
'location' => 'Abu Dhabi',
|
|
'salary' => 2000,
|
|
'status' => 'completed',
|
|
'notes' => 'Past job',
|
|
]);
|
|
|
|
// Offer 2: Cancelled status, joining 30 days ago
|
|
JobOffer::create([
|
|
'employer_id' => $emp2->id,
|
|
'worker_id' => $worker->id,
|
|
'work_date' => now()->subDays(30),
|
|
'location' => 'Sharjah',
|
|
'salary' => 1800,
|
|
'status' => 'cancelled',
|
|
'notes' => 'Cancelled job',
|
|
]);
|
|
|
|
// Offer 3: Accepted (Active) status, joining 10 days ago
|
|
JobOffer::create([
|
|
'employer_id' => $emp3->id,
|
|
'worker_id' => $worker->id,
|
|
'work_date' => now()->subDays(10),
|
|
'location' => 'Dubai',
|
|
'salary' => 3000,
|
|
'status' => 'accepted',
|
|
'notes' => 'Active job',
|
|
]);
|
|
|
|
// List all employers (should return 3)
|
|
// With Active employer at the top, then previous employers sorted by work_date desc:
|
|
// 1st: Emp 3 (Active)
|
|
// 2nd: Emp 1 (Completed, 20 days ago)
|
|
// 3rd: Emp 2 (Cancelled, 30 days ago)
|
|
$response = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-test-token',
|
|
])->getJson('/api/workers/employers');
|
|
|
|
$response->assertStatus(200);
|
|
$data = $response->json('data.employers');
|
|
|
|
$this->assertCount(3, $data);
|
|
$this->assertEquals('Active', $data[0]['status']);
|
|
$this->assertEquals('Employer Three', $data[0]['employer']['name']);
|
|
$this->assertEquals('Completed', $data[1]['status']);
|
|
$this->assertEquals('Employer One', $data[1]['employer']['name']);
|
|
$this->assertEquals('Cancelled', $data[2]['status']);
|
|
$this->assertEquals('Employer Two', $data[2]['employer']['name']);
|
|
|
|
// Test filtering by status Completed
|
|
$responseFiltered = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-test-token',
|
|
])->getJson('/api/workers/employers?status=completed');
|
|
|
|
$responseFiltered->assertStatus(200);
|
|
$filteredData = $responseFiltered->json('data.employers');
|
|
$this->assertCount(1, $filteredData);
|
|
$this->assertEquals('Completed', $filteredData[0]['status']);
|
|
$this->assertEquals('Employer One', $filteredData[0]['employer']['name']);
|
|
|
|
// Test filtering by status Active
|
|
$responseActive = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-test-token',
|
|
])->getJson('/api/workers/employers?status=active');
|
|
|
|
$responseActive->assertStatus(200);
|
|
$activeData = $responseActive->json('data.employers');
|
|
$this->assertCount(1, $activeData);
|
|
$this->assertEquals('Active', $activeData[0]['status']);
|
|
$this->assertEquals('Employer Three', $activeData[0]['employer']['name']);
|
|
|
|
// Test pagination
|
|
$responsePaginated = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-test-token',
|
|
])->getJson('/api/workers/employers?per_page=2');
|
|
|
|
$responsePaginated->assertStatus(200);
|
|
$paginatedData = $responsePaginated->json('data.employers');
|
|
$this->assertCount(2, $paginatedData);
|
|
$this->assertEquals(3, $responsePaginated->json('data.pagination.total'));
|
|
$this->assertEquals(2, $responsePaginated->json('data.pagination.per_page'));
|
|
}
|
|
|
|
public function test_worker_can_view_employer_profile_with_permissions_and_reviews()
|
|
{
|
|
// Create worker
|
|
$worker = Worker::create([
|
|
'name' => 'Rahul Sharma',
|
|
'email' => 'rahul@example.com',
|
|
'phone' => '+971501234567',
|
|
'language' => 'HI',
|
|
'password' => bcrypt('password'),
|
|
'nationality' => 'Indian',
|
|
'age' => 25,
|
|
'salary' => 1500,
|
|
'availability' => 'Immediate',
|
|
'experience' => 'Not Specified',
|
|
'religion' => 'Not Specified',
|
|
'bio' => 'Test',
|
|
'verified' => true,
|
|
'status' => 'active',
|
|
'api_token' => 'worker-test-token',
|
|
]);
|
|
|
|
WorkerDocument::create([
|
|
'worker_id' => $worker->id,
|
|
'type' => 'passport',
|
|
'number' => '123456',
|
|
'file_path' => 'passports/test.pdf',
|
|
]);
|
|
|
|
// Create an employer
|
|
$employer = User::create([
|
|
'name' => 'Employer One',
|
|
'email' => 'emp1@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
]);
|
|
|
|
EmployerProfile::create([
|
|
'user_id' => $employer->id,
|
|
'company_name' => 'Ahmad Tech Ltd',
|
|
'phone' => '+971500000001',
|
|
'nationality' => 'UAE',
|
|
'city' => 'Dubai',
|
|
'accommodation' => 'Provided',
|
|
'language' => 'English',
|
|
]);
|
|
|
|
// Create active job post
|
|
\App\Models\JobPost::create([
|
|
'employer_id' => $employer->id,
|
|
'title' => 'Housekeeper Needed',
|
|
'location' => 'Dubai Marina',
|
|
'salary' => 2500,
|
|
'workers_needed' => 1,
|
|
'job_type' => 'Full Time',
|
|
'start_date' => now()->addDays(5)->toDateString(),
|
|
'description' => 'Clean house',
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// Create an accepted job offer (connection exists)
|
|
JobOffer::create([
|
|
'employer_id' => $employer->id,
|
|
'worker_id' => $worker->id,
|
|
'work_date' => now()->subDays(10),
|
|
'location' => 'Dubai',
|
|
'salary' => 2500,
|
|
'status' => 'accepted',
|
|
]);
|
|
|
|
// Create a review submitted by another worker
|
|
$otherWorker = Worker::create([
|
|
'name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'phone' => '+971501234568',
|
|
'password' => bcrypt('password'),
|
|
'nationality' => 'Filipino',
|
|
'age' => 25,
|
|
'salary' => 1500,
|
|
'availability' => 'Immediate',
|
|
'experience' => 'Not Specified',
|
|
'religion' => 'Not Specified',
|
|
'bio' => 'Test',
|
|
'passport_status' => 'valid',
|
|
]);
|
|
|
|
\App\Models\EmployerReview::create([
|
|
'worker_id' => $otherWorker->id,
|
|
'employer_id' => $employer->id,
|
|
'rating' => 5,
|
|
'title' => 'Excellent sponsor',
|
|
'comment' => 'Very polite and pays on time.',
|
|
]);
|
|
|
|
// Hit the new API endpoint
|
|
$response = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-test-token',
|
|
])->getJson("/api/workers/employers/{$employer->id}");
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertJsonPath('success', true);
|
|
$response->assertJsonPath('data.employer.name', 'Employer One');
|
|
$response->assertJsonPath('data.employer.email', 'emp1@example.com'); // Contact info visible because of JobOffer connection
|
|
$response->assertJsonPath('data.employer.phone', '+971500000001');
|
|
$response->assertJsonPath('data.employer.company_name', 'Ahmad Tech Ltd');
|
|
$response->assertJsonPath('data.employer.rating', 5);
|
|
$response->assertJsonPath('data.employer.reviews_count', 1);
|
|
$response->assertJsonPath('data.employer.review_summary.stars.5', 1);
|
|
$response->assertJsonCount(1, 'data.employer.active_jobs');
|
|
$response->assertJsonPath('data.employer.active_jobs.0.title', 'Housekeeper Needed');
|
|
$response->assertJsonCount(1, 'data.reviews.data');
|
|
$response->assertJsonPath('data.reviews.data.0.worker.name', 'John Doe');
|
|
$response->assertJsonPath('data.reviews.data.0.title', 'Excellent sponsor');
|
|
}
|
|
|
|
public function test_worker_can_view_employer_profile_without_permissions_masks_contact()
|
|
{
|
|
// Create worker
|
|
$worker = Worker::create([
|
|
'name' => 'Rahul Sharma',
|
|
'email' => 'rahul@example.com',
|
|
'phone' => '+971501234567',
|
|
'language' => 'HI',
|
|
'password' => bcrypt('password'),
|
|
'nationality' => 'Indian',
|
|
'age' => 25,
|
|
'salary' => 1500,
|
|
'availability' => 'Immediate',
|
|
'experience' => 'Not Specified',
|
|
'religion' => 'Not Specified',
|
|
'bio' => 'Test',
|
|
'verified' => true,
|
|
'status' => 'active',
|
|
'api_token' => 'worker-test-token',
|
|
]);
|
|
|
|
WorkerDocument::create([
|
|
'worker_id' => $worker->id,
|
|
'type' => 'passport',
|
|
'number' => '123456',
|
|
'file_path' => 'passports/test.pdf',
|
|
]);
|
|
|
|
// Create an employer
|
|
$employer = User::create([
|
|
'name' => 'Employer One',
|
|
'email' => 'emp1@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
]);
|
|
|
|
EmployerProfile::create([
|
|
'user_id' => $employer->id,
|
|
'company_name' => 'Ahmad Tech Ltd',
|
|
'phone' => '+971500000001',
|
|
]);
|
|
|
|
// Hit the API (no connection exists)
|
|
$response = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-test-token',
|
|
])->getJson("/api/workers/employers/{$employer->id}");
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertJsonPath('success', true);
|
|
$response->assertJsonPath('data.employer.name', 'Employer One');
|
|
$response->assertJsonPath('data.employer.email', null); // Masked/null since no connection exists
|
|
$response->assertJsonPath('data.employer.phone', null);
|
|
}
|
|
|
|
public function test_worker_hired_via_job_application_appears_in_employers_list()
|
|
{
|
|
// 1. Create a worker
|
|
$worker = Worker::create([
|
|
'name' => 'Hired Worker',
|
|
'email' => 'hiredworker@example.com',
|
|
'phone' => '+971501234567',
|
|
'language' => 'HI',
|
|
'password' => bcrypt('password'),
|
|
'nationality' => 'Indian',
|
|
'age' => 25,
|
|
'salary' => 1500,
|
|
'availability' => 'Immediate',
|
|
'experience' => 'Not Specified',
|
|
'religion' => 'Not Specified',
|
|
'bio' => 'Test',
|
|
'verified' => true,
|
|
'status' => 'active',
|
|
'api_token' => 'worker-hired-token',
|
|
]);
|
|
|
|
WorkerDocument::create([
|
|
'worker_id' => $worker->id,
|
|
'type' => 'passport',
|
|
'number' => '123456',
|
|
'file_path' => 'passports/test.pdf',
|
|
]);
|
|
|
|
// 2. Create employer with active subscription
|
|
$employer = User::create([
|
|
'name' => 'Premium Employer',
|
|
'email' => 'premium_emp@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
'subscription_status' => 'active',
|
|
'api_token' => 'premium_employer_token',
|
|
]);
|
|
|
|
EmployerProfile::create([
|
|
'user_id' => $employer->id,
|
|
'company_name' => 'Premium Corp Ltd',
|
|
'nationality' => 'UAE',
|
|
'city' => 'Abu Dhabi',
|
|
]);
|
|
|
|
\App\Models\Subscription::create([
|
|
'user_id' => $employer->id,
|
|
'plan_id' => 'premium',
|
|
'amount_aed' => 100.00,
|
|
'starts_at' => now(),
|
|
'expires_at' => now()->addDays(30),
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// 3. Create a JobPost
|
|
$job = \App\Models\JobPost::create([
|
|
'employer_id' => $employer->id,
|
|
'title' => 'Housekeeper Needed',
|
|
'workers_needed' => 1,
|
|
'location' => 'Abu Dhabi',
|
|
'salary' => 2000,
|
|
'job_type' => 'Full Time',
|
|
'start_date' => now()->addDays(5),
|
|
'description' => 'Test job',
|
|
'requirements' => 'None',
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// 4. Create JobApplication
|
|
$application = \App\Models\JobApplication::create([
|
|
'job_id' => $job->id,
|
|
'worker_id' => $worker->id,
|
|
'status' => 'applied',
|
|
'notes' => 'Looking forward to work',
|
|
]);
|
|
|
|
// Verify employer list is empty for the worker initially
|
|
$response = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-hired-token',
|
|
])->getJson('/api/workers/employers');
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertJsonCount(0, 'data.employers');
|
|
|
|
// 5. Employer hires candidate via API
|
|
$response = $this->postJson("/api/employers/applications/{$application->id}/status", [
|
|
'status' => 'hired',
|
|
'notes' => 'Hired and approved'
|
|
], [
|
|
'Authorization' => 'Bearer premium_employer_token'
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
// Verify that the JobOffer with accepted status has been created
|
|
$this->assertDatabaseHas('job_offers', [
|
|
'employer_id' => $employer->id,
|
|
'worker_id' => $worker->id,
|
|
'status' => 'accepted',
|
|
]);
|
|
|
|
// 6. Hit the worker employers API and assert that the employer is now listed
|
|
$response = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-hired-token',
|
|
])->getJson('/api/workers/employers');
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertJsonCount(1, 'data.employers');
|
|
$response->assertJsonPath('data.employers.0.employer.name', 'Premium Employer');
|
|
$response->assertJsonPath('data.employers.0.employer.company_name', 'Premium Corp Ltd');
|
|
$response->assertJsonPath('data.employers.0.status', 'Active');
|
|
}
|
|
|
|
public function test_worker_hired_via_job_application_appears_without_job_offer()
|
|
{
|
|
// 1. Create a worker
|
|
$worker = Worker::create([
|
|
'name' => 'Hired Worker Legacy',
|
|
'email' => 'legacyworker@example.com',
|
|
'phone' => '+971501234560',
|
|
'language' => 'HI',
|
|
'password' => bcrypt('password'),
|
|
'nationality' => 'Indian',
|
|
'age' => 25,
|
|
'salary' => 1500,
|
|
'availability' => 'Immediate',
|
|
'experience' => 'Not Specified',
|
|
'religion' => 'Not Specified',
|
|
'bio' => 'Test',
|
|
'verified' => true,
|
|
'status' => 'active',
|
|
'api_token' => 'worker-legacy-token',
|
|
]);
|
|
|
|
WorkerDocument::create([
|
|
'worker_id' => $worker->id,
|
|
'type' => 'passport',
|
|
'number' => '123456',
|
|
'file_path' => 'passports/test.pdf',
|
|
]);
|
|
|
|
// 2. Create employer
|
|
$employer = User::create([
|
|
'name' => 'Legacy Employer',
|
|
'email' => 'legacy_emp@example.com',
|
|
'password' => bcrypt('password'),
|
|
'role' => 'employer',
|
|
'subscription_status' => 'active',
|
|
'api_token' => 'legacy_employer_token',
|
|
]);
|
|
|
|
EmployerProfile::create([
|
|
'user_id' => $employer->id,
|
|
'company_name' => 'Legacy Corp Ltd',
|
|
'nationality' => 'UAE',
|
|
'city' => 'Dubai',
|
|
]);
|
|
|
|
// 3. Create a JobPost
|
|
$job = \App\Models\JobPost::create([
|
|
'employer_id' => $employer->id,
|
|
'title' => 'Housekeeper Needed Legacy',
|
|
'workers_needed' => 1,
|
|
'location' => 'Dubai',
|
|
'salary' => 2000,
|
|
'job_type' => 'Full Time',
|
|
'start_date' => now()->addDays(5),
|
|
'description' => 'Test job',
|
|
'requirements' => 'None',
|
|
'status' => 'active',
|
|
]);
|
|
|
|
// 4. Create JobApplication with status 'hired' directly, and NO JobOffer
|
|
$application = \App\Models\JobApplication::create([
|
|
'job_id' => $job->id,
|
|
'worker_id' => $worker->id,
|
|
'status' => 'hired',
|
|
'notes' => 'Hired directly in DB previously',
|
|
]);
|
|
|
|
// 5. Hit the worker employers API and assert that the employer is listed
|
|
$response = $this->withHeaders([
|
|
'Authorization' => 'Bearer worker-legacy-token',
|
|
])->getJson('/api/workers/employers');
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertJsonCount(1, 'data.employers');
|
|
$response->assertJsonPath('data.employers.0.employer.name', 'Legacy Employer');
|
|
$response->assertJsonPath('data.employers.0.employer.company_name', 'Legacy Corp Ltd');
|
|
$response->assertJsonPath('data.employers.0.status', 'Active');
|
|
}
|
|
}
|