108 lines
4.5 KiB
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();
|
|
}
|
|
}
|