parfum/tests/Feature/Livewire/Studio/Catalog/Perfume/IndexTest.php
Yoga Pangestu 81a9753620 feat(perfume. bottle): implementasi testing
- kasih return type
- ubah array to collection di audit
- mengubah waktu refresh tabel menjadi 30 detik
2025-12-11 11:15:59 +07:00

119 lines
3.5 KiB
PHP

<?php
use App\Models\Employee;
use App\Models\Perfume;
use App\Models\User;
use Database\Seeders\RolePermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Spatie\Permission\Models\Role;
uses(RefreshDatabase::class);
beforeEach(function () {
$this->seed(RolePermissionSeeder::class);
$this->user = User::factory()
->active()
->has(Employee::factory())
->create();
$this->ownerRole = Role::where('name', 'Owner')->first();
$this->user->roles()->attach($this->ownerRole->id);
});
function mountPerfumeIndexComponent(User $user)
{
return Livewire::actingAs($user)->test(\App\Livewire\Studio\Catalog\Perfume\Index::class);
}
/*
|--------------------------------------------------------------------------
| Index Component Rendering & Basic Functionality
|--------------------------------------------------------------------------
*/
it('renders perfume index page successfully', function () {
mountPerfumeIndexComponent($this->user)
->assertViewIs('livewire.studio.catalog.perfume.index')
->assertViewHas('pageTitle', 'Parfum');
});
it('displays perfumes correctly', function () {
Perfume::factory()->count(3)->create();
// Just check that the component renders without errors and has perfumes
$component = mountPerfumeIndexComponent($this->user);
$component->assertViewIs('livewire.studio.catalog.perfume.index');
expect(Perfume::count())->toBe(3);
});
/*
|--------------------------------------------------------------------------
| Delete Perfume Tests
|--------------------------------------------------------------------------
*/
it('deletes perfume successfully when authorized', function () {
$perfume = Perfume::factory()->create([
'name' => 'Perfume to Delete',
]);
mountPerfumeIndexComponent($this->user)
->call('delete', $perfume)
->assertHasNoErrors()
->assertDispatched('refreshDatatable');
$this->assertSoftDeleted('perfumes', [
'id' => $perfume->id,
]);
});
it('prevents perfume deletion when unauthorized', function () {
$this->ownerRole->revokePermissionTo('delete perfume');
$perfume = Perfume::factory()->create();
mountPerfumeIndexComponent($this->user)
->call('delete', $perfume)
->assertForbidden();
});
/*
|--------------------------------------------------------------------------
| Authorization Edge Cases
|--------------------------------------------------------------------------
*/
it('handles unauthorized user with revoked permissions', function () {
// Revoke all perfume permissions
$this->ownerRole->revokePermissionTo(['delete perfume']);
// Define gates to return false
Gate::define('delete perfume', fn () => false);
$perfume = Perfume::factory()->create();
// Test delete
mountPerfumeIndexComponent($this->user)
->call('delete', $perfume)
->assertForbidden();
});
it('handles user with partial permissions correctly', function () {
// Remove owner role and create a user with limited permissions
$this->user->roles()->detach();
$limitedRole = Role::create(['name' => 'Limited User']);
$this->user->roles()->attach($limitedRole->id);
// Give only some permissions but not delete
$limitedRole->givePermissionTo([]);
$perfume = Perfume::factory()->create();
// Should not be able to delete
mountPerfumeIndexComponent($this->user)
->call('delete', $perfume)
->assertForbidden();
});