seed(DatabaseSeeder::class); }); test('guests cannot access the tickets page', function (): void { $this->get(route('tickets.index')) ->assertRedirect(route('login')); }); test('authenticated users with correct permissions can access the tickets page', function (): void { $user = User::factory()->create(); $user->assignRole('user'); $this->actingAs($user); $this->get(route('tickets.index')) ->assertOk() ->assertSee('Support Tickets'); }); test('submitting a support ticket creates the ticket and generates a unique ticket ID', function (): void { $user = User::factory()->create(); $user->assignRole('user'); $this->actingAs($user); $app = ConnectedApp::first(); $supportRole = Role::where('name', 'Support')->firstOrFail(); $dto = new CreateTicketRequest( userId: $user->id, connectedAppId: $app->id, issueCategory: 'Billing Query', description: 'Need assistance with billing renewal.', notifiedRoleIds: [$supportRole->id], notifiedUserIds: [], attachment: null, ); $service = app(TicketService::class); $ticketData = $service->create($dto); expect($ticketData->ticketId)->toStartWith('TKT-') ->and(mb_strlen($ticketData->ticketId))->toBe(12) ->and($ticketData->issueCategory)->toBe('Billing Query') ->and($ticketData->statusSlug)->toBe(TicketStatusEnum::Open->value) ->and($ticketData->notifiedRoleNames)->toContain('Support'); $this->assertDatabaseHas('tickets', [ 'user_id' => $user->id, 'connected_app_id' => $app->id, 'issue_category' => 'Billing Query', ]); $this->assertDatabaseHas('ticket_notified_roles', [ 'ticket_id' => $ticketData->id, 'role_id' => $supportRole->id, ]); }); test('submitting a ticket with category Others requires at least 20 characters for description', function (): void { $user = User::factory()->create(); $user->assignRole('user'); $this->actingAs($user); $supportRole = Role::where('name', 'Support')->firstOrFail(); // Test Validation Failure via Livewire component form object Livewire::test('pages::tickets.index') ->set('form.issueCategory', 'Others') ->set('form.description', 'Short desc') ->set('form.routingType', 'role') ->set('form.notifiedRoleIds', [$supportRole->id]) ->call('saveTicket') ->assertHasErrors(['form.description' => 'min']); }); test('attaching a file for Others category uploads and stores the file', function (): void { Storage::fake('public'); $user = User::factory()->create(); $user->assignRole('user'); $this->actingAs($user); $supportRole = Role::where('name', 'Support')->firstOrFail(); $file = UploadedFile::fake()->create('screenshot.png', 500); $dto = new CreateTicketRequest( userId: $user->id, connectedAppId: null, issueCategory: 'Others', description: 'A very detailed query containing more than twenty characters.', notifiedRoleIds: [$supportRole->id], notifiedUserIds: [], attachment: $file, ); $service = app(TicketService::class); $ticketData = $service->create($dto); $this->assertDatabaseHas('ticket_attachments', [ 'file_name' => 'screenshot.png', 'mime_type' => 'image/png', ]); expect(count($ticketData->attachments))->toBe(1); Storage::disk('public')->assertExists($ticketData->attachments[0]['file_path']); }); test('notification routing to a specific user triggers notification to that user', function (): void { Notification::fake(); $user = User::factory()->create(); $user->assignRole('user'); $this->actingAs($user); $adminUser = User::where('email', 'admin@example.com')->firstOrFail(); $dto = new CreateTicketRequest( userId: $user->id, connectedAppId: null, issueCategory: 'Technical Issue', description: 'SSO log-in error.', notifiedRoleIds: [], notifiedUserIds: [$adminUser->id], attachment: null, ); $service = app(TicketService::class); $service->create($dto); Notification::assertSentTo( $adminUser, TicketRaisedNotification::class ); }); test('notification routing to multiple roles triggers notifications to all users assigned to those roles', function (): void { Notification::fake(); $user = User::factory()->create(); $user->assignRole('user'); $this->actingAs($user); $supportRole = Role::where('name', 'Support')->firstOrFail(); $managerRole = Role::where('name', 'Manager')->firstOrFail(); // Create a support user $supportUser = User::factory()->create(); $supportUser->assignRole($supportRole); // Create a manager user $managerUser = User::factory()->create(); $managerUser->assignRole($managerRole); $dto = new CreateTicketRequest( userId: $user->id, connectedAppId: null, issueCategory: 'Service Extension', description: 'Requesting 3 days trial extension.', notifiedRoleIds: [$supportRole->id, $managerRole->id], notifiedUserIds: [], attachment: null, ); $service = app(TicketService::class); $service->create($dto); Notification::assertSentTo( [$supportUser, $managerUser], TicketRaisedNotification::class ); });