feat: phase 5 — complaints with ownership-guarded resolution and activity logging

This commit is contained in:
sean
2026-08-25 19:14:29 +07:00
parent 029a4a21f8
commit 28937a786e
3 changed files with 461 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
<?php
namespace Tests\Feature\Complaints;
use App\Filament\Pages\Transactions\Complaints as ComplaintsPage;
use App\Models\User;
use App\Services\ComplaintService;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Validation\ValidationException;
use Livewire\Livewire;
use Tests\Support\InsForgeFake;
use Tests\TestCase;
class ComplaintTest extends TestCase
{
private const CUSTOMER_ID = 'cccccccc-0000-0000-0000-000000000001';
protected function setUp(): void
{
parent::setUp();
InsForgeFake::reset();
InsForgeFake::fakeRest();
InsForgeFake::seed('customers', [
'id' => self::CUSTOMER_ID,
'customer_code' => 'CUST-0001',
'name' => 'Andi',
]);
}
private function actor(string $role, string $suffix = '0001'): User
{
$user = new User;
$user->forceFill([
'id' => "eeee7777-0000-0000-0000-{$role}{$suffix}",
'name' => ucfirst($role),
'email' => "{$role}@beraspro.test",
'role' => $role,
'is_active' => true,
]);
return $user;
}
private function seedComplaint(array $overrides = []): array
{
$row = array_merge([
'id' => 'bbbb8888-0000-0000-0000-000000000001',
'complaint_number' => 'CMP-20260825-0001',
'customer_id' => self::CUSTOMER_ID,
'complaint_date' => '2026-08-25',
'category' => 'product',
'description' => 'Beras hitam',
'status' => ComplaintService::STATUS_OPEN,
'priority' => 'high',
'created_by' => $this->actor('operator')->id,
'customers' => ['code' => 'CUST-0001', 'name' => 'Andi'],
], $overrides);
InsForgeFake::seed('complaints', $row);
return $row;
}
public function test_create_generates_number_and_log(): void
{
$result = app(ComplaintService::class)->createComplaint([
'customer_id' => self::CUSTOMER_ID,
'description' => 'Kemasan rusak',
'category' => 'product',
'priority' => 'low',
], $this->actor('operator'));
$this->assertSame('CMP-'.now()->format('Ymd').'-0001', $result['complaint_number']);
$stored = array_values(InsForgeFake::$store['complaints'])[0];
$this->assertSame(ComplaintService::STATUS_OPEN, $stored['status']);
$log = end(InsForgeFake::$store['activity_logs']);
$this->assertSame('complaint_created', $log['action']);
}
public function test_creator_can_resolve_own_complaint(): void
{
$creator = $this->actor('operator');
$complaint = $this->seedComplaint(['created_by' => $creator->id]);
app(ComplaintService::class)->resolve($complaint['id'], 'ganti produk baru', $creator);
$stored = InsForgeFake::$store['complaints'][$complaint['id']];
$this->assertSame(ComplaintService::STATUS_RESOLVED, $stored['status']);
$this->assertSame('ganti produk baru', $stored['resolution']);
$this->assertNotNull($stored['resolved_at']);
}
public function test_other_operator_cannot_resolve(): void
{
$complaint = $this->seedComplaint();
$this->expectException(AuthorizationException::class);
app(ComplaintService::class)->resolve($complaint['id'], 'coba tutup', $this->actor('operator', '9999'));
}
public function test_admin_can_resolve_any_complaint(): void
{
$complaint = $this->seedComplaint();
app(ComplaintService::class)->resolve($complaint['id'], 'direfund', $this->actor('admin'));
$this->assertSame(ComplaintService::STATUS_RESOLVED, InsForgeFake::$store['complaints'][$complaint['id']]['status']);
}
public function test_already_resolved_cannot_be_resolved_again(): void
{
$complaint = $this->seedComplaint(['status' => ComplaintService::STATUS_RESOLVED, 'resolution' => 'ok']);
$this->expectException(ValidationException::class);
app(ComplaintService::class)->resolve($complaint['id'], 'lagi', $this->actor('admin'));
}
public function test_page_renders_and_shows_complaint(): void
{
$this->actingAs($this->actor('operator'));
$this->seedComplaint();
Livewire::test(ComplaintsPage::class)
->assertSuccessful()
->assertSee('CMP-20260825-0001')
->assertSee('Beras hitam');
}
public function test_close_action_hidden_for_non_owner_operator(): void
{
$user = $this->actor('operator', '9999');
$this->actingAs($user);
$complaint = $this->seedComplaint();
Livewire::test(ComplaintsPage::class)
->assertSuccessful()
->assertDontSeeHtml('wire:key="writable-actions-tutup"');
}
}