From 635542fac43a0003753e98b6d95f23db2234b6a0 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Thu, 30 Apr 2026 08:29:01 +0700 Subject: [PATCH] docs: add testing guidelines for feature tests with Pest PHP --- tests/testing_guidelines.md | 137 ++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 tests/testing_guidelines.md diff --git a/tests/testing_guidelines.md b/tests/testing_guidelines.md new file mode 100644 index 0000000..19477a0 --- /dev/null +++ b/tests/testing_guidelines.md @@ -0,0 +1,137 @@ +# Testing Guidelines - Feature Tests + +Dokumentasi ini merangkum aturan dan pola standard dalam pembuatan feature test di proyek ini. Semua test baru (misal: module Order) **harus** mengikuti struktur ini untuk menjaga konsistensi. + +## 1. Teknologi & Lokasi +- **Framework**: [Pest PHP](https://pestphp.com/) +- **Lokasi**: `tests/Feature/Admin/Master/` (atau folder yang relevan sesuai grouping menu). +- **Penamaan File**: `[Name]Test.php` (Contoh: `OrderTest.php`). + +## 2. Struktur Dasar (Describe Blocks) +Setiap file test harus dibagi menjadi minimal 3 blok `describe`: + +### A. Authorization +Digunakan untuk mengetes akses dasar (apakah sudah login dan apakah punya izin minimal untuk melihat index). +```php +describe('Order Module - Authorization', function () { + it('redirects to login when accessing order index unauthenticated', function () { + get(route('order.index'))->assertRedirect(route('login')); + }); + + it('returns 403 when user has no permission to view orders', function () { + actingAs(createUnauthorizedUser()) + ->get(route('order.index')) + ->assertStatus(403); + }); +}); +``` + +### B. Authorized Actions +Blok utama untuk mengetes fitur CRUD dan fitur spesifik lainnya. Gunakan `beforeEach` untuk setup user dengan permissions lengkap. +```php +describe('Order Module - Authorized Actions', function () { + beforeEach(function () { + $user = createAuthorizedUser([ + 'View:Order', + 'Create:Order', + 'Edit:Order', + 'Delete:Order', + 'DeleteAny:Order', + 'ToggleStatus:Order', // Jika ada status + ]); + actingAs($user); + }); + + // Test cases go here... +}); +``` + +### C. Unauthorized Actions +Mengetes restriksi akses untuk user yang sudah login tapi tidak punya permission spesifik untuk aksi tertentu. +```php +describe('Order Module - Unauthorized Actions', function () { + beforeEach(function () { + actingAs(createUnauthorizedUser()); + }); + + it('cannot store an order without permission', function () { + postJson(route('order.store'), [])->assertStatus(403); + }); + // ... dst untuk update, delete, toggleStatus +}); +``` + +## 3. Pola Testing Fitur Standard + +### Page Visits (Inertia) +Gunakan `assertInertia` untuk mengecek komponen dan ketersediaan data (props). +```php +it('can access order index page', function () { + get(route('order.index')) + ->assertOk() + ->assertInertia(fn ($page) => $page + ->component('admin/transaction/order/index') // path component + ->has('orders') // mengecek prop data + ); +}); +``` + +### Store / Update +- Gunakan `postJson` atau `patchJson`. +- Cek redirect, session success, dan keberadaan data di database. +```php +it('can store a new order', function () { + $data = [ /* dummy data */ ]; + postJson(route('order.store'), $data) + ->assertRedirect() + ->assertSessionHas('success'); + + assertDatabaseHas('orders', ['field' => 'value']); +}); +``` + +### Validation +Tes skenario input kosong atau salah format untuk memastikan `Request` bekerja. +```php +it('validates order creation', function () { + postJson(route('order.store'), []) + ->assertStatus(422) + ->assertJsonValidationErrors(['required_field']); +}); +``` + +### Delete & Bulk Delete +- Pastikan menggunakan `assertSoftDeleted` jika model menggunakan SoftDeletes. +- Untuk bulk, kirim array `ids`. +```php +it('can delete orders in bulk', function () { + $ids = Order::factory()->count(3)->create()->pluck('id')->toArray(); + deleteJson(route('order.bulkDestroy'), ['ids' => $ids]) + ->assertRedirect() + ->assertSessionHas('success'); + + foreach ($ids as $id) { + assertSoftDeleted('orders', ['id' => $id]); + } +}); +``` + +### Toggle Status +Cek perubahan nilai di database setelah request. +```php +it('can toggle order status', function () { + $order = Order::factory()->create(['is_active' => true]); + patchJson(route('order.toggleStatus', $order))->assertRedirect(); + expect($order->fresh()->is_active)->toBeFalse(); +}); +``` + +## 4. Fitur Spesifik Module (Aturan Tambahan) +Jika module memiliki fitur unik (seperti `Order` yang mungkin punya stok atau perhitungan subtotal), tambahkan test case khusus namun tetap ikuti style yang sama: +- **Relasi**: Jika menyimpan data ke tabel relasi (seperti `OrderItems`), gunakan `assertDatabaseHas` untuk tabel tersebut. +- **File Upload**: Gunakan `Storage::fake()` dan `UploadedFile::fake()`. +- **Logic Bisnis**: Jika ada logic otomatis (misal: stok berkurang), cek kondisi database sebelum dan sesudah aksi. + +## 5. Helper Functions (Tersedia di `tests/Pest.php`) +- `createAuthorizedUser(array $permissions)`: Membuat user dan memberikan permissions. +- `createUnauthorizedUser()`: Membuat user tanpa permissions tambahan.