summaryrefslogtreecommitdiff
path: root/spec/requests/projects
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/projects')
-rw-r--r--spec/requests/projects/google_cloud/deployments_controller_spec.rb71
-rw-r--r--spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb152
-rw-r--r--spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb86
-rw-r--r--spec/requests/projects/google_cloud/service_accounts_controller_spec.rb105
-rw-r--r--spec/requests/projects/google_cloud_controller_spec.rb78
-rw-r--r--spec/requests/projects/harbor/repositories_controller_spec.rb69
-rw-r--r--spec/requests/projects/redirect_controller_spec.rb66
7 files changed, 593 insertions, 34 deletions
diff --git a/spec/requests/projects/google_cloud/deployments_controller_spec.rb b/spec/requests/projects/google_cloud/deployments_controller_spec.rb
index fd356bc61c7..7bd9609a7dc 100644
--- a/spec/requests/projects/google_cloud/deployments_controller_spec.rb
+++ b/spec/requests/projects/google_cloud/deployments_controller_spec.rb
@@ -22,13 +22,21 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
project.add_maintainer(user_maintainer)
end
- describe "Routes must be restricted behind Google OAuth2" do
+ describe "Routes must be restricted behind Google OAuth2", :snowplow do
context 'when a public request is made' do
it 'returns not found on GET request' do
urls_list.each do |url|
get url
expect(response).to have_gitlab_http_status(:not_found)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: nil
+ )
end
end
end
@@ -40,6 +48,14 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
get url
expect(response).to have_gitlab_http_status(:not_found)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: nil
+ )
end
end
end
@@ -60,7 +76,7 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
end
end
- describe 'Authorized GET project/-/google_cloud/deployments/cloud_run' do
+ describe 'Authorized GET project/-/google_cloud/deployments/cloud_run', :snowplow do
let_it_be(:url) { "#{project_google_cloud_deployments_cloud_run_path(project)}" }
before do
@@ -72,25 +88,39 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
end
it 'redirects to google_cloud home on enable service error' do
- # since GPC_PROJECT_ID is not set, enable cloud run service should return an error
-
get url
expect(response).to redirect_to(project_google_cloud_index_path(project))
+ # since GPC_PROJECT_ID is not set, enable cloud run service should return an error
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'deployments#cloud_run',
+ label: 'enable_cloud_run_error',
+ extra: { message: 'No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.',
+ status: :error },
+ project: project,
+ user: user_maintainer
+ )
end
- it 'tracks error and redirects to gcp_error' do
- mock_google_error = Google::Apis::ClientError.new('some_error')
+ it 'redirects to gcp_error' do
+ mock_gcp_error = Google::Apis::ClientError.new('some_error')
allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service|
- allow(service).to receive(:execute).and_raise(mock_google_error)
+ allow(service).to receive(:execute).and_raise(mock_gcp_error)
end
- expect(Gitlab::ErrorTracking).to receive(:track_exception).with(mock_google_error, { project_id: project.id })
-
get url
expect(response).to render_template(:gcp_error)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'deployments#cloud_run',
+ label: 'gcp_error',
+ extra: mock_gcp_error,
+ project: project,
+ user: user_maintainer
+ )
end
context 'GCP_PROJECT_IDs are defined' do
@@ -106,6 +136,14 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
get url
expect(response).to redirect_to(project_google_cloud_index_path(project))
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'deployments#cloud_run',
+ label: 'generate_pipeline_error',
+ extra: { status: :error },
+ project: project,
+ user: user_maintainer
+ )
end
it 'redirects to create merge request form' do
@@ -121,11 +159,24 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do
expect(response).to have_gitlab_http_status(:found)
expect(response.location).to include(project_new_merge_request_path(project))
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'deployments#cloud_run',
+ label: 'cloud_run_success',
+ extra: { "title": "Enable deployments to Cloud Run",
+ "description": "This merge request includes a Cloud Run deployment job in the pipeline definition (.gitlab-ci.yml).\n\nThe `deploy-to-cloud-run` job:\n* Requires the following environment variables\n * `GCP_PROJECT_ID`\n * `GCP_SERVICE_ACCOUNT_KEY`\n* Job definition can be found at: https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library\n\nThis pipeline definition has been committed to the branch ``.\nYou may modify the pipeline definition further or accept the changes as-is if suitable.\n",
+ "source_project_id": project.id,
+ "target_project_id": project.id,
+ "source_branch": nil,
+ "target_branch": project.default_branch },
+ project: project,
+ user: user_maintainer
+ )
end
end
end
- describe 'Authorized GET project/-/google_cloud/deployments/cloud_storage' do
+ describe 'Authorized GET project/-/google_cloud/deployments/cloud_storage', :snowplow do
let_it_be(:url) { "#{project_google_cloud_deployments_cloud_storage_path(project)}" }
before do
diff --git a/spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb b/spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb
new file mode 100644
index 00000000000..56474b6520d
--- /dev/null
+++ b/spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb
@@ -0,0 +1,152 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::GoogleCloud::GcpRegionsController do
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:repository) { project.repository }
+
+ let(:user_guest) { create(:user) }
+ let(:user_maintainer) { create(:user) }
+
+ RSpec.shared_examples "should track not_found event" do
+ it "tracks event" do
+ is_expected.to be(404)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: nil
+ )
+ end
+ end
+
+ RSpec.shared_examples "should track access_denied event" do
+ it "tracks event" do
+ is_expected.to be(404)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: nil
+ )
+ end
+ end
+
+ RSpec.shared_examples "should track feature_flag_disabled event" do |user|
+ it "tracks event" do
+ is_expected.to be(404)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'feature_flag_enabled!',
+ label: 'access_denied',
+ property: 'feature_flag_not_enabled',
+ project: project,
+ user: user_maintainer
+ )
+ end
+ end
+
+ RSpec.shared_examples "should track gcp_error event" do |config|
+ it "tracks event" do
+ is_expected.to be(403)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'google_oauth2_enabled!',
+ label: 'access_denied',
+ extra: { reason: 'google_oauth2_not_configured', config: config },
+ project: project,
+ user: user_maintainer
+ )
+ end
+ end
+
+ RSpec.shared_examples "should be not found" do
+ it 'returns not found' do
+ is_expected.to be(404)
+ end
+ end
+
+ RSpec.shared_examples "should be forbidden" do
+ it 'returns forbidden' do
+ is_expected.to be(403)
+ end
+ end
+
+ RSpec.shared_examples "public request should 404" do
+ it_behaves_like "should be not found"
+ it_behaves_like "should track not_found event"
+ end
+
+ RSpec.shared_examples "unauthorized access should 404" do
+ before do
+ project.add_guest(user_guest)
+ end
+
+ it_behaves_like "should be not found"
+ it_behaves_like "should track access_denied event"
+ end
+
+ describe 'GET #index', :snowplow do
+ subject { get project_google_cloud_gcp_regions_path(project) }
+
+ it_behaves_like "public request should 404"
+ it_behaves_like "unauthorized access should 404"
+
+ context 'when authorized members make requests' do
+ before do
+ project.add_maintainer(user_maintainer)
+ sign_in(user_maintainer)
+ end
+
+ it 'renders gcp_regions' do
+ is_expected.to render_template('projects/google_cloud/gcp_regions/index')
+ end
+
+ context 'but gitlab instance is not configured for google oauth2' do
+ unconfigured_google_oauth2 = Struct.new(:app_id, :app_secret)
+ .new('', '')
+
+ before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
+ .with('google_oauth2')
+ .and_return(unconfigured_google_oauth2)
+ end
+
+ it_behaves_like "should be forbidden"
+ it_behaves_like "should track gcp_error event", unconfigured_google_oauth2
+ end
+
+ context 'but feature flag is disabled' do
+ before do
+ stub_feature_flags(incubation_5mp_google_cloud: false)
+ end
+
+ it_behaves_like "should be not found"
+ it_behaves_like "should track feature_flag_disabled event"
+ end
+ end
+ end
+
+ describe 'POST #index', :snowplow do
+ subject { post project_google_cloud_gcp_regions_path(project), params: { gcp_region: 'region1', environment: 'env1' } }
+
+ it_behaves_like "public request should 404"
+ it_behaves_like "unauthorized access should 404"
+
+ context 'when authorized members make requests' do
+ before do
+ project.add_maintainer(user_maintainer)
+ sign_in(user_maintainer)
+ end
+
+ it 'redirects to google cloud index' do
+ is_expected.to redirect_to(project_google_cloud_index_path(project))
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb
new file mode 100644
index 00000000000..07590d3710e
--- /dev/null
+++ b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::GoogleCloud::RevokeOauthController do
+ include SessionHelpers
+
+ describe 'POST #create', :snowplow, :clean_gitlab_redis_sessions, :aggregate_failures do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:url) { project_google_cloud_revoke_oauth_index_path(project).to_s }
+
+ let(:user) { project.creator }
+
+ before do
+ sign_in(user)
+
+ stub_session(GoogleApi::CloudPlatform::Client.session_key_for_token => 'token')
+
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ allow(client).to receive(:validate_token).and_return(true)
+ end
+ end
+
+ context 'when GCP token is invalid' do
+ before do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ allow(client).to receive(:validate_token).and_return(false)
+ end
+ end
+
+ it 'redirects to Google OAuth2 authorize URL' do
+ sign_in(user)
+
+ post url
+
+ expect(response).to redirect_to(assigns(:authorize_url))
+ end
+ end
+
+ context 'when revocation is successful' do
+ before do
+ stub_request(:post, "https://oauth2.googleapis.com/revoke")
+ .to_return(status: 200, body: "", headers: {})
+ end
+
+ it 'calls revoke endpoint and redirects' do
+ post url
+
+ expect(request.session[GoogleApi::CloudPlatform::Client.session_key_for_token]).to be_nil
+ expect(response).to redirect_to(project_google_cloud_index_path(project))
+ expect(flash[:notice]).to eq('Google OAuth2 token revocation requested')
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'revoke_oauth#create',
+ label: 'create',
+ property: 'success',
+ project: project,
+ user: user
+ )
+ end
+ end
+
+ context 'when revocation fails' do
+ before do
+ stub_request(:post, "https://oauth2.googleapis.com/revoke")
+ .to_return(status: 400, body: "", headers: {})
+ end
+
+ it 'calls revoke endpoint and redirects' do
+ post url
+
+ expect(request.session[GoogleApi::CloudPlatform::Client.session_key_for_token]).to be_nil
+ expect(response).to redirect_to(project_google_cloud_index_path(project))
+ expect(flash[:alert]).to eq('Google OAuth2 token revocation request failed')
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'revoke_oauth#create',
+ label: 'create',
+ property: 'failed',
+ project: project,
+ user: user
+ )
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
index 0f243a6a7a9..4b32965e2b0 100644
--- a/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
+++ b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
let_it_be(:project) { create(:project, :public) }
- describe 'GET index' do
+ describe 'GET index', :snowplow do
let_it_be(:url) { "#{project_google_cloud_service_accounts_path(project)}" }
let(:user_guest) { create(:user) }
@@ -27,6 +27,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
get url
expect(response).to have_gitlab_http_status(:not_found)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: nil
+ )
end
it 'returns not found on POST request' do
@@ -42,6 +50,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
sign_in(unauthorized_member)
get url
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: unauthorized_member
+ )
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -52,6 +68,14 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
sign_in(unauthorized_member)
post url
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: unauthorized_member
+ )
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -80,34 +104,75 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
end
context 'and user has successfully completed the google oauth2 flow' do
- before do
- allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
- mock_service_account = Struct.new(:project_id, :unique_id, :email).new(123, 456, 'em@ai.l')
- allow(client).to receive(:validate_token).and_return(true)
- allow(client).to receive(:list_projects).and_return([{}, {}, {}])
- allow(client).to receive(:create_service_account).and_return(mock_service_account)
- allow(client).to receive(:create_service_account_key).and_return({})
- allow(client).to receive(:grant_service_account_roles)
+ context 'but the user does not have gcp projects' do
+ before do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ mock_service_account = Struct.new(:project_id, :unique_id, :email).new(123, 456, 'em@ai.l')
+ allow(client).to receive(:list_projects).and_return([])
+ allow(client).to receive(:validate_token).and_return(true)
+ allow(client).to receive(:create_service_account).and_return(mock_service_account)
+ allow(client).to receive(:create_service_account_key).and_return({})
+ allow(client).to receive(:grant_service_account_roles)
+ end
end
- end
- it 'returns success on GET' do
- authorized_members.each do |authorized_member|
- sign_in(authorized_member)
+ it 'renders no_gcp_projects' do
+ authorized_members.each do |authorized_member|
+ allow_next_instance_of(BranchesFinder) do |branches_finder|
+ allow(branches_finder).to receive(:execute).and_return([])
+ end
- get url
+ allow_next_instance_of(TagsFinder) do |branches_finder|
+ allow(branches_finder).to receive(:execute).and_return([])
+ end
+
+ sign_in(authorized_member)
- expect(response).to have_gitlab_http_status(:ok)
+ get url
+
+ expect(response).to render_template('projects/google_cloud/errors/no_gcp_projects')
+ end
end
end
- it 'returns success on POST' do
- authorized_members.each do |authorized_member|
- sign_in(authorized_member)
+ context 'user has three gcp_projects' do
+ before do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ mock_service_account = Struct.new(:project_id, :unique_id, :email).new(123, 456, 'em@ai.l')
+ allow(client).to receive(:list_projects).and_return([{}, {}, {}])
+ allow(client).to receive(:validate_token).and_return(true)
+ allow(client).to receive(:create_service_account).and_return(mock_service_account)
+ allow(client).to receive(:create_service_account_key).and_return({})
+ allow(client).to receive(:grant_service_account_roles)
+ end
+ end
- post url, params: { gcp_project: 'prj1', environment: 'env1' }
+ it 'returns success on GET' do
+ authorized_members.each do |authorized_member|
+ allow_next_instance_of(BranchesFinder) do |branches_finder|
+ allow(branches_finder).to receive(:execute).and_return([])
+ end
+
+ allow_next_instance_of(TagsFinder) do |branches_finder|
+ allow(branches_finder).to receive(:execute).and_return([])
+ end
+
+ sign_in(authorized_member)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ it 'returns success on POST' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ post url, params: { gcp_project: 'prj1', ref: 'env1' }
- expect(response).to redirect_to(project_google_cloud_index_path(project))
+ expect(response).to redirect_to(project_google_cloud_index_path(project))
+ end
end
end
end
diff --git a/spec/requests/projects/google_cloud_controller_spec.rb b/spec/requests/projects/google_cloud_controller_spec.rb
index 37682152994..d0814990989 100644
--- a/spec/requests/projects/google_cloud_controller_spec.rb
+++ b/spec/requests/projects/google_cloud_controller_spec.rb
@@ -8,7 +8,7 @@ MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret)
RSpec.describe Projects::GoogleCloudController do
let_it_be(:project) { create(:project, :public) }
- describe 'GET index' do
+ describe 'GET index', :snowplow do
let_it_be(:url) { "#{project_google_cloud_index_path(project)}" }
context 'when a public request is made' do
@@ -16,6 +16,13 @@ RSpec.describe Projects::GoogleCloudController do
get url
expect(response).to have_gitlab_http_status(:not_found)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: nil)
end
end
@@ -29,6 +36,14 @@ RSpec.describe Projects::GoogleCloudController do
get url
expect(response).to have_gitlab_http_status(:not_found)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: user
+ )
end
end
@@ -42,6 +57,14 @@ RSpec.describe Projects::GoogleCloudController do
get url
expect(response).to have_gitlab_http_status(:not_found)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'admin_project_google_cloud!',
+ label: 'access_denied',
+ property: 'invalid_user',
+ project: project,
+ user: user
+ )
end
end
@@ -74,19 +97,26 @@ RSpec.describe Projects::GoogleCloudController do
let(:user) { project.creator }
context 'but gitlab instance is not configured for google oauth2' do
- before do
+ it 'returns forbidden' do
unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '')
allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
.with('google_oauth2')
.and_return(unconfigured_google_oauth2)
- end
- it 'returns forbidden' do
sign_in(user)
get url
expect(response).to have_gitlab_http_status(:forbidden)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'google_oauth2_enabled!',
+ label: 'access_denied',
+ extra: { reason: 'google_oauth2_not_configured',
+ config: unconfigured_google_oauth2 },
+ project: project,
+ user: user
+ )
end
end
@@ -101,6 +131,46 @@ RSpec.describe Projects::GoogleCloudController do
get url
expect(response).to have_gitlab_http_status(:not_found)
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'feature_flag_enabled!',
+ label: 'access_denied',
+ property: 'feature_flag_not_enabled',
+ project: project,
+ user: user
+ )
+ end
+ end
+
+ context 'but google oauth2 token is not valid' do
+ it 'does not return revoke oauth url' do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ allow(client).to receive(:validate_token).and_return(false)
+ end
+
+ sign_in(user)
+
+ get url
+
+ expect(response).to be_successful
+ expect_snowplow_event(
+ category: 'Projects::GoogleCloud',
+ action: 'google_cloud#index',
+ label: 'index',
+ extra: {
+ screen: 'home',
+ serviceAccounts: [],
+ createServiceAccountUrl: project_google_cloud_service_accounts_path(project),
+ enableCloudRunUrl: project_google_cloud_deployments_cloud_run_path(project),
+ enableCloudStorageUrl: project_google_cloud_deployments_cloud_storage_path(project),
+ emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg'),
+ configureGcpRegionsUrl: project_google_cloud_gcp_regions_path(project),
+ gcpRegions: [],
+ revokeOauthUrl: nil
+ },
+ project: project,
+ user: user
+ )
end
end
end
diff --git a/spec/requests/projects/harbor/repositories_controller_spec.rb b/spec/requests/projects/harbor/repositories_controller_spec.rb
new file mode 100644
index 00000000000..cdb5a696d7e
--- /dev/null
+++ b/spec/requests/projects/harbor/repositories_controller_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Harbor::RepositoriesController do
+ let_it_be(:project, reload: true) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ shared_examples 'responds with 404 status' do
+ it 'returns 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ shared_examples 'responds with 200 status' do
+ it 'renders the index template' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index)
+ end
+ end
+
+ before do
+ stub_feature_flags(harbor_registry_integration: true)
+ project.add_developer(user)
+ sign_in(user)
+ end
+
+ describe 'GET #index' do
+ subject do
+ get project_harbor_registry_index_path(project)
+ response
+ end
+
+ context 'with harbor registry feature flag enabled' do
+ it_behaves_like 'responds with 200 status'
+ end
+
+ context 'with harbor registry feature flag disabled' do
+ before do
+ stub_feature_flags(harbor_registry_integration: false)
+ end
+
+ it_behaves_like 'responds with 404 status'
+ end
+ end
+
+ describe 'GET #show' do
+ subject do
+ get project_harbor_registry_path(project, 1)
+ response
+ end
+
+ context 'with harbor registry feature flag enabled' do
+ it_behaves_like 'responds with 200 status'
+ end
+
+ context 'with harbor registry feature flag disabled' do
+ before do
+ stub_feature_flags(harbor_registry_integration: false)
+ end
+
+ it_behaves_like 'responds with 404 status'
+ end
+ end
+end
diff --git a/spec/requests/projects/redirect_controller_spec.rb b/spec/requests/projects/redirect_controller_spec.rb
new file mode 100644
index 00000000000..3bbca3ca32b
--- /dev/null
+++ b/spec/requests/projects/redirect_controller_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Projects::RedirectController requests" do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:private_project) { create(:project, :private) }
+ let_it_be(:public_project) { create(:project, :public) }
+ let_it_be(:user) { create(:user) }
+
+ before_all do
+ private_project.add_developer(user)
+ end
+
+ describe 'GET redirect_from_id' do
+ where(:authenticated, :project, :is_found) do
+ true | ref(:private_project) | true
+ false | ref(:private_project) | false
+ true | ref(:public_project) | true
+ false | ref(:public_project) | true
+ true | build(:project, id: 0) | false
+ end
+
+ with_them do
+ before do
+ sign_in(user) if authenticated
+
+ get "/projects/#{project.id}"
+ end
+
+ if params[:is_found]
+ it 'redirects to the project page' do
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(project_path(project))
+ end
+ else
+ it 'gives 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+
+ # This is a regression test for https://gitlab.com/gitlab-org/gitlab/-/issues/351058
+ context 'with sourcegraph enabled' do
+ let_it_be(:sourcegraph_url) { 'https://sourcegraph.test' }
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(sourcegraph_url)
+ allow(Gitlab::CurrentSettings).to receive(:sourcegraph_enabled).and_return(true)
+
+ sign_in(user)
+ end
+
+ context 'with projects/:id route' do
+ subject { get "/projects/#{public_project.id}" }
+
+ it 'redirects successfully' do
+ subject
+
+ expect(response).to redirect_to(project_path(public_project))
+ end
+ end
+ end
+end