create(); $project = Project::factory()->create(['key' => 'CORE']); $team = Team::factory()->create(); app(InitializeProjectTicketMetadata::class)->handle($project); $boardColumn = BoardColumn::factory()->for($project)->create([ 'name' => 'In progress', ]); TicketStatus::factory()->for($project)->for($boardColumn)->create([ 'name' => 'In progress', ]); $this->syncProjectPermissions($project, $user, ['admin']); $expectedSectionProps = [ 'general' => 'sourceTemplates', 'board' => 'boardColumns', 'metadata' => 'ticketTypes', 'repositories' => 'repositoryConnections', 'notifications' => 'notificationActions', 'access' => 'teams', ]; foreach ($expectedSectionProps as $section => $expectedProp) { $this->actingAs($user) ->get(route('projects.settings.index', [ 'project' => $project, 'section' => $section, ])) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('projects/Settings') ->where('activeSection', $section) ->where('project.id', $project->id) ->has("sectionData.{$expectedProp}"), ); } } public function test_missing_and_invalid_sections_fall_back_to_general(): void { $user = User::factory()->create(); $project = Project::factory()->create(); $this->syncProjectPermissions($project, $user, ['admin']); foreach ([null, 'unknown'] as $section) { $parameters = ['project' => $project]; if ($section !== null) { $parameters['section'] = $section; } $this->actingAs($user) ->get(route('projects.settings.index', $parameters)) ->assertOk() ->assertInertia(fn (Assert $page) => $page ->component('projects/Settings') ->where('activeSection', 'general') ->has('sectionData.sourceTemplates'), ); } } public function test_users_without_project_admin_permission_cannot_open_settings(): void { $user = User::factory()->create(); $project = Project::factory()->create(); $this->syncProjectPermissions($project, $user, ['view']); $this->actingAs($user) ->get(route('projects.settings.index', $project)) ->assertForbidden(); } public function test_repository_providers_are_not_queried_outside_the_repository_section(): void { Http::preventStrayRequests(); $user = User::factory()->create(); $project = Project::factory()->create(); UserGitConnection::factory()->for($user)->create([ 'base_url' => 'https://git.example.test', 'provider' => GitProviderKey::Gitea, ]); $this->syncProjectPermissions($project, $user, ['admin']); $this->actingAs($user) ->get(route('projects.settings.index', [ 'project' => $project, 'section' => 'general', ])) ->assertOk(); Http::assertNothingSent(); } public function test_legacy_settings_urls_redirect_to_the_matching_section(): void { $user = User::factory()->create(); $project = Project::factory()->create(); $this->syncProjectPermissions($project, $user, ['admin']); $legacyRoutes = [ 'projects.settings.general' => 'general', 'projects.settings.board' => 'board', 'projects.settings.metadata' => 'metadata', 'projects.settings.repositories' => 'repositories', 'projects.settings.notifications' => 'notifications', 'projects.access' => 'access', ]; foreach ($legacyRoutes as $legacyRoute => $section) { $this->actingAs($user) ->get(route($legacyRoute, $project)) ->assertRedirect(route('projects.settings.index', [ 'project' => $project, 'section' => $section, ])); } } }