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