Files
GSB-Construction/tests/Feature/ContractorOnboardingTest.php

191 lines
6.4 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Modules\ContractorManagement\Models\Contractor;
use Spatie\Permission\Models\Role;
use Tests\TestCase;
class ContractorOnboardingTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
// Create required roles for tests
Role::firstOrCreate(['name' => 'admin']);
Role::firstOrCreate(['name' => 'contractor-admin']);
}
public function test_guest_can_register_as_contractor(): void
{
$response = $this->post(route('contractors.register.store'), [
'company_name' => 'Acme Builders',
'contact_person' => 'John Doe',
'email' => 'contact@acme.com',
'phone' => '12345678',
'specialization' => 'general',
'address' => '123 Acme Street',
'tax_id' => 'TX-999',
'payment_terms' => 'net_30',
'admin_name' => 'John Doe',
'admin_email' => 'john@acme.com',
'password' => 'password123',
'password_confirmation' => 'password123',
]);
$response->assertRedirect(route('login'));
$response->assertSessionHas('success');
// Verify Contractor was created as pending
$contractor = Contractor::where('email', 'contact@acme.com')->first();
$this->assertNotNull($contractor);
$this->assertEquals('pending', $contractor->status);
// Verify Admin User was created as inactive
$user = User::where('email', 'john@acme.com')->first();
$this->assertNotNull($user);
$this->assertEquals('inactive', $user->status);
$this->assertEquals($contractor->id, $user->contractor_id);
$this->assertTrue($user->hasRole('contractor-admin'));
}
public function test_inactive_contractor_admin_cannot_login(): void
{
// 1. Create a pending contractor and inactive admin user
$contractor = Contractor::create([
'company_name' => 'Acme Builders',
'contact_person' => 'John Doe',
'email' => 'contact@acme.com',
'status' => 'pending',
'payment_terms' => 'net_30',
]);
$user = User::factory()->create([
'contractor_id' => $contractor->id,
'email' => 'john@acme.com',
'password' => Hash::make('password123'),
'status' => 'inactive',
]);
// 2. Try logging in
$response = $this->post(route('login'), [
'email' => 'john@acme.com',
'password' => 'password123',
]);
// 3. Verify they are blocked and validation error is thrown
$response->assertSessionHasErrors('email');
$this->assertFalse(auth()->check());
}
public function test_platform_owner_can_approve_pending_contractor(): void
{
// 1. Create pending contractor and inactive user
$contractor = Contractor::create([
'company_name' => 'Pending Contractor LLC',
'contact_person' => 'John Doe',
'email' => 'contact@acme.com',
'status' => 'pending',
'payment_terms' => 'net_30',
]);
$user = User::factory()->create([
'contractor_id' => $contractor->id,
'status' => 'inactive',
]);
// 2. Create Platform Owner
$platformOwner = User::factory()->create([
'contractor_id' => null,
'user_type' => 'admin',
'status' => 'active',
]);
$platformOwner->assignRole('admin');
// 3. Authenticate as Platform Owner and approve
$response = $this->actingAs($platformOwner)
->post(route('contractors.approve', $contractor));
$response->assertSessionHas('success');
// 4. Verify status is active
$this->assertEquals('active', $contractor->refresh()->status);
$this->assertEquals('active', $user->refresh()->status);
}
public function test_platform_owner_can_reject_pending_contractor(): void
{
// 1. Create pending contractor and inactive user
$contractor = Contractor::create([
'company_name' => 'Rejected LLC',
'contact_person' => 'John Doe',
'email' => 'contact@acme.com',
'status' => 'pending',
'payment_terms' => 'net_30',
]);
$user = User::factory()->create([
'contractor_id' => $contractor->id,
'status' => 'inactive',
]);
// 2. Create Platform Owner
$platformOwner = User::factory()->create([
'contractor_id' => null,
'user_type' => 'admin',
'status' => 'active',
]);
$platformOwner->assignRole('admin');
// 3. Authenticate as Platform Owner and reject
$response = $this->actingAs($platformOwner)
->post(route('contractors.reject', $contractor));
$response->assertSessionHas('success');
// 4. Verify contractor and users are deleted
$this->assertNull(Contractor::find($contractor->id));
$this->assertNull(User::find($user->id));
}
public function test_non_platform_owners_cannot_access_approvals(): void
{
$contractor = Contractor::create([
'company_name' => 'Acme Builders',
'contact_person' => 'John Doe',
'email' => 'contact@acme.com',
'status' => 'pending',
'payment_terms' => 'net_30',
]);
$dummyContractor = Contractor::create([
'company_name' => 'Regular Contractor Ltd',
'contact_person' => 'Jane Doe',
'email' => 'jane@regular.com',
'status' => 'active',
'payment_terms' => 'net_30',
]);
$regularUser = User::factory()->create([
'contractor_id' => $dummyContractor->id,
'status' => 'active',
]);
// Trying to approve or reject should abort
$this->actingAs($regularUser)
->get(route('contractors.pending'))
->assertStatus(403);
$this->actingAs($regularUser)
->post(route('contractors.approve', $contractor))
->assertStatus(403);
$this->actingAs($regularUser)
->post(route('contractors.reject', $contractor))
->assertStatus(403);
}
}