get(route('dashboard')); $response->assertRedirect(route('login')); } public function test_authenticated_users_see_an_empty_dashboard_without_assigned_tickets(): void { $user = User::factory()->create(); $this->actingAs($user); $this->get(route('dashboard')) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('Dashboard') ->has('assignedTicketsByProject', 0)); } public function test_dashboard_only_contains_the_users_tickets_from_visible_projects(): void { $user = User::factory()->create(); $otherUser = User::factory()->create(); $directProject = Project::factory()->create([ 'key' => 'WEB', 'name' => 'Web platform', ]); $teamProject = Project::factory()->create([ 'key' => 'OPS', 'name' => 'Operations', ]); $hiddenProject = Project::factory()->create([ 'key' => 'SEC', 'name' => 'Private security', ]); $team = Team::factory()->create(); $team->users()->attach($user); $this->syncProjectPermissions($directProject, $user, ['view']); $this->syncProjectPermissions($teamProject, $team, ['view']); Ticket::factory()->create([ 'assignee_user_id' => $user->id, 'project_id' => $directProject->id, 'sequence_number' => 1, 'ticket_key' => 'WEB-1', 'title' => 'Older assigned ticket', ]); Ticket::factory()->create([ 'assignee_user_id' => $user->id, 'project_id' => $directProject->id, 'sequence_number' => 2, 'ticket_key' => 'WEB-2', 'title' => 'Newest assigned ticket', ]); Ticket::factory()->create([ 'assignee_user_id' => $user->id, 'project_id' => $teamProject->id, 'sequence_number' => 1, 'ticket_key' => 'OPS-1', 'title' => 'Team-visible assigned ticket', ]); Ticket::factory()->create([ 'assignee_user_id' => $otherUser->id, 'project_id' => $directProject->id, 'sequence_number' => 3, 'ticket_key' => 'WEB-3', 'title' => 'Another users ticket', ]); Ticket::factory()->create([ 'assignee_user_id' => $user->id, 'project_id' => $hiddenProject->id, 'sequence_number' => 1, 'ticket_key' => 'SEC-1', 'title' => 'Hidden project ticket', ]); $this->actingAs($user) ->get(route('dashboard')) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('Dashboard') ->has('assignedTicketsByProject', 2) ->where('assignedTicketsByProject.0.project.id', $teamProject->id) ->has('assignedTicketsByProject.0.tickets', 1) ->where('assignedTicketsByProject.0.tickets.0.ticket_key', 'OPS-1') ->where('assignedTicketsByProject.1.project.id', $directProject->id) ->has('assignedTicketsByProject.1.tickets', 2) ->where('assignedTicketsByProject.1.tickets.0.ticket_key', 'WEB-2') ->where('assignedTicketsByProject.1.tickets.1.ticket_key', 'WEB-1')); } public function test_dashboard_presentation_uses_real_data_and_handles_empty_state(): void { $process = new Process(['node', 'tests/Fixtures/dashboard.mjs'], base_path()); $process->setTimeout(60); $process->run(); $this->assertTrue($process->isSuccessful(), $process->getOutput().$process->getErrorOutput()); $this->assertStringContainsString('Dashboard behavior checks passed.', $process->getOutput()); } }