migrant-web/tests/Feature/EmployerProfileApiTest.php

414 lines
16 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\EmployerProfile;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class EmployerProfileApiTest extends TestCase
{
use RefreshDatabase;
protected $employer;
protected $token;
protected function setUp(): void
{
parent::setUp();
$this->token = 'test-employer-token';
$this->employer = User::create([
'name' => 'Original Name',
'email' => 'employer@example.com',
'password' => bcrypt('Password@123'),
'role' => 'employer',
'api_token' => $this->token,
]);
EmployerProfile::create([
'user_id' => $this->employer->id,
'address' => 'Original Address',
'phone' => '+971501112222',
'verification_status' => 'approved',
'notifications' => true,
]);
}
/**
* Test employer can retrieve profile.
*/
public function test_employer_can_get_profile()
{
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->getJson('/api/employers/profile');
$response->assertStatus(200)
->assertJsonStructure([
'success',
'data' => [
'profile' => [
'name',
'email',
'phone',
'address',
'notifications',
'verification_status',
'emirates_id',
]
]
]);
$this->assertEquals('Original Name', $response->json('data.profile.name'));
$this->assertEquals('Original Address', $response->json('data.profile.address'));
}
/**
* Test employer can update profile details.
*/
public function test_employer_can_update_profile()
{
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->postJson('/api/employers/profile/update', [
'name' => 'Updated Name',
'email' => 'employer_updated@example.com',
'phone' => '+971509999999',
'address' => 'Updated Address Info',
'notifications' => false,
]);
$response->assertStatus(200)
->assertJsonStructure([
'success',
'message',
'data' => [
'profile' => [
'name',
'email',
'phone',
'address',
'notifications',
'emirates_id',
]
]
]);
$this->assertDatabaseHas('users', [
'id' => $this->employer->id,
'name' => 'Updated Name',
'email' => 'employer_updated@example.com',
]);
$this->assertDatabaseHas('employer_profiles', [
'user_id' => $this->employer->id,
'address' => 'Updated Address Info',
'notifications' => false,
]);
}
/**
* Test employer can update profile with optional Emirates ID fields.
*/
public function test_employer_can_update_profile_with_emirates_id_fields()
{
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->postJson('/api/employers/profile/update', [
'name' => 'Ahmad',
'email' => 'ahmad@example.com',
'phone' => '+971509990001',
'address' => 'Villa 12, Jumeirah 2',
'notifications' => true,
'id_number' => '784-1987-5493842-5',
'card_number' => '151023946',
'full_name' => 'Mohammad Jobaier Mohammad Abul Kalam',
'date_of_birth' => '14/04/1987',
'nationality' => 'Bangladesh',
'gender' => 'M',
'issue_date' => '12/12/2025',
'expiry_date' => '11/12/2027',
'occupation' => 'Electrician',
'employer' => 'Msj International Technical Services L.L.C UAE',
'issuing_place' => 'Dubai',
]);
$response->assertStatus(200)
->assertJson([
'success' => true,
'data' => [
'profile' => [
'name' => 'Mohammad Jobaier Mohammad Abul Kalam',
'email' => 'ahmad@example.com',
'phone' => '+971509990001',
'address' => 'Villa 12, Jumeirah 2',
'id_number' => '784-1987-5493842-5',
'card_number' => '151023946',
'full_name' => 'Mohammad Jobaier Mohammad Abul Kalam',
'gender' => 'M',
'emirates_id' => [
'emirates_id_number' => '784-1987-5493842-5',
'name' => 'Mohammad Jobaier Mohammad Abul Kalam',
'date_of_birth' => '1987-04-14',
'nationality' => 'Bangladesh',
'issue_date' => '2025-12-12',
'expiry_date' => '2027-12-11',
'employer' => 'Msj International Technical Services L.L.C UAE',
'issue_place' => 'Dubai',
'occupation' => 'Electrician',
]
]
]
]);
$this->assertDatabaseHas('employer_profiles', [
'user_id' => $this->employer->id,
'emirates_id_number' => '784-1987-5493842-5',
'emirates_id_card_number' => '151023946',
'emirates_id_name' => 'Mohammad Jobaier Mohammad Abul Kalam',
'emirates_id_gender' => 'M',
]);
}
/**
* Test employer cannot change an existing Emirates ID number.
*/
public function test_employer_cannot_change_existing_emirates_id_number()
{
// First, set the Emirates ID
$profile = $this->employer->employerProfile;
$profile->emirates_id_number = '784-1987-5493842-5';
$profile->save();
// Attempt to change to a different ID
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->postJson('/api/employers/profile/update', [
'name' => 'Original Name',
'email' => 'employer@example.com',
'phone' => '+971501112222',
'address' => 'Original Address',
'id_number' => '784-9999-0000000-0',
]);
$response->assertStatus(422)
->assertJson([
'success' => false,
'errors' => [
'id_number' => ['Emirates ID mismatch.']
]
]);
// Verify ID was NOT changed
$this->assertEquals('784-1987-5493842-5', $profile->fresh()->emirates_id_number);
}
/**
* Test employer dashboard returns only the latest 2 approved charity drives.
*/
public function test_employer_dashboard_returns_only_two_charity_drives()
{
// Create 5 approved announcements
for ($i = 1; $i <= 5; $i++) {
$ann = new \App\Models\Announcement([
'title' => "Charity Drive $i",
'body' => "Details of charity drive $i",
'type' => 'charity',
'status' => 'approved',
]);
$ann->created_at = now()->subMinutes(6 - $i);
$ann->save();
}
// Create 1 pending announcement
$pendingAnn = new \App\Models\Announcement([
'title' => "Pending Charity Drive",
'body' => "Details of pending charity drive",
'type' => 'charity',
'status' => 'pending',
]);
$pendingAnn->created_at = now();
$pendingAnn->save();
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->getJson('/api/employers/dashboard');
$response->assertStatus(200)
->assertJson([
'success' => true,
]);
$announcements = $response->json('data.recent_announcements');
$this->assertCount(2, $announcements);
// Make sure it contains the latest 2 approved ones
$titles = collect($announcements)->pluck('title');
$this->assertTrue($titles->contains('Charity Drive 5'));
$this->assertTrue($titles->contains('Charity Drive 4'));
$this->assertFalse($titles->contains('Charity Drive 3'));
$this->assertFalse($titles->contains('Charity Drive 2'));
$this->assertFalse($titles->contains('Charity Drive 1'));
$this->assertFalse($titles->contains('Pending Charity Drive'));
}
public function test_employer_dashboard_returns_total_workers_active()
{
// Delete any existing workers seeded or created to make count precise
\App\Models\Worker::query()->delete();
// Create 3 active workers
$w1 = \App\Models\Worker::create([
'name' => 'Active 1', 'email' => 'a1@test.com', 'phone' => '+971501110001',
'password' => bcrypt('password'), 'status' => 'active', 'nationality' => 'Indian',
'preferred_location' => 'Dubai', 'age' => 25, 'salary' => 1500, 'experience' => '3 Years',
'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker',
'verified' => true,
]);
\App\Models\WorkerDocument::create([
'worker_id' => $w1->id, 'type' => 'passport', 'number' => 'P111',
'issue_date' => '2020-01-01', 'expiry_date' => '2030-01-01',
]);
$w2 = \App\Models\Worker::create([
'name' => 'Active 2', 'email' => 'a2@test.com', 'phone' => '+971501110002',
'password' => bcrypt('password'), 'status' => 'active', 'nationality' => 'Indian',
'preferred_location' => 'Dubai', 'age' => 26, 'salary' => 1500, 'experience' => '3 Years',
'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker',
'verified' => true,
]);
\App\Models\WorkerDocument::create([
'worker_id' => $w2->id, 'type' => 'passport', 'number' => 'P222',
'issue_date' => '2020-01-01', 'expiry_date' => '2030-01-01',
]);
$w3 = \App\Models\Worker::create([
'name' => 'Active 3', 'email' => 'a3@test.com', 'phone' => '+971501110003',
'password' => bcrypt('password'), 'status' => 'active', 'nationality' => 'Indian',
'preferred_location' => 'Dubai', 'age' => 27, 'salary' => 1500, 'experience' => '3 Years',
'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker',
'verified' => true,
]);
\App\Models\WorkerDocument::create([
'worker_id' => $w3->id, 'type' => 'passport', 'number' => 'P333',
'issue_date' => '2020-01-01', 'expiry_date' => '2030-01-01',
]);
// Create 2 inactive/hidden workers
\App\Models\Worker::create([
'name' => 'Inactive 1', 'email' => 'i1@test.com', 'phone' => '+971502220001',
'password' => bcrypt('password'), 'status' => 'hidden', 'nationality' => 'Indian',
'preferred_location' => 'Dubai', 'age' => 28, 'salary' => 1500, 'experience' => '3 Years',
'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker',
]);
\App\Models\Worker::create([
'name' => 'Inactive 2', 'email' => 'i2@test.com', 'phone' => '+971502220002',
'password' => bcrypt('password'), 'status' => 'Hired', 'nationality' => 'Indian',
'preferred_location' => 'Dubai', 'age' => 29, 'salary' => 1500, 'experience' => '3 Years',
'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker',
]);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->getJson('/api/employers/dashboard');
$response->assertStatus(200);
$this->assertEquals(3, $response->json('data.stats.total_workers'));
}
/**
* Test employer can change password successfully.
*/
public function test_employer_can_change_password()
{
// 1. Create a matching sponsor
$sponsor = \App\Models\Sponsor::create([
'full_name' => 'Employer One',
'email' => $this->employer->email,
'mobile' => '+971509990011',
'organization_name' => 'Elite Services',
'address' => 'Dubai',
'role' => 'sponsor',
'password' => bcrypt('Password@123'),
]);
// Verify initial password hash is set
$this->employer->update([
'password' => bcrypt('Password@123')
]);
// 2. Try with wrong current password
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->postJson('/api/employers/change-password', [
'current_password' => 'WrongPassword',
'new_password' => 'NewPassword@123',
'new_password_confirmation' => 'NewPassword@123',
]);
$response->assertStatus(422)
->assertJsonValidationErrors(['current_password']);
// 3. Try with correct current password
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->postJson('/api/employers/change-password', [
'current_password' => 'Password@123',
'new_password' => 'NewPassword@123',
'new_password_confirmation' => 'NewPassword@123',
]);
$response->assertStatus(200)
->assertJson([
'success' => true,
'message' => 'Password changed successfully.'
]);
// Verify password is updated for both User and Sponsor
$this->assertTrue(\Illuminate\Support\Facades\Hash::check('NewPassword@123', $this->employer->fresh()->password));
$this->assertTrue(\Illuminate\Support\Facades\Hash::check('NewPassword@123', $sponsor->fresh()->password));
}
/**
* Test registering an employer with DD/MM/YYYY dates normalizes them to Y-m-d.
*/
public function test_employer_registration_normalizes_dates()
{
$response = $this->postJson('/api/employers/register', [
'name' => 'Sandeep Vishwakarma',
'email' => 'sandeep@example.com',
'phone' => '+971509990002',
'address' => 'Dubai, UAE',
'emirates_id' => [
'emirates_id_number' => '784-2002-4977006-4',
'name' => 'Sandeep Vishwakarma',
'date_of_birth' => '05/07/2002',
'issue_date' => '07/06/2023',
'expiry_date' => '06/06/2025',
],
]);
$response->assertStatus(201)
->assertJson([
'success' => true,
]);
$this->assertDatabaseHas('employer_profiles', [
'phone' => '+971509990002',
'emirates_id_dob' => '2002-07-05',
'emirates_id_issue_date' => '2023-06-07',
'emirates_id_expiry' => '2025-06-06',
]);
$this->assertDatabaseHas('sponsors', [
'mobile' => '+971509990002',
'emirates_id_dob' => '2002-07-05',
'emirates_id_issue_date' => '2023-06-07',
'emirates_id_expiry' => '2025-06-06',
]);
}
}