Files
portal-api/tests/Feature/Api/Admin/LeadApiTest.php

108 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Api\Admin;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Modules\Lead\App\Models\Lead;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Tests\TestCase;
class LeadApiTest extends TestCase
{
use RefreshDatabase;
private const BASE = '/api/v1/administrator/leads';
private function admin(array $permissions): User
{
$role = Role::create(['name' => 'role-' . uniqid(), 'guard_name' => 'admin']);
foreach ($permissions as $name) {
$role->givePermissionTo(Permission::firstOrCreate(['name' => $name, 'guard_name' => 'admin']));
}
$admin = User::factory()->create();
$admin->assignRole($role);
return $admin;
}
public function test_crud_flow_and_email_is_normalized_and_unique(): void
{
$admin = $this->admin(['lead.view', 'lead.create', 'lead.edit', 'lead.destroy']);
$uuid = $this->actingAs($admin, 'admin')
->postJson(self::BASE, ['fullname' => 'Khách A', 'email' => ' Khach.A@Example.com ', 'status' => 'new'])
->assertCreated()
->assertJsonPath('data.email', 'khach.a@example.com')
->json('data.uuid');
$this->actingAs($admin, 'admin')
->postJson(self::BASE, ['email' => 'khach.a@example.com'])
->assertStatus(422);
$this->actingAs($admin, 'admin')
->putJson(self::BASE . "/{$uuid}", ['email' => 'khach.a@example.com', 'status' => 'contacted', 'phone' => '0901234567'])
->assertOk()
->assertJsonPath('data.status', 'contacted');
$this->actingAs($admin, 'admin')->getJson(self::BASE . '?filter=0901')->assertOk()->assertJsonPath('data.total', 1);
$this->actingAs($admin, 'admin')->getJson(self::BASE . "/{$uuid}")->assertOk()->assertJsonPath('data.phone', '0901234567');
$this->actingAs($admin, 'admin')->deleteJson(self::BASE . "/{$uuid}")->assertOk();
$this->assertSame(0, Lead::count());
}
public function test_index_filters_by_source_and_recorded_date(): void
{
$admin = $this->admin(['lead.view']);
$match = Lead::create(['email' => 'a@example.com', 'source' => 'whmcs_contact']);
Lead::create(['email' => 'b@example.com', 'source' => 'manual']);
$old = Lead::create(['email' => 'c@example.com', 'source' => 'whmcs_contact']);
$old->forceFill(['created_at' => now()->subMonth()])->saveQuietly();
$this->actingAs($admin, 'admin')
->getJson(self::BASE . '?' . http_build_query(['source' => 'whmcs_contact', 'date_from' => now()->subDay()->toDateString(), 'date_to' => now()->toDateString()]))
->assertOk()
->assertJsonPath('data.total', 1)
->assertJsonPath('data.items.0.uuid', $match->uuid);
}
public function test_permissions_are_enforced(): void
{
$viewer = $this->admin(['lead.view']);
$this->actingAs($viewer, 'admin')->getJson(self::BASE)->assertOk();
$this->actingAs($viewer, 'admin')->postJson(self::BASE, ['email' => 'x@example.com'])->assertForbidden();
$this->actingAs($viewer, 'admin')->deleteJson(self::BASE . '/' . uniqid())->assertForbidden();
}
public function test_bulk_status_and_bulk_delete_only_touch_given_uuids(): void
{
$admin = $this->admin(['lead.view', 'lead.edit', 'lead.destroy']);
$leads = collect(['a', 'b', 'c'])->map(fn ($name) => Lead::create(['email' => "{$name}@example.com"]));
$this->actingAs($admin, 'admin')
->postJson(self::BASE . '/bulk-status', ['uuids' => [$leads[0]->uuid, $leads[1]->uuid], 'status' => 'contacted'])
->assertOk()
->assertJsonPath('data.affected', 2);
$this->assertSame(2, Lead::where('status', 'contacted')->count());
$this->actingAs($admin, 'admin')
->postJson(self::BASE . '/bulk-status', ['uuids' => [$leads[2]->uuid], 'status' => 'bogus'])
->assertStatus(422);
$this->actingAs($admin, 'admin')
->postJson(self::BASE . '/bulk-delete', ['uuids' => [$leads[0]->uuid, $leads[2]->uuid]])
->assertOk()
->assertJsonPath('data.affected', 2);
$this->assertSame([$leads[1]->uuid], Lead::pluck('uuid')->all());
$this->actingAs($this->admin(['lead.view']), 'admin')
->postJson(self::BASE . '/bulk-delete', ['uuids' => [$leads[1]->uuid]])
->assertForbidden();
}
}