migrant-web/tests/Feature/WorkerReviewTest.php

305 lines
10 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\Worker;
use App\Models\JobPost;
use App\Models\JobApplication;
use App\Models\EmployerReview;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class WorkerReviewTest extends TestCase
{
use RefreshDatabase;
protected $employer;
protected $worker;
protected $job;
protected function setUp(): void
{
parent::setUp();
// Create employer
$this->employer = User::create([
'name' => 'Test Employer',
'email' => 'employer@example.com',
'password' => bcrypt('password'),
'role' => 'employer',
]);
// Create worker
$this->worker = Worker::create([
'name' => 'Worker User',
'email' => 'worker@example.com',
'password' => bcrypt('password'),
'phone' => '971501234567',
'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',
]);
// Create job post
$this->job = JobPost::create([
'employer_id' => $this->employer->id,
'title' => 'Test Job',
'location' => 'Dubai',
'salary' => 2500,
'workers_needed' => 1,
'job_type' => 'Full Time',
'start_date' => now()->subMonths(4)->toDateString(),
'description' => 'Test Job Description',
'status' => 'active',
]);
}
public function test_cannot_review_without_confirmed_hire_and_joining()
{
// Act: Try to review before any job application is made
$response = $this->postJson('/api/workers/reviews', [
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 5,
'comment' => 'Great employer!',
], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(403);
$response->assertJsonPath('success', false);
$response->assertJsonPath('message', 'You can only review employers with a confirmed hire and completed joining.');
}
public function test_cannot_review_before_3_months_since_joining()
{
// Setup job application with hired status but joining_confirmed_at is only 2 months ago
JobApplication::create([
'job_id' => $this->job->id,
'worker_id' => $this->worker->id,
'status' => 'hired',
'joining_confirmed_at' => now()->subMonths(2)->toDateString(),
]);
// Act: Try to review
$response = $this->postJson('/api/workers/reviews', [
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 5,
'comment' => 'Great employer!',
], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(403);
$response->assertJsonPath('success', false);
$response->assertJsonPath('message', 'You can write a review only after 3 months from the joining date.');
}
public function test_can_review_after_3_months_since_joining()
{
// Setup job application with hired status and joining_confirmed_at 3.5 months ago
JobApplication::create([
'job_id' => $this->job->id,
'worker_id' => $this->worker->id,
'status' => 'hired',
'joining_confirmed_at' => now()->subMonths(3)->subDays(15)->toDateString(),
]);
// Act: Post review
$response = $this->postJson('/api/workers/reviews', [
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 4,
'title' => 'Fair Employer',
'comment' => 'Very good experience overall.',
], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(201);
$response->assertJsonPath('success', true);
$response->assertJsonPath('data.review.rating', 4);
$response->assertJsonPath('data.review.title', 'Fair Employer');
$response->assertJsonPath('data.review.comment', 'Very good experience overall.');
$this->assertDatabaseHas('employer_reviews', [
'worker_id' => $this->worker->id,
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 4,
'title' => 'Fair Employer',
]);
}
public function test_cannot_duplicate_reviews()
{
// Setup job application
JobApplication::create([
'job_id' => $this->job->id,
'worker_id' => $this->worker->id,
'status' => 'hired',
'joining_confirmed_at' => now()->subMonths(4)->toDateString(),
]);
// Submit first review
EmployerReview::create([
'worker_id' => $this->worker->id,
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 5,
'comment' => 'Nice',
]);
// Act: Try to submit duplicate review
$response = $this->postJson('/api/workers/reviews', [
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 4,
'comment' => 'Another review',
], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(422);
$response->assertJsonPath('success', false);
$response->assertJsonPath('message', 'You have already submitted a review for this job/employer.');
}
public function test_edit_review_within_7_days()
{
// Setup existing review created now
$review = EmployerReview::create([
'worker_id' => $this->worker->id,
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 3,
'title' => 'Initial Title',
'comment' => 'Initial Comment',
]);
// Act: Edit the review
$response = $this->putJson("/api/workers/reviews/{$review->id}", [
'rating' => 5,
'title' => 'Updated Title',
'comment' => 'Updated Comment Details',
], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$response->assertJsonPath('data.review.rating', 5);
$response->assertJsonPath('data.review.title', 'Updated Title');
$response->assertJsonPath('data.review.comment', 'Updated Comment Details');
$this->assertDatabaseHas('employer_reviews', [
'id' => $review->id,
'rating' => 5,
'title' => 'Updated Title',
]);
}
public function test_cannot_edit_review_after_7_days()
{
// Setup existing review created 8 days ago
$review = EmployerReview::create([
'worker_id' => $this->worker->id,
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 3,
'comment' => 'Initial Comment',
]);
// Force creation date to be 8 days ago
$review->created_at = now()->subDays(8);
$review->save();
// Act: Attempt to edit
$response = $this->putJson("/api/workers/reviews/{$review->id}", [
'rating' => 5,
'comment' => 'Attempted Edit',
], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(403);
$response->assertJsonPath('success', false);
$response->assertJsonPath('message', 'The 7-day edit window for this review has expired.');
}
public function test_view_and_list_reviews()
{
// Create a review
$review = EmployerReview::create([
'worker_id' => $this->worker->id,
'employer_id' => $this->employer->id,
'job_id' => $this->job->id,
'rating' => 5,
'title' => 'Awesome place',
'comment' => 'Had a wonderful time.',
]);
// 1. Get Single Review
$response = $this->getJson("/api/workers/reviews/{$review->id}", [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$response->assertJsonPath('data.review.title', 'Awesome place');
$response->assertJsonPath('data.review.rating', 5);
// 2. List Reviews
$response = $this->getJson('/api/workers/reviews', [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
$response->assertJsonCount(1, 'data.reviews');
$response->assertJsonPath('data.reviews.0.title', 'Awesome place');
}
public function test_review_with_invalid_or_missing_job_id_passes_and_saves_null()
{
// Setup job application with hired status and joining_confirmed_at 3.5 months ago
JobApplication::create([
'job_id' => $this->job->id,
'worker_id' => $this->worker->id,
'status' => 'hired',
'joining_confirmed_at' => now()->subMonths(3)->subDays(15)->toDateString(),
]);
// Act: Post review with an invalid job_id (e.g. 'invalid-id-or-empty')
$response = $this->postJson('/api/workers/reviews', [
'employer_id' => $this->employer->id,
'job_id' => 'invalid-id-or-empty',
'rating' => 4,
'title' => 'Fair Employer',
'comment' => 'Very good experience overall.',
], [
'Authorization' => 'Bearer worker_api_token'
]);
$response->assertStatus(201);
$response->assertJsonPath('success', true);
$response->assertJsonPath('data.review.job_id', null); // Resolved to null
$this->assertDatabaseHas('employer_reviews', [
'worker_id' => $this->worker->id,
'employer_id' => $this->employer->id,
'job_id' => null,
'rating' => 4,
]);
}
}