# 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.