user = User::factory()->create(['is_active' => IsActive::ACTIVE]); // Setup Permissions Permission::firstOrCreate(['name' => 'ViewAny:Department', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Create:Department', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Update:Department', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Delete:Department', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Restore:Department', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'ForceDelete:Department', 'guard_name' => 'web']); $this->user->givePermissionTo([ 'ViewAny:Department', 'Create:Department', 'Update:Department', 'Delete:Department', 'Restore:Department', 'ForceDelete:Department', ]); }); /* |-------------------------------------------------------------------------- | Positive Scenarios |-------------------------------------------------------------------------- */ test('can render department list page', function () { $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->assertSuccessful(); }); test('can list departments', function () { $departments = Department::factory()->count(5)->create(); $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->call('loadTable') ->assertCanSeeTableRecords($departments); }); test('can create department', function () { $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->mountAction('create') ->setActionData([ 'name' => 'Dinas Pendidikan', 'alias' => 'Disdik', ]) ->callMountedAction() ->assertHasNoActionErrors(); $this->assertDatabaseHas('departments', [ 'name' => 'Dinas Pendidikan', 'alias' => 'Disdik', 'is_active' => IsActive::ACTIVE->value, ]); }); test('can edit department', function () { $department = Department::factory()->create(); $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->mountTableAction('edit', $department) ->setActionData([ 'name' => 'OPD Baru Updated', 'alias' => 'OPD-U', ]) ->callMountedTableAction() ->assertHasNoActionErrors(); expect($department->refresh()->name)->toBe('OPD Baru Updated'); }); test('can toggle is_active status', function () { $department = Department::factory()->create(['is_active' => IsActive::INACTIVE]); $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->call('updateTableColumnState', 'is_active', $department->getKey(), true); expect($department->refresh()->is_active)->toBe(IsActive::ACTIVE); }); /* |-------------------------------------------------------------------------- | Negative Scenarios (Validation & Authorization) |-------------------------------------------------------------------------- */ test('cannot create department with invalid data', function () { $this->actingAs($this->user); // Empty name & alias Livewire::test(ManageDepartments::class) ->mountAction('create') ->setActionData(['name' => '', 'alias' => '']) ->callMountedAction() ->assertHasActionErrors(['name' => 'required', 'alias' => 'required']); // Name exceeding 100 chars Livewire::test(ManageDepartments::class) ->mountAction('create') ->setActionData(['name' => str_repeat('a', 101), 'alias' => 'Short']) ->callMountedAction() ->assertHasActionErrors(['name' => 'max']); // Alias exceeding 20 chars Livewire::test(ManageDepartments::class) ->mountAction('create') ->setActionData(['name' => 'Valid Name', 'alias' => str_repeat('a', 21)]) ->callMountedAction() ->assertHasActionErrors(['alias' => 'max']); }); test('unauthorized user cannot render department page', function () { $unauthorizedUser = User::factory()->create(['is_active' => IsActive::ACTIVE]); $this->actingAs($unauthorizedUser); Livewire::test(ManageDepartments::class) ->assertForbidden(); }); test('user without permissions cannot see actions', function () { $viewOnlyUser = User::factory()->create(['is_active' => IsActive::ACTIVE]); $viewOnlyUser->givePermissionTo('ViewAny:Department'); $department = Department::factory()->create(); $this->actingAs($viewOnlyUser); Livewire::test(ManageDepartments::class) ->assertActionHidden('create') ->assertTableActionHidden('edit', $department); }); /* |-------------------------------------------------------------------------- | Soft Delete Scenarios |-------------------------------------------------------------------------- */ test('can delete department', function () { $department = Department::factory()->create(); $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->callTableAction('delete', $department); $this->assertSoftDeleted($department); }); test('can restore deleted department', function () { $roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']); $this->user->assignRole($roleDev); $department = Department::factory()->create(['deleted_at' => now()]); $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->filterTable('trashed', 'with') ->callTableAction('restore', $department); $this->assertDatabaseHas('departments', [ 'id' => $department->id, 'deleted_at' => null, ]); }); test('can force delete department', function () { $roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']); $this->user->assignRole($roleDev); $department = Department::factory()->create(['deleted_at' => now()]); $this->actingAs($this->user); Livewire::test(ManageDepartments::class) ->filterTable('trashed', 'only') ->callTableAction('forceDelete', $department); $this->assertDatabaseMissing('departments', ['id' => $department->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(ManageDepartments::class) ->assertTableFilterHidden('trashed'); $roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']); $this->user->assignRole($roleDev); Livewire::test(ManageDepartments::class) ->assertTableFilterVisible('trashed'); });