- Added activity logs for ticket status changes, comments, and ticket views. - Implemented `TicketStatusChangedNotification` to notify users of status updates. - Enhanced ticket list filtering with pagination, search, and status filters. - Updated UI to better handle ticket assignments, status updates, and comment notifications. - Extended tests for activity logs, unauthorized actions, status change notifications, and filtering functionalities.
189 lines
5.9 KiB
PHP
189 lines
5.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Data\Ticket\CreateTicketRequest;
|
|
use App\Enums\TicketStatusEnum;
|
|
use App\Models\{Ticket, User};
|
|
use App\Services\TicketService;
|
|
use Database\Seeders\DatabaseSeeder;
|
|
use Livewire\Livewire;
|
|
|
|
beforeEach(function (): void {
|
|
$this->seed(DatabaseSeeder::class);
|
|
});
|
|
|
|
test('anyone can search tickets by ticket id', function (): void {
|
|
$user = User::factory()->create();
|
|
$user->assignRole('user');
|
|
$this->actingAs($user);
|
|
|
|
$service = app(TicketService::class);
|
|
|
|
// Create Ticket 1
|
|
$dto1 = new CreateTicketRequest(
|
|
userId: $user->id,
|
|
connectedAppId: null,
|
|
issueCategory: 'Technical Issue',
|
|
description: 'First test ticket.',
|
|
notifiedRoleIds: [],
|
|
notifiedUserIds: [],
|
|
attachment: null,
|
|
);
|
|
$ticket1Data = $service->create($dto1);
|
|
|
|
// Create Ticket 2
|
|
$dto2 = new CreateTicketRequest(
|
|
userId: $user->id,
|
|
connectedAppId: null,
|
|
issueCategory: 'Billing Query',
|
|
description: 'Second test ticket.',
|
|
notifiedRoleIds: [],
|
|
notifiedUserIds: [],
|
|
attachment: null,
|
|
);
|
|
$ticket2Data = $service->create($dto2);
|
|
|
|
// Search by Ticket 1 code/ID using Livewire component
|
|
Livewire::test('pages::tickets.index')
|
|
->set('search', $ticket1Data->ticketId)
|
|
->assertSee($ticket1Data->ticketId)
|
|
->assertDontSee($ticket2Data->ticketId);
|
|
|
|
// Search by Ticket 2 code/ID
|
|
Livewire::test('pages::tickets.index')
|
|
->set('search', $ticket2Data->ticketId)
|
|
->assertSee($ticket2Data->ticketId)
|
|
->assertDontSee($ticket1Data->ticketId);
|
|
});
|
|
|
|
test('tickets table is paginated to 10 items per page', function (): void {
|
|
$user = User::factory()->create();
|
|
$user->assignRole('user');
|
|
$this->actingAs($user);
|
|
|
|
$service = app(TicketService::class);
|
|
|
|
// Create 12 tickets
|
|
$createdTicketIds = [];
|
|
for ($i = 1; $i <= 12; $i++) {
|
|
$dto = new CreateTicketRequest(
|
|
userId: $user->id,
|
|
connectedAppId: null,
|
|
issueCategory: 'Technical Issue',
|
|
description: "Ticket number {$i}.",
|
|
notifiedRoleIds: [],
|
|
notifiedUserIds: [],
|
|
attachment: null,
|
|
);
|
|
$ticketData = $service->create($dto);
|
|
Ticket::where('id', $ticketData->id)->update([
|
|
'created_at' => now()->addSeconds($i),
|
|
]);
|
|
$createdTicketIds[] = $ticketData->ticketId;
|
|
}
|
|
|
|
$component = Livewire::test('pages::tickets.index');
|
|
|
|
// On page 1, we should see the latest 10 tickets (since we order by latest, the last 10 created)
|
|
$page1Tickets = array_slice(array_reverse($createdTicketIds), 0, 10);
|
|
$page2Tickets = array_slice(array_reverse($createdTicketIds), 10, 2);
|
|
|
|
foreach ($page1Tickets as $id) {
|
|
$component->assertSee($id);
|
|
}
|
|
|
|
foreach ($page2Tickets as $id) {
|
|
$component->assertDontSee($id);
|
|
}
|
|
|
|
// Go to page 2
|
|
$component->call('gotoPage', 2);
|
|
|
|
foreach ($page1Tickets as $id) {
|
|
$component->assertDontSee($id);
|
|
}
|
|
|
|
foreach ($page2Tickets as $id) {
|
|
$component->assertSee($id);
|
|
}
|
|
});
|
|
|
|
test('status filtering works on paginated data at query level', function (): void {
|
|
$user = User::factory()->create();
|
|
$user->assignRole('user');
|
|
$this->actingAs($user);
|
|
|
|
$service = app(TicketService::class);
|
|
$admin = User::where('email', 'admin@example.com')->firstOrFail();
|
|
|
|
// Create Ticket 1 (Open status by default)
|
|
$dto1 = new CreateTicketRequest(
|
|
userId: $user->id,
|
|
connectedAppId: null,
|
|
issueCategory: 'Technical Issue',
|
|
description: 'Open ticket.',
|
|
notifiedRoleIds: [],
|
|
notifiedUserIds: [],
|
|
attachment: null,
|
|
);
|
|
$ticket1Data = $service->create($dto1);
|
|
|
|
// Create Ticket 2 and change its status to Hold
|
|
$dto2 = new CreateTicketRequest(
|
|
userId: $user->id,
|
|
connectedAppId: null,
|
|
issueCategory: 'Billing Query',
|
|
description: 'Hold ticket.',
|
|
notifiedRoleIds: [],
|
|
notifiedUserIds: [],
|
|
attachment: null,
|
|
);
|
|
$ticket2Data = $service->create($dto2);
|
|
|
|
// Act as admin to change status
|
|
$this->actingAs($admin);
|
|
$service->updateStatus($ticket2Data->id, TicketStatusEnum::Hold->value);
|
|
|
|
// Act as user to view
|
|
$this->actingAs($user);
|
|
|
|
// Filter by Open
|
|
Livewire::test('pages::tickets.index')
|
|
->set('statusFilter', TicketStatusEnum::Open->value)
|
|
->assertSee($ticket1Data->ticketId)
|
|
->assertDontSee($ticket2Data->ticketId);
|
|
|
|
// Filter by Hold
|
|
Livewire::test('pages::tickets.index')
|
|
->set('statusFilter', TicketStatusEnum::Hold->value)
|
|
->assertSee($ticket2Data->ticketId)
|
|
->assertDontSee($ticket1Data->ticketId);
|
|
});
|
|
|
|
test('normal user can see status filter and see custom empty state message when no results match search', function (): void {
|
|
$user = User::factory()->create();
|
|
$user->assignRole('user');
|
|
$this->actingAs($user);
|
|
|
|
// Initial load: Should see default empty state message
|
|
Livewire::test('pages::tickets.index')
|
|
->assertSee('No Support Tickets Found')
|
|
->assertDontSee('No Matching Tickets Found')
|
|
->assertSee('You have not raised any support tickets yet.');
|
|
|
|
// Search for non-existent ticket ID: Should see the custom empty search state message
|
|
Livewire::test('pages::tickets.index')
|
|
->set('search', 'TKT-NONEXISTENT-99')
|
|
->assertSee('No Matching Tickets Found')
|
|
->assertDontSee('No Support Tickets Found')
|
|
->assertSee('matching your search query or filter criteria');
|
|
|
|
// Filter by Hold status: Should see the custom empty filter state message
|
|
Livewire::test('pages::tickets.index')
|
|
->set('statusFilter', 'hold')
|
|
->assertSee('No Matching Tickets Found')
|
|
->assertDontSee('No Support Tickets Found')
|
|
->assertSee('matching your search query or filter criteria');
|
|
});
|