user = User::factory()->create(['is_active' => IsActive::ACTIVE]); // Setup Permissions Permission::firstOrCreate(['name' => 'ViewAny:SubClassification', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Create:SubClassification', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Update:SubClassification', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Delete:SubClassification', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'Restore:SubClassification', 'guard_name' => 'web']); Permission::firstOrCreate(['name' => 'ForceDelete:SubClassification', 'guard_name' => 'web']); $this->user->givePermissionTo([ 'ViewAny:SubClassification', 'Create:SubClassification', 'Update:SubClassification', 'Delete:SubClassification', 'Restore:SubClassification', 'ForceDelete:SubClassification', ]); }); test('can render sub-classification list page', function () { $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->assertSuccessful(); }); test('can list sub-classifications', function () { $subClassifications = SubClassification::factory()->count(5)->create(); $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->call('loadTable') ->assertCanSeeTableRecords($subClassifications); }); test('can create sub-classification', function () { $classification = Classification::factory()->create(['is_active' => IsActive::ACTIVE]); $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->mountAction('create') ->setActionData([ 'classification_id' => $classification->id, 'name' => 'Sub Klasifikasi Baru', ]) ->callMountedAction() ->assertHasNoActionErrors(); $this->assertDatabaseHas('sub_classifications', [ 'classification_id' => $classification->id, 'name' => 'Sub Klasifikasi Baru', ]); }); test('cannot create sub-classification with invalid data', function () { $this->actingAs($this->user); // Empty name Livewire::test(ManageSubClassifications::class) ->mountAction('create') ->setActionData(['name' => '', 'classification_id' => null]) ->callMountedAction() ->assertHasActionErrors(['name' => 'required', 'classification_id' => 'required']); // Non-existent classification Livewire::test(ManageSubClassifications::class) ->mountAction('create') ->setActionData(['name' => 'Valid Name', 'classification_id' => 999999]) ->callMountedAction() ->assertHasActionErrors(['classification_id']); }); test('can edit sub-classification', function () { $subClassification = SubClassification::factory()->create(); $newClassification = Classification::factory()->create(['is_active' => IsActive::ACTIVE]); $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->mountTableAction('edit', $subClassification) ->setActionData([ 'classification_id' => $newClassification->id, 'name' => 'Sub Klasifikasi Updated', ]) ->callMountedTableAction() ->assertHasNoActionErrors(); expect($subClassification->refresh()->name)->toBe('Sub Klasifikasi Updated'); expect($subClassification->classification_id)->toBe($newClassification->id); }); test('can toggle is_active status', function () { $subClassification = SubClassification::factory()->create(['is_active' => IsActive::INACTIVE]); $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->call('updateTableColumnState', 'is_active', $subClassification->getKey(), true); expect($subClassification->refresh()->is_active)->toBe(IsActive::ACTIVE); }); test('unauthorized user cannot render sub-classification page', function () { $unauthorizedUser = User::factory()->create(['is_active' => IsActive::ACTIVE]); $this->actingAs($unauthorizedUser); Livewire::test(ManageSubClassifications::class) ->assertForbidden(); }); test('user without update permission cannot see edit action', function () { $viewOnlyUser = User::factory()->create(['is_active' => IsActive::ACTIVE]); $viewOnlyUser->givePermissionTo('ViewAny:SubClassification'); $subClassification = SubClassification::factory()->create(); $this->actingAs($viewOnlyUser); Livewire::test(ManageSubClassifications::class) ->assertTableActionHidden('edit', $subClassification); }); test('can delete sub-classification', function () { $subClassification = SubClassification::factory()->create(); $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->callTableAction('delete', $subClassification); $this->assertSoftDeleted($subClassification); }); test('can restore deleted sub-classification', function () { $roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']); $this->user->assignRole($roleDev); $subClassification = SubClassification::factory()->create(['deleted_at' => now()]); $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->filterTable('trashed', 'with') ->callTableAction('restore', $subClassification); $this->assertDatabaseHas('sub_classifications', [ 'id' => $subClassification->id, 'deleted_at' => null, ]); }); test('can force delete sub-classification', function () { $roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']); $this->user->assignRole($roleDev); $subClassification = SubClassification::factory()->create(['deleted_at' => now()]); $this->actingAs($this->user); Livewire::test(ManageSubClassifications::class) ->filterTable('trashed', 'only') ->callTableAction('forceDelete', $subClassification); $this->assertDatabaseMissing('sub_classifications', ['id' => $subClassification->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(ManageSubClassifications::class) ->assertTableFilterHidden('trashed'); $roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value, 'guard_name' => 'web']); $this->user->assignRole($roleDev); Livewire::test(ManageSubClassifications::class) ->assertTableFilterVisible('trashed'); });