migrant-web/tests/Feature/EmployerSubscriptionUpgradeTest.php

260 lines
9.8 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\Plan;
use App\Models\Subscription;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class EmployerSubscriptionUpgradeTest extends TestCase
{
use RefreshDatabase;
protected $employer;
protected function setUp(): void
{
parent::setUp();
// Create employer
$this->employer = User::create([
'name' => 'Employer User',
'email' => 'employer@example.com',
'password' => bcrypt('password'),
'role' => 'employer',
'subscription_status' => 'expired',
'subscription_expires_at' => null,
]);
}
public function test_purchase_when_no_active_subscription_activates_immediately()
{
$response = $this->actingAs($this->employer)->postJson(route('employer.subscription.purchase'), [
'plan_id' => 'premium',
]);
$response->assertStatus(200);
$response->assertJsonPath('success', true);
// Assert subscription is active
$this->assertDatabaseHas('subscriptions', [
'user_id' => $this->employer->id,
'plan_id' => 'premium',
'status' => 'active',
]);
$this->employer->refresh();
$this->assertEquals('active', $this->employer->subscription_status);
$this->assertNotNull($this->employer->subscription_expires_at);
}
public function test_purchase_when_active_subscription_exists_queues_pending()
{
// 1. Create active subscription
$activeSub = Subscription::create([
'user_id' => $this->employer->id,
'plan_id' => 'basic',
'amount_aed' => 99.00,
'starts_at' => now(),
'expires_at' => now()->addDays(30),
'status' => 'active',
]);
$this->employer->update([
'subscription_status' => 'active',
'subscription_expires_at' => $activeSub->expires_at,
]);
// 2. Purchase another subscription
$response = $this->actingAs($this->employer)->postJson(route('employer.subscription.purchase'), [
'plan_id' => 'premium',
]);
$response->assertStatus(200);
// Assert new subscription is pending and queued chronologically
$this->assertDatabaseHas('subscriptions', [
'user_id' => $this->employer->id,
'plan_id' => 'premium',
'status' => 'pending',
'starts_at' => $activeSub->expires_at,
]);
// User should still have active status with previous expiry
$this->employer->refresh();
$this->assertEquals('active', $this->employer->subscription_status);
$this->assertEquals($activeSub->expires_at->toDateTimeString(), $this->employer->subscription_expires_at->toDateTimeString());
}
public function test_pending_subscription_activates_when_active_expires()
{
// 1. Create active subscription expiring in the past
$expiredSub = Subscription::create([
'user_id' => $this->employer->id,
'plan_id' => 'basic',
'amount_aed' => 99.00,
'starts_at' => now()->subDays(40),
'expires_at' => now()->subDays(10), // expired 10 days ago
'status' => 'active',
]);
// 2. Create pending subscription queued to start when expired sub ended
$pendingSub = Subscription::create([
'user_id' => $this->employer->id,
'plan_id' => 'premium',
'amount_aed' => 199.00,
'starts_at' => $expiredSub->expires_at,
'expires_at' => $expiredSub->expires_at->copy()->addDays(30),
'status' => 'pending',
]);
$this->employer->update([
'subscription_status' => 'active',
'subscription_expires_at' => $expiredSub->expires_at,
]);
// 3. Trigger check and activate routine
User::checkAndActivatePendingSubscriptions($this->employer->id);
// 4. Assert expired sub is set to expired
$expiredSub->refresh();
$this->assertEquals('expired', $expiredSub->status);
// 5. Assert pending sub is now active
$pendingSub->refresh();
$this->assertEquals('active', $pendingSub->status);
// 6. Assert user is active and has new expires_at set starting from now
$this->employer->refresh();
$this->assertEquals('active', $this->employer->subscription_status);
$this->assertTrue($this->employer->subscription_expires_at > now());
}
public function test_expired_subscription_restricts_access_and_redirects_to_subscription_plans()
{
// 1. Create expired subscription
Subscription::create([
'user_id' => $this->employer->id,
'plan_id' => 'basic',
'amount_aed' => 99.00,
'starts_at' => now()->subDays(40),
'expires_at' => now()->subDays(10), // expired 10 days ago
'status' => 'expired',
]);
$this->employer->update([
'subscription_status' => 'expired',
'subscription_expires_at' => now()->subDays(10),
]);
// 2. Try to view dashboard - should redirect to subscription
$response = $this->actingAs($this->employer)
->withSession(['user' => $this->employer])
->get('/employer/dashboard');
$response->assertRedirect(route('employer.subscription'));
// 3. Accessing subscription page itself is allowed
$subResponse = $this->actingAs($this->employer)
->withSession(['user' => $this->employer])
->get(route('employer.subscription'));
$subResponse->assertStatus(200);
}
public function test_contact_limit_blocks_new_conversations_but_allows_existing_ones()
{
// 1. Create a custom plan with max_contact_people = 2
Plan::create([
'id' => 'test-plan-2',
'name' => 'Test Plan 2',
'price' => 10.00,
'duration' => 'Monthly',
'features' => ['Feature 1'],
'max_contact_people' => 2,
'unlimited_contacts' => false,
'enable_job_apply' => true,
'status' => 'Active',
]);
Subscription::create([
'user_id' => $this->employer->id,
'plan_id' => 'test-plan-2',
'amount_aed' => 10.00,
'starts_at' => now(),
'expires_at' => now()->addDays(30),
'status' => 'active',
]);
$this->employer->update([
'subscription_status' => 'active',
'subscription_expires_at' => now()->addDays(30),
]);
// Create 3 workers
$worker1 = \App\Models\Worker::create(['name' => 'Worker One', 'email' => 'w1@ex.com', 'phone' => '1111111', 'nationality' => 'Indian', 'status' => 'active', 'passport_status' => 'valid', 'age' => 25, 'salary' => 1500, 'availability' => 'Immediate', 'experience' => '2 Years', 'religion' => 'Christian', 'bio' => 'Helper']);
$worker2 = \App\Models\Worker::create(['name' => 'Worker Two', 'email' => 'w2@ex.com', 'phone' => '2222222', 'nationality' => 'Indian', 'status' => 'active', 'passport_status' => 'valid', 'age' => 26, 'salary' => 1600, 'availability' => 'Immediate', 'experience' => '2 Years', 'religion' => 'Christian', 'bio' => 'Helper']);
$worker3 = \App\Models\Worker::create(['name' => 'Worker Three', 'email' => 'w3@ex.com', 'phone' => '3333333', 'nationality' => 'Indian', 'status' => 'active', 'passport_status' => 'valid', 'age' => 27, 'salary' => 1700, 'availability' => 'Immediate', 'experience' => '2 Years', 'religion' => 'Christian', 'bio' => 'Helper']);
// 2. Contact worker 1 -> Allowed
$response1 = $this->actingAs($this->employer)
->withSession(['user' => $this->employer])
->get(route('employer.messages.start', ['workerId' => $worker1->id]));
$response1->assertRedirect();
$this->assertDatabaseHas('conversations', [
'employer_id' => $this->employer->id,
'worker_id' => $worker1->id,
]);
// 3. Contact worker 2 -> Allowed
$response2 = $this->actingAs($this->employer)
->withSession(['user' => $this->employer])
->get(route('employer.messages.start', ['workerId' => $worker2->id]));
$response2->assertRedirect();
$this->assertDatabaseHas('conversations', [
'employer_id' => $this->employer->id,
'worker_id' => $worker2->id,
]);
// 4. Contact worker 3 -> Blocked (limit reached)
$response3 = $this->actingAs($this->employer)
->withSession(['user' => $this->employer])
->get(route('employer.messages.start', ['workerId' => $worker3->id]));
$response3->assertRedirect(route('employer.subscription'));
$response3->assertSessionHas('error');
$this->assertDatabaseMissing('conversations', [
'employer_id' => $this->employer->id,
'worker_id' => $worker3->id,
]);
// 5. Contact worker 1 again -> Allowed (already contacted)
$response4 = $this->actingAs($this->employer)
->withSession(['user' => $this->employer])
->get(route('employer.messages.start', ['workerId' => $worker1->id]));
$response4->assertRedirect();
}
public function test_api_expired_subscription_blocks_access()
{
$token = 'test_api_token_123';
$this->employer->update([
'api_token' => $token,
'subscription_status' => 'expired',
]);
// Access API dashboard -> Should get 403 Forbidden
$response = $this->getJson('/api/employers/dashboard', [
'Authorization' => 'Bearer ' . $token,
]);
$response->assertStatus(403);
$response->assertJsonPath('success', false);
}
}