test: Create testing guidelines for Filament resources, detailing setup, test categories, and best practices for comprehensive feature testing.

This commit is contained in:
Yoga Pangestu 2026-03-18 01:09:26 +07:00
parent 10fb1dfa04
commit 0e53ef8cc7

187
docs/testing-guidlines.md Normal file
View File

@ -0,0 +1,187 @@
# Panduan Pengujian (Testing Guidelines) Filament Resource
Dokumen ini berisi standar dan pola pengujian untuk semua Filament Resource dalam aplikasi ini menggunakan **Pest** dan **Livewire Test Utility**.
---
## 1. Persiapan (Setup)
Setiap file test harus menggunakan trait `RefreshDatabase` dan menyiapkan environment di dalam blok `beforeEach`.
### Komponen Wajib Setup:
- **User**: Buat user aktif menggunakan factory.
- **Permissions**: Daftarkan permission yang relevan dengan Resource (format: `Action:Model`).
- **Role**: Assign permission ke user tersebut.
```php
uses(RefreshDatabase::class);
beforeEach(function () {
$this->user = User::factory()->create(['is_active' => IsActive::ACTIVE]);
// Contoh untuk Resource 'Post'
$permissions = [
'ViewAny:Post',
'Create:Post',
'Update:Post',
'Delete:Post',
'Restore:Post',
'ForceDelete:Post',
];
foreach ($permissions as $permission) {
Permission::firstOrCreate(['name' => $permission, 'guard_name' => 'web']);
}
$this->user->givePermissionTo($permissions);
});
```
---
## 2. Kategori Pengujian
### A. Rendering & Otorisasi
Memastikan halaman dapat diakses oleh user yang berhak dan ditolak untuk yang tidak berhak.
- **Positif**: `assertSuccessful()`.
- **Negatif**: `assertForbidden()`.
```php
test('halaman list dapat diakses', function () {
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)->assertSuccessful();
});
test('user tanpa akses ditolak mengakses halaman', function () {
$guest = User::factory()->create();
$this->actingAs($guest);
Livewire::test(ManagePosts::class)->assertForbidden();
});
```
### B. Menampilkan Data (Listing)
Memastikan tabel menampilkan data yang sesuai dan filter berfungsi (jika ada).
```php
test('dapat menampilkan daftar data', function () {
$posts = Post::factory()->count(3)->create();
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)
->call('loadTable') // Jika menggunakan deferLoading
->assertCanSeeTableRecords($posts);
});
```
### C. Operasi CRUD (Create, Read, Update, Delete)
Gunakan `mountAction` untuk action di level halaman (seperti 'create') dan `mountTableAction` untuk action di baris tabel (seperti 'edit').
```php
// Create
test('dapat membuat data baru', function () {
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)
->mountAction('create')
->setActionData(['title' => 'Judul Baru'])
->callMountedAction()
->assertHasNoActionErrors();
$this->assertDatabaseHas('posts', ['title' => 'Judul Baru']);
});
// Edit
test('dapat mengubah data', function () {
$post = Post::factory()->create();
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)
->mountTableAction('edit', $post)
->setActionData(['title' => 'Judul Update'])
->callMountedTableAction()
->assertHasNoActionErrors();
expect($post->refresh()->title)->toBe('Judul Update');
});
```
### D. Validasi Form
Uji setiap aturan validasi kritis (required, unique, max, dll).
```php
test('validasi: judul wajib diisi', function () {
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)
->mountAction('create')
->setActionData(['title' => ''])
->callMountedAction()
->assertHasActionErrors(['title' => 'required']);
});
```
### E. Soft Delete & Trash
Pengujian untuk fitur restore dan force delete biasanya membutuhkan role **Developer**.
```php
test('dapat menghapus data (soft delete)', function () {
$post = Post::factory()->create();
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)->callTableAction('delete', $post);
$this->assertSoftDeleted($post);
});
test('dapat merestore data yang dihapus', function () {
// Berikan role Developer agar bisa melihat filter 'trashed'
$roleDev = Role::firstOrCreate(['name' => RoleEnum::DEVELOPER->value]);
$this->user->assignRole($roleDev);
$post = Post::factory()->create(['deleted_at' => now()]);
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)
->filterTable('trashed', 'with')
->callTableAction('restore', $post);
$this->assertDatabaseHas('posts', ['id' => $post->id, 'deleted_at' => null]);
});
```
### F. Fitur Khusus: Filter & Toggle
Jangan lupa menguji kolom toggle dan filter kustom.
```php
// Toggle Status
test('dapat mengubah status is_active via toggle', function () {
$post = Post::factory()->create(['is_active' => false]);
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)
->call('updateTableColumnState', 'is_active', $post->id, true);
expect($post->refresh()->is_active)->toBeTrue();
});
// Filter
test('dapat memfilter data berdasarkan kategori', function () {
$postA = Post::factory()->create(['category' => 'A']);
$postB = Post::factory()->create(['category' => 'B']);
$this->actingAs($this->user);
Livewire::test(ManagePosts::class)
->filterTable('category', 'A')
->assertCanSeeTableRecords([$postA])
->assertCanNotSeeTableRecords([$postB]);
});
```
---
## 3. Praktik Terbaik (Best Practices)
1. **Granularitas**: Satu test case fokus pada satu aturan validasi atau satu alur logika.
2. **Keamanan**: Selalu sertakan test untuk user yang tidak memiliki permission (unauthorized).
3. **Clean Up**: Gunakan `RefreshDatabase` agar data antar test tidak saling mengganggu.
4. **Factory**: Pastikan factory menghasilkan data yang valid sesuai integritas database.
5. **UI State**: Gunakan `assertActionHidden()` untuk memastikan tombol (seperti 'edit' atau 'delete') benar-benar tersembunyi bagi user yang tidak punya akses.