- add rotating admin refresh tokens and password gates\n- expand ticket galleries, exports, and client resources\n- improve IP allocation auditing and dashboard data\n- enforce encrypted client access tokens on public routes
109 lines
4.1 KiB
PHP
109 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Api\Admin\Ticket;
|
|
|
|
use App\Models\Customer;
|
|
use App\Models\Ticket;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Str;
|
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
use Tests\TestCase;
|
|
|
|
class AdminTicketTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private Customer $customer;
|
|
|
|
private User $admin;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->customer = Customer::factory()->create(['fullname' => 'Nguyễn Văn A']);
|
|
|
|
$role = Role::create(['name' => 'support', 'guard_name' => 'admin']);
|
|
foreach (['support.view', 'support.edit'] as $permission) {
|
|
$role->givePermissionTo(Permission::firstOrCreate(['name' => $permission, 'guard_name' => 'admin']));
|
|
}
|
|
$this->admin = User::factory()->create(['username' => 'hotro']);
|
|
$this->admin->assignRole($role);
|
|
}
|
|
|
|
private function makeTicket(string $status, array $attributes = []): Ticket
|
|
{
|
|
return Ticket::create(array_merge([
|
|
'uuid' => (string) Str::uuid(),
|
|
'ticket_num' => 'TKT-' . Str::upper(Str::random(6)),
|
|
'subject' => 'Subject',
|
|
'description' => 'Description',
|
|
'status' => $status,
|
|
'room' => 'technical',
|
|
'customer_id' => $this->customer->id,
|
|
], $attributes));
|
|
}
|
|
|
|
public function test_counts_only_open_and_pending_tickets(): void
|
|
{
|
|
foreach (['open', 'open', 'pending', 'resolved', 'closed'] as $status) {
|
|
$this->makeTicket($status);
|
|
}
|
|
|
|
$this->actingAs($this->admin, 'admin')
|
|
->getJson('/api/v1/administrator/tickets/pending-count')
|
|
->assertOk()
|
|
->assertJsonPath('data.count', 3);
|
|
}
|
|
|
|
public function test_detail_returns_status_history_with_causer(): void
|
|
{
|
|
$ticket = $this->makeTicket('open');
|
|
|
|
$this->actingAs($this->admin, 'admin')
|
|
->patchJson("/api/v1/administrator/tickets/{$ticket->ticket_num}/status", ['status' => 'pending'])->assertOk();
|
|
$this->actingAs($this->admin, 'admin')
|
|
->patchJson("/api/v1/administrator/tickets/{$ticket->ticket_num}/status", ['status' => 'resolved'])->assertOk();
|
|
|
|
$history = $this->actingAs($this->admin, 'admin')
|
|
->getJson("/api/v1/administrator/tickets/{$ticket->ticket_num}")
|
|
->assertOk()
|
|
->json('data.status_history');
|
|
|
|
$this->assertSame(
|
|
[['pending', 'resolved'], ['open', 'pending'], [null, 'open']],
|
|
array_map(fn ($log) => [$log['from'], $log['to']], $history),
|
|
);
|
|
$this->assertSame('hotro', $history[0]['causer_name']);
|
|
$this->assertSame('admin', $history[0]['causer_type']);
|
|
}
|
|
|
|
public function test_exports_filtered_tickets_to_branded_excel(): void
|
|
{
|
|
$this->makeTicket('open', ['subject' => 'VPS không vào được', 'ticket_num' => 'TKT-EXPORT', 'data' => json_encode(['priority' => 'high'])]);
|
|
$this->makeTicket('closed', ['subject' => 'Ticket khác']);
|
|
|
|
$response = $this->actingAs($this->admin, 'admin')
|
|
->get('/api/v1/administrator/tickets/export?' . http_build_query(['filter' => 'vps', 'status' => ['open']]))
|
|
->assertOk();
|
|
|
|
$sheet = IOFactory::load($response->baseResponse->getFile()->getPathname())->getActiveSheet();
|
|
|
|
$this->assertSame('DANH SÁCH TICKET HỖ TRỢ', $sheet->getCell('A6')->getValue());
|
|
$this->assertSame('Mã ticket', $sheet->getCell('A7')->getValue());
|
|
$this->assertSame(
|
|
['TKT-EXPORT', 'VPS không vào được', 'Nguyễn Văn A', $this->customer->email, 'Kỹ thuật', 'Cao', 'Mở', 0],
|
|
array_slice($sheet->rangeToArray('A8:J8', null, true, false)[0], 0, 8),
|
|
);
|
|
$this->assertNull($sheet->getCell('A9')->getValue());
|
|
|
|
$this->actingAs(User::factory()->create(), 'admin')
|
|
->getJson('/api/v1/administrator/tickets/export')
|
|
->assertForbidden();
|
|
}
|
|
}
|