215 lines
6.5 KiB
PHP
215 lines
6.5 KiB
PHP
<?php
|
|
|
|
use App\Enums\IsActive;
|
|
use App\Enums\RoleEnum;
|
|
use App\Filament\Resources\Master\Locations\Pages\ManageLocations;
|
|
use App\Models\Location;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->user = User::factory()->create(['is_active' => IsActive::ACTIVE]);
|
|
|
|
// Setup Permissions
|
|
Permission::firstOrCreate(['name' => 'ViewAny:Location', 'guard_name' => 'web']);
|
|
Permission::firstOrCreate(['name' => 'Create:Location', 'guard_name' => 'web']);
|
|
Permission::firstOrCreate(['name' => 'Update:Location', 'guard_name' => 'web']);
|
|
Permission::firstOrCreate(['name' => 'Delete:Location', 'guard_name' => 'web']);
|
|
Permission::firstOrCreate(['name' => 'Restore:Location', 'guard_name' => 'web']);
|
|
Permission::firstOrCreate(['name' => 'ForceDelete:Location', 'guard_name' => 'web']);
|
|
|
|
$this->user->givePermissionTo([
|
|
'ViewAny:Location',
|
|
'Create:Location',
|
|
'Update:Location',
|
|
'Delete:Location',
|
|
'Restore:Location',
|
|
'ForceDelete:Location',
|
|
]);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Positive Scenarios
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('can render location list page', function () {
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->assertSuccessful();
|
|
});
|
|
|
|
test('can list locations', function () {
|
|
$locations = Location::factory()->count(5)->create();
|
|
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->call('loadTable')
|
|
->assertCanSeeTableRecords($locations);
|
|
});
|
|
|
|
test('can create location', function () {
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->mountAction('create')
|
|
->setActionData([
|
|
'name' => 'Lokus Baru',
|
|
])
|
|
->callMountedAction()
|
|
->assertHasNoActionErrors();
|
|
|
|
$this->assertDatabaseHas('locations', [
|
|
'name' => 'Lokus Baru',
|
|
'is_active' => IsActive::ACTIVE->value,
|
|
]);
|
|
});
|
|
|
|
test('can edit location', function () {
|
|
$location = Location::factory()->create();
|
|
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->mountTableAction('edit', $location)
|
|
->setActionData([
|
|
'name' => 'Lokus Updated',
|
|
])
|
|
->callMountedTableAction()
|
|
->assertHasNoActionErrors();
|
|
|
|
expect($location->refresh()->name)->toBe('Lokus Updated');
|
|
});
|
|
|
|
test('can toggle is_active status', function () {
|
|
$location = Location::factory()->create(['is_active' => IsActive::INACTIVE]);
|
|
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->call('updateTableColumnState', 'is_active', $location->getKey(), true);
|
|
|
|
expect($location->refresh()->is_active)->toBe(IsActive::ACTIVE);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Negative Scenarios (Validation & Authorization)
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('cannot create location with empty name', function () {
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->mountAction('create')
|
|
->setActionData(['name' => ''])
|
|
->callMountedAction()
|
|
->assertHasActionErrors(['name' => 'required']);
|
|
});
|
|
|
|
test('cannot create location with name exceeding 50 characters', function () {
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->mountAction('create')
|
|
->setActionData(['name' => str_repeat('a', 51)])
|
|
->callMountedAction()
|
|
->assertHasActionErrors(['name' => 'max']);
|
|
});
|
|
|
|
test('unauthorized user cannot render location page', function () {
|
|
$unauthorizedUser = User::factory()->create(['is_active' => IsActive::ACTIVE]);
|
|
|
|
$this->actingAs($unauthorizedUser);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->assertForbidden();
|
|
});
|
|
|
|
test('user without create permission cannot see create action', function () {
|
|
$viewOnlyUser = User::factory()->create(['is_active' => IsActive::ACTIVE]);
|
|
$viewOnlyUser->givePermissionTo('ViewAny:Location');
|
|
$location = Location::factory()->create();
|
|
|
|
$this->actingAs($viewOnlyUser);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->assertActionHidden('create')
|
|
->assertTableActionHidden('edit', $location);
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Soft Delete Scenarios
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
test('can delete location', function () {
|
|
$location = Location::factory()->create();
|
|
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->callTableAction('delete', $location);
|
|
|
|
$this->assertSoftDeleted($location);
|
|
});
|
|
|
|
test('can restore deleted location', function () {
|
|
$roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']);
|
|
$this->user->assignRole($roleDev);
|
|
|
|
$location = Location::factory()->create(['deleted_at' => now()]);
|
|
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->filterTable('trashed', 'with')
|
|
->callTableAction('restore', $location);
|
|
|
|
$this->assertDatabaseHas('locations', [
|
|
'id' => $location->id,
|
|
'deleted_at' => null,
|
|
]);
|
|
});
|
|
|
|
test('can force delete location', function () {
|
|
$roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']);
|
|
$this->user->assignRole($roleDev);
|
|
|
|
$location = Location::factory()->create(['deleted_at' => now()]);
|
|
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->filterTable('trashed', 'only')
|
|
->callTableAction('forceDelete', $location);
|
|
|
|
$this->assertDatabaseMissing('locations', ['id' => $location->id]);
|
|
});
|
|
|
|
test('trashed filter visibility depends on developer role', function () {
|
|
$roleAdmin = Role::firstOrCreate(['name' => RoleEnum::ADMINISTRATOR->value, 'guard_name' => 'web']);
|
|
$this->user->assignRole($roleAdmin);
|
|
|
|
$this->actingAs($this->user);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->assertTableFilterHidden('trashed');
|
|
|
|
$roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']);
|
|
$this->user->assignRole($roleDev);
|
|
|
|
Livewire::test(ManageLocations::class)
|
|
->assertTableFilterVisible('trashed');
|
|
});
|