test: Create testing guidelines for Filament resources, detailing setup, test categories, and best practices for comprehensive feature testing.
This commit is contained in:
parent
10fb1dfa04
commit
0e53ef8cc7
187
docs/testing-guidlines.md
Normal file
187
docs/testing-guidlines.md
Normal 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.
|
||||
Loading…
Reference in New Issue
Block a user