diff options
Diffstat (limited to 'spec/controllers')
43 files changed, 931 insertions, 2007 deletions
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb index a18ebe9c9a0..4a92911f914 100644 --- a/spec/controllers/admin/application_settings_controller_spec.rb +++ b/spec/controllers/admin/application_settings_controller_spec.rb @@ -66,6 +66,26 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set sign_in(admin) end + context 'when there are recent ServicePing reports' do + it 'attempts to use prerecorded data' do + create(:raw_usage_data) + + expect(Gitlab::Usage::ServicePingReport).not_to receive(:for) + + get :usage_data, format: :json + end + end + + context 'when there are NO recent ServicePing reports' do + it 'calculates data on the fly' do + allow(Gitlab::Usage::ServicePingReport).to receive(:for).and_call_original + + get :usage_data, format: :json + + expect(Gitlab::Usage::ServicePingReport).to have_received(:for) + end + end + it 'returns HTML data' do get :usage_data, format: :html @@ -331,6 +351,17 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set end end end + + context 'pipeline creation rate limiting' do + let(:application_settings) { ApplicationSetting.current } + + it 'updates pipeline_limit_per_project_user_sha setting' do + put :update, params: { application_setting: { pipeline_limit_per_project_user_sha: 25 } } + + expect(response).to redirect_to(general_admin_application_settings_path) + expect(application_settings.reload.pipeline_limit_per_project_user_sha).to eq(25) + end + end end describe 'PUT #reset_registration_token' do @@ -368,4 +399,37 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set expect(response).to redirect_to("https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf") end end + + describe 'GET #service_usage_data' do + before do + stub_usage_data_connections + stub_database_flavor_check + sign_in(admin) + end + + it 'assigns truthy value if there are recent ServicePing reports in database' do + create(:raw_usage_data) + + get :service_usage_data, format: :html + + expect(assigns(:service_ping_data_present)).to be_truthy + expect(response).to have_gitlab_http_status(:ok) + end + + it 'assigns truthy value if there are recent ServicePing reports in cache', :use_clean_rails_memory_store_caching do + Rails.cache.write('usage_data', true) + + get :service_usage_data, format: :html + + expect(assigns(:service_ping_data_present)).to be_truthy + expect(response).to have_gitlab_http_status(:ok) + end + + it 'assigns falsey value if there are NO recent ServicePing reports' do + get :service_usage_data, format: :html + + expect(assigns(:service_ping_data_present)).to be_falsey + expect(response).to have_gitlab_http_status(:ok) + end + end end diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb index fed9d2e8588..ca2b50b529c 100644 --- a/spec/controllers/admin/clusters_controller_spec.rb +++ b/spec/controllers/admin/clusters_controller_spec.rb @@ -102,87 +102,6 @@ RSpec.describe Admin::ClustersController do end end - describe 'GET #new' do - let(:user) { admin } - - def go(provider: 'gcp') - get :new, params: { provider: provider } - end - - include_examples ':certificate_based_clusters feature flag controller responses' do - let(:subject) { go } - end - - describe 'functionality for new cluster' do - context 'when omniauth has been configured' do - let(:key) { 'secret-key' } - let(:session_key_for_redirect_uri) do - GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key) - end - - context 'when selected provider is gke and no valid gcp token exists' do - it 'redirects to gcp authorize_url' do - go - - expect(response).to redirect_to(assigns(:authorize_url)) - end - end - end - - context 'when omniauth has not configured' do - before do - stub_omniauth_setting(providers: []) - end - - it 'does not have authorize_url' do - go - - expect(assigns(:authorize_url)).to be_nil - end - end - - context 'when access token is valid' do - before do - stub_google_api_validate_token - end - - it 'has new object' do - go - - expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::ClusterPresenter) - end - end - - context 'when access token is expired' do - before do - stub_google_api_expired_token - end - - it { expect(@valid_gcp_token).to be_falsey } - end - - context 'when access token is not stored in session' do - it { expect(@valid_gcp_token).to be_falsey } - end - end - - describe 'functionality for existing cluster' do - it 'has new object' do - go - - expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::ClusterPresenter) - end - end - - include_examples 'GET new cluster shared examples' - - describe 'security' do - it { expect { go }.to be_allowed_for(:admin) } - it { expect { go }.to be_denied_for(:user) } - it { expect { go }.to be_denied_for(:external) } - end - end - it_behaves_like 'GET #metrics_dashboard for dashboard', 'Cluster health' do let(:cluster) { create(:cluster, :instance, :provided_by_gcp) } @@ -216,164 +135,6 @@ RSpec.describe Admin::ClustersController do end end - describe 'POST #create_gcp' do - let(:legacy_abac_param) { 'true' } - let(:params) do - { - cluster: { - name: 'new-cluster', - provider_gcp_attributes: { - gcp_project_id: 'gcp-project-12345', - legacy_abac: legacy_abac_param - } - } - } - end - - def post_create_gcp - post :create_gcp, params: params - end - - include_examples ':certificate_based_clusters feature flag controller responses' do - let(:subject) { post_create_gcp } - end - - describe 'functionality' do - context 'when access token is valid' do - before do - stub_google_api_validate_token - end - - it 'creates a new cluster' do - expect(ClusterProvisionWorker).to receive(:perform_async) - expect { post_create_gcp }.to change { Clusters::Cluster.count } - .and change { Clusters::Providers::Gcp.count } - - cluster = Clusters::Cluster.instance_type.first - - expect(response).to redirect_to(admin_cluster_path(cluster)) - expect(cluster).to be_gcp - expect(cluster).to be_kubernetes - expect(cluster.provider_gcp).to be_legacy_abac - end - - context 'when legacy_abac param is false' do - let(:legacy_abac_param) { 'false' } - - it 'creates a new cluster with legacy_abac_disabled' do - expect(ClusterProvisionWorker).to receive(:perform_async) - expect { post_create_gcp }.to change { Clusters::Cluster.count } - .and change { Clusters::Providers::Gcp.count } - expect(Clusters::Cluster.instance_type.first.provider_gcp).not_to be_legacy_abac - end - end - end - - context 'when access token is expired' do - before do - stub_google_api_expired_token - end - - it { expect(@valid_gcp_token).to be_falsey } - end - - context 'when access token is not stored in session' do - it { expect(@valid_gcp_token).to be_falsey } - end - end - - describe 'security' do - before do - allow_next_instance_of(described_class) do |instance| - allow(instance).to receive(:token_in_session).and_return('token') - allow(instance).to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s) - end - allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance| - allow(instance).to receive(:projects_zones_clusters_create) do - double( - 'instance', - self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', - status: 'RUNNING' - ) - end - end - - allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil) - end - - it { expect { post_create_gcp }.to be_allowed_for(:admin) } - it { expect { post_create_gcp }.to be_denied_for(:user) } - it { expect { post_create_gcp }.to be_denied_for(:external) } - end - end - - describe 'POST #create_aws' do - let(:params) do - { - cluster: { - name: 'new-cluster', - provider_aws_attributes: { - key_name: 'key', - role_arn: 'arn:role', - region: 'region', - vpc_id: 'vpc', - instance_type: 'instance type', - num_nodes: 3, - security_group_id: 'security group', - subnet_ids: %w(subnet1 subnet2) - } - } - } - end - - def post_create_aws - post :create_aws, params: params - end - - include_examples ':certificate_based_clusters feature flag controller responses' do - let(:subject) { post_create_aws } - end - - it 'creates a new cluster' do - expect(ClusterProvisionWorker).to receive(:perform_async) - expect { post_create_aws }.to change { Clusters::Cluster.count } - .and change { Clusters::Providers::Aws.count } - - cluster = Clusters::Cluster.instance_type.first - - expect(response).to have_gitlab_http_status(:created) - expect(response.location).to eq(admin_cluster_path(cluster)) - expect(cluster).to be_aws - expect(cluster).to be_kubernetes - end - - context 'params are invalid' do - let(:params) do - { - cluster: { name: '' } - } - end - - it 'does not create a cluster' do - expect { post_create_aws }.not_to change { Clusters::Cluster.count } - - expect(response).to have_gitlab_http_status(:unprocessable_entity) - expect(response.media_type).to eq('application/json') - expect(response.body).to include('is invalid') - end - end - - describe 'security' do - before do - allow(WaitForClusterCreationWorker).to receive(:perform_in) - end - - it { expect { post_create_aws }.to be_allowed_for(:admin) } - it { expect { post_create_aws }.to be_denied_for(:user) } - it { expect { post_create_aws }.to be_denied_for(:external) } - end - end - describe 'POST #create_user' do let(:params) do { diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb index d9b7e00fd75..fb843ac6a7a 100644 --- a/spec/controllers/admin/groups_controller_spec.rb +++ b/spec/controllers/admin/groups_controller_spec.rb @@ -51,7 +51,7 @@ RSpec.describe Admin::GroupsController do it 'adds user to members', :aggregate_failures, :snowplow do put :members_update, params: { id: group, - user_ids: group_user.id, + user_id: group_user.id, access_level: Gitlab::Access::GUEST } @@ -70,7 +70,7 @@ RSpec.describe Admin::GroupsController do it 'can add unlimited members', :aggregate_failures do put :members_update, params: { id: group, - user_ids: 1.upto(1000).to_a.join(','), + user_id: 1.upto(1000).to_a.join(','), access_level: Gitlab::Access::GUEST } @@ -81,7 +81,7 @@ RSpec.describe Admin::GroupsController do it 'adds no user to members', :aggregate_failures do put :members_update, params: { id: group, - user_ids: '', + user_id: '', access_level: Gitlab::Access::GUEST } diff --git a/spec/controllers/admin/requests_profiles_controller_spec.rb b/spec/controllers/admin/requests_profiles_controller_spec.rb deleted file mode 100644 index 7ee46b5b28a..00000000000 --- a/spec/controllers/admin/requests_profiles_controller_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Admin::RequestsProfilesController do - let_it_be(:admin) { create(:admin) } - - before do - sign_in(admin) - end - - describe '#show' do - let(:tmpdir) { Dir.mktmpdir('profiler-test') } - let(:test_file) { File.join(tmpdir, basename) } - - subject do - get :show, params: { name: basename } - end - - before do - stub_const('Gitlab::RequestProfiler::PROFILES_DIR', tmpdir) - File.write(test_file, sample_data) - end - - after do - FileUtils.rm_rf(tmpdir) - end - - context 'when loading HTML profile' do - let(:basename) { "profile_#{Time.current.to_i}_execution.html" } - - let(:sample_data) do - '<html> <body> <h1>Heading</h1> <p>paragraph.</p> </body> </html>' - end - - it 'renders the data' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response.body).to eq(sample_data) - end - end - - context 'when loading TXT profile' do - let(:basename) { "profile_#{Time.current.to_i}_memory.txt" } - - let(:sample_data) do - <<~TXT - Total allocated: 112096396 bytes (1080431 objects) - Total retained: 10312598 bytes (53567 objects) - TXT - end - - it 'renders the data' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response.body).to eq(sample_data) - end - end - - context 'when loading PDF profile' do - let(:basename) { "profile_#{Time.current.to_i}_anything.pdf" } - - let(:sample_data) { 'mocked pdf content' } - - it 'fails to render the data' do - expect { subject }.to raise_error(ActionController::UrlGenerationError, /No route matches.*unmatched constraints:/) - end - end - end -end diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb index 8f70cb32d3e..fea59969400 100644 --- a/spec/controllers/admin/runners_controller_spec.rb +++ b/spec/controllers/admin/runners_controller_spec.rb @@ -26,27 +26,12 @@ RSpec.describe Admin::RunnersController do describe '#show' do render_views - let_it_be(:project) { create(:project) } - - before_all do - create(:ci_build, runner: runner, project: project) - end - it 'shows a runner show page' do get :show, params: { id: runner.id } expect(response).to have_gitlab_http_status(:ok) expect(response).to render_template(:show) end - - it 'when runner_read_only_admin_view is off, redirects to the runner edit page' do - stub_feature_flags(runner_read_only_admin_view: false) - - get :show, params: { id: runner.id } - - expect(response).to have_gitlab_http_status(:redirect) - expect(response).to redirect_to edit_admin_runner_path(runner) - end end describe '#edit' do @@ -55,11 +40,6 @@ RSpec.describe Admin::RunnersController do let_it_be(:project) { create(:project) } let_it_be(:project_two) { create(:project) } - before_all do - create(:ci_build, runner: runner, project: project) - create(:ci_build, runner: runner, project: project_two) - end - it 'shows a runner edit page' do get :edit, params: { id: runner.id } @@ -77,9 +57,6 @@ RSpec.describe Admin::RunnersController do control_count = ActiveRecord::QueryRecorder.new { get :edit, params: { id: runner.id } }.count - new_project = create(:project) - create(:ci_build, runner: runner, project: new_project) - # There is one additional query looking up subject.group in ProjectPolicy for the # needs_new_sso_session permission expect { get :edit, params: { id: runner.id } }.not_to exceed_query_limit(control_count + 1) @@ -89,17 +66,42 @@ RSpec.describe Admin::RunnersController do end describe '#update' do - it 'updates the runner and ticks the queue' do - new_desc = runner.description.swapcase + let(:new_desc) { runner.description.swapcase } + let(:runner_params) { { id: runner.id, runner: { description: new_desc } } } - expect do - post :update, params: { id: runner.id, runner: { description: new_desc } } - end.to change { runner.ensure_runner_queue_value } + subject(:request) { post :update, params: runner_params } - runner.reload + context 'with update succeeding' do + before do + expect_next_instance_of(Ci::Runners::UpdateRunnerService, runner) do |service| + expect(service).to receive(:update).with(anything).and_call_original + end + end - expect(response).to have_gitlab_http_status(:found) - expect(runner.description).to eq(new_desc) + it 'updates the runner and ticks the queue' do + expect { request }.to change { runner.ensure_runner_queue_value } + + runner.reload + + expect(response).to have_gitlab_http_status(:found) + expect(runner.description).to eq(new_desc) + end + end + + context 'with update failing' do + before do + expect_next_instance_of(Ci::Runners::UpdateRunnerService, runner) do |service| + expect(service).to receive(:update).with(anything).and_return(false) + end + end + + it 'does not update runner or tick the queue' do + expect { request }.not_to change { runner.ensure_runner_queue_value } + expect { request }.not_to change { runner.reload.description } + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template(:show) + end end end diff --git a/spec/controllers/admin/topics_controller_spec.rb b/spec/controllers/admin/topics_controller_spec.rb index ea510f916da..67943525687 100644 --- a/spec/controllers/admin/topics_controller_spec.rb +++ b/spec/controllers/admin/topics_controller_spec.rb @@ -77,24 +77,31 @@ RSpec.describe Admin::TopicsController do describe 'POST #create' do it 'creates topic' do expect do - post :create, params: { projects_topic: { name: 'test' } } + post :create, params: { projects_topic: { name: 'test', title: 'Test' } } end.to change { Projects::Topic.count }.by(1) end - it 'shows error message for invalid topic' do - post :create, params: { projects_topic: { name: nil } } + it 'shows error message for invalid topic name' do + post :create, params: { projects_topic: { name: nil, title: 'Test' } } errors = assigns[:topic].errors expect(errors).to contain_exactly(errors.full_message(:name, I18n.t('errors.messages.blank'))) end - it 'shows error message if topic not unique (case insensitive)' do - post :create, params: { projects_topic: { name: topic.name.upcase } } + it 'shows error message if topic name not unique (case insensitive)' do + post :create, params: { projects_topic: { name: topic.name.upcase, title: topic.title } } errors = assigns[:topic].errors expect(errors).to contain_exactly(errors.full_message(:name, I18n.t('errors.messages.taken'))) end + it 'shows error message for invalid topic title' do + post :create, params: { projects_topic: { name: 'test', title: nil } } + + errors = assigns[:topic].errors + expect(errors).to contain_exactly(errors.full_message(:title, I18n.t('errors.messages.blank'))) + end + context 'as a normal user' do before do sign_in(user) diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb index abada97fb10..efa00877142 100644 --- a/spec/controllers/dashboard/todos_controller_spec.rb +++ b/spec/controllers/dashboard/todos_controller_spec.rb @@ -113,6 +113,19 @@ RSpec.describe Dashboard::TodosController do expect(response).to redirect_to(dashboard_todos_path(page: last_page, project_id: project.id)) end + + it 'returns directly addressed if filtering by mentioned action_id' do + allow(controller).to receive(:current_user).and_return(user) + + mentioned_todos = [ + create(:todo, :directly_addressed, project: project, user: user, target: issues.first), + create(:todo, :mentioned, project: project, user: user, target: issues.first) + ] + + get :index, params: { action_id: ::Todo::MENTIONED, project_id: project.id } + + expect(assigns(:todos)).to match_array(mentioned_todos) + end end end diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb index 4de31e2e135..0818dce776d 100644 --- a/spec/controllers/graphql_controller_spec.rb +++ b/spec/controllers/graphql_controller_spec.rb @@ -9,15 +9,10 @@ RSpec.describe GraphqlController do stub_feature_flags(graphql: true) end - describe 'ArgumentError' do - let(:user) { create(:user) } - let(:message) { 'green ideas sleep furiously' } + describe 'rescue_from' do + let_it_be(:message) { 'green ideas sleep furiously' } - before do - sign_in(user) - end - - it 'handles argument errors' do + it 'handles ArgumentError' do allow(subject).to receive(:execute) do raise Gitlab::Graphql::Errors::ArgumentError, message end @@ -28,6 +23,19 @@ RSpec.describe GraphqlController do 'errors' => include(a_hash_including('message' => message)) ) end + + it 'handles StandardError' do + allow(subject).to receive(:execute) do + raise StandardError, message + end + + post :execute + + expect(json_response).to include( + 'errors' => include(a_hash_including('message' => /Internal server error/, + 'raisedAt' => /graphql_controller_spec.rb/)) + ) + end end describe 'POST #execute' do diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb index 4eeae64b760..4b82c5ceb1c 100644 --- a/spec/controllers/groups/clusters_controller_spec.rb +++ b/spec/controllers/groups/clusters_controller_spec.rb @@ -115,95 +115,6 @@ RSpec.describe Groups::ClustersController do end end - describe 'GET new' do - def go(provider: 'gcp') - get :new, params: { group_id: group, provider: provider } - end - - include_examples ':certificate_based_clusters feature flag controller responses' do - let(:subject) { go } - end - - describe 'functionality for new cluster' do - context 'when omniauth has been configured' do - let(:key) { 'secret-key' } - let(:session_key_for_redirect_uri) do - GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key) - end - - before do - allow(SecureRandom).to receive(:hex).and_return(key) - end - - it 'redirects to gcp authorize_url' do - go - - expect(assigns(:authorize_url)).to include(key) - expect(session[session_key_for_redirect_uri]).to eq(new_group_cluster_path(group, provider: :gcp)) - expect(response).to redirect_to(assigns(:authorize_url)) - end - end - - context 'when omniauth has not configured' do - before do - stub_omniauth_setting(providers: []) - end - - it 'does not have authorize_url' do - go - - expect(assigns(:authorize_url)).to be_nil - end - end - - context 'when access token is valid' do - before do - stub_google_api_validate_token - end - - it 'has new object' do - go - - expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::ClusterPresenter) - end - end - - context 'when access token is expired' do - before do - stub_google_api_expired_token - end - - it { expect(@valid_gcp_token).to be_falsey } - end - - context 'when access token is not stored in session' do - it { expect(@valid_gcp_token).to be_falsey } - end - end - - describe 'functionality for existing cluster' do - it 'has new object' do - go - - expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::ClusterPresenter) - end - end - - include_examples 'GET new cluster shared examples' - - describe 'security' do - it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { expect { go }.to be_allowed_for(:admin) } - it('is denied for admin when admin mode is disabled') { expect { go }.to be_denied_for(:admin) } - it { expect { go }.to be_allowed_for(:owner).of(group) } - it { expect { go }.to be_allowed_for(:maintainer).of(group) } - it { expect { go }.to be_denied_for(:developer).of(group) } - it { expect { go }.to be_denied_for(:reporter).of(group) } - it { expect { go }.to be_denied_for(:guest).of(group) } - it { expect { go }.to be_denied_for(:user) } - it { expect { go }.to be_denied_for(:external) } - end - end - it_behaves_like 'GET #metrics_dashboard for dashboard', 'Cluster health' do let(:cluster) { create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group]) } @@ -244,105 +155,6 @@ RSpec.describe Groups::ClustersController do end end - describe 'POST create for new cluster' do - let(:legacy_abac_param) { 'true' } - let(:params) do - { - cluster: { - name: 'new-cluster', - managed: '1', - provider_gcp_attributes: { - gcp_project_id: 'gcp-project-12345', - legacy_abac: legacy_abac_param - } - } - } - end - - def go - post :create_gcp, params: params.merge(group_id: group) - end - - include_examples ':certificate_based_clusters feature flag controller responses' do - let(:subject) { go } - end - - describe 'functionality' do - context 'when access token is valid' do - before do - stub_google_api_validate_token - end - - it 'creates a new cluster' do - expect(ClusterProvisionWorker).to receive(:perform_async) - expect { go }.to change { Clusters::Cluster.count } - .and change { Clusters::Providers::Gcp.count } - - cluster = group.clusters.first - - expect(response).to redirect_to(group_cluster_path(group, cluster)) - expect(cluster).to be_gcp - expect(cluster).to be_kubernetes - expect(cluster.provider_gcp).to be_legacy_abac - expect(cluster).to be_managed - expect(cluster).to be_namespace_per_environment - end - - context 'when legacy_abac param is false' do - let(:legacy_abac_param) { 'false' } - - it 'creates a new cluster with legacy_abac_disabled' do - expect(ClusterProvisionWorker).to receive(:perform_async) - expect { go }.to change { Clusters::Cluster.count } - .and change { Clusters::Providers::Gcp.count } - expect(group.clusters.first.provider_gcp).not_to be_legacy_abac - end - end - end - - context 'when access token is expired' do - before do - stub_google_api_expired_token - end - - it { expect(@valid_gcp_token).to be_falsey } - end - - context 'when access token is not stored in session' do - it { expect(@valid_gcp_token).to be_falsey } - end - end - - describe 'security' do - before do - allow_any_instance_of(described_class) - .to receive(:token_in_session).and_return('token') - allow_any_instance_of(described_class) - .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s) - allow_any_instance_of(GoogleApi::CloudPlatform::Client) - .to receive(:projects_zones_clusters_create) do - double( - 'instance', - self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', - status: 'RUNNING' - ) - end - - allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil) - end - - it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { expect { go }.to be_allowed_for(:admin) } - it('is denied for admin when admin mode is disabled') { expect { go }.to be_denied_for(:admin) } - it { expect { go }.to be_allowed_for(:owner).of(group) } - it { expect { go }.to be_allowed_for(:maintainer).of(group) } - it { expect { go }.to be_denied_for(:developer).of(group) } - it { expect { go }.to be_denied_for(:reporter).of(group) } - it { expect { go }.to be_denied_for(:guest).of(group) } - it { expect { go }.to be_denied_for(:user) } - it { expect { go }.to be_denied_for(:external) } - end - end - describe 'POST create for existing cluster' do let(:params) do { diff --git a/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb b/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb index 50e19d5b482..ed79712f828 100644 --- a/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb +++ b/spec/controllers/groups/dependency_proxy_auth_controller_spec.rb @@ -8,18 +8,6 @@ RSpec.describe Groups::DependencyProxyAuthController do describe 'GET #authenticate' do subject { get :authenticate } - context 'feature flag disabled' do - before do - stub_feature_flags(dependency_proxy_for_private_groups: false) - end - - it 'returns successfully', :aggregate_failures do - subject - - expect(response).to have_gitlab_http_status(:success) - end - end - context 'without JWT' do it 'returns unauthorized with oauth realm', :aggregate_failures do subject diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb index 61445603a2d..5b4b00106cb 100644 --- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb +++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb @@ -20,33 +20,9 @@ RSpec.describe Groups::DependencyProxyForContainersController do request.headers['HTTP_AUTHORIZATION'] = nil end - context 'feature flag disabled' do - let_it_be(:group) { create(:group) } - - before do - stub_feature_flags(dependency_proxy_for_private_groups: false) - end - - it { is_expected.to have_gitlab_http_status(:ok) } - end - it { is_expected.to have_gitlab_http_status(:unauthorized) } end - shared_examples 'feature flag disabled with private group' do - before do - stub_feature_flags(dependency_proxy_for_private_groups: false) - end - - it 'returns not found' do - group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) - - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - shared_examples 'with invalid path' do context 'with invalid image' do let(:image) { '../path_traversal' } @@ -208,7 +184,6 @@ RSpec.describe Groups::DependencyProxyForContainersController do context 'feature enabled' do it_behaves_like 'without a token' it_behaves_like 'without permission' - it_behaves_like 'feature flag disabled with private group' context 'remote token request fails' do let(:token_response) do @@ -321,7 +296,6 @@ RSpec.describe Groups::DependencyProxyForContainersController do context 'feature enabled' do it_behaves_like 'without a token' it_behaves_like 'without permission' - it_behaves_like 'feature flag disabled with private group' context 'a valid user' do before do diff --git a/spec/controllers/groups/releases_controller_spec.rb b/spec/controllers/groups/releases_controller_spec.rb index 8b08f913e10..9d372114d62 100644 --- a/spec/controllers/groups/releases_controller_spec.rb +++ b/spec/controllers/groups/releases_controller_spec.rb @@ -60,32 +60,6 @@ RSpec.describe Groups::ReleasesController do end end - context 'group_releases_finder_inoperator feature flag' do - before do - sign_in(guest) - end - - it 'calls old code when disabled' do - stub_feature_flags(group_releases_finder_inoperator: false) - - allow(ReleasesFinder).to receive(:new).and_call_original - - index - - expect(ReleasesFinder).to have_received(:new) - end - - it 'calls new code when enabled' do - stub_feature_flags(group_releases_finder_inoperator: true) - - allow(Releases::GroupReleasesFinder).to receive(:new).and_call_original - - index - - expect(Releases::GroupReleasesFinder).to have_received(:new) - end - end - context 'N+1 queries' do it 'avoids N+1 database queries' do control_count = ActiveRecord::QueryRecorder.new { subject }.count diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb index a53f09e2afc..77c62c0d930 100644 --- a/spec/controllers/groups/runners_controller_spec.rb +++ b/spec/controllers/groups/runners_controller_spec.rb @@ -194,205 +194,4 @@ RSpec.describe Groups::RunnersController do end end end - - describe '#destroy' do - context 'when user is an owner' do - before do - group.add_owner(user) - end - - it 'destroys the runner and redirects' do - expect_next_instance_of(Ci::Runners::UnregisterRunnerService, runner, user) do |service| - expect(service).to receive(:execute).once.and_call_original - end - - delete :destroy, params: params - - expect(response).to have_gitlab_http_status(:found) - expect(Ci::Runner.find_by(id: runner.id)).to be_nil - end - - it 'destroys the project runner and redirects' do - delete :destroy, params: params_runner_project - - expect(response).to have_gitlab_http_status(:found) - expect(Ci::Runner.find_by(id: runner_project.id)).to be_nil - end - end - - context 'with runner associated with multiple projects' do - let_it_be(:project_2) { create(:project, group: group) } - - let(:runner_project_2) { create(:ci_runner, :project, projects: [project, project_2]) } - let(:params_runner_project_2) { { group_id: group, id: runner_project_2 } } - - context 'when user is an admin', :enable_admin_mode do - let(:user) { create(:user, :admin) } - - before do - sign_in(user) - end - - it 'destroys the project runner and redirects' do - delete :destroy, params: params_runner_project_2 - - expect(response).to have_gitlab_http_status(:found) - expect(Ci::Runner.find_by(id: runner_project_2.id)).to be_nil - end - end - - context 'when user is an owner' do - before do - group.add_owner(user) - end - - it 'does not destroy the project runner' do - delete :destroy, params: params_runner_project_2 - - expect(response).to have_gitlab_http_status(:found) - expect(flash[:alert]).to eq('Runner cannot be deleted, please contact your administrator.') - expect(Ci::Runner.find_by(id: runner_project_2.id)).to be_present - end - end - end - - context 'when user is not an owner' do - before do - group.add_maintainer(user) - end - - it 'responds 404 and does not destroy the runner' do - delete :destroy, params: params - - expect(response).to have_gitlab_http_status(:not_found) - expect(Ci::Runner.find_by(id: runner.id)).to be_present - end - - it 'responds 404 and does not destroy the project runner' do - delete :destroy, params: params_runner_project - - expect(response).to have_gitlab_http_status(:not_found) - expect(Ci::Runner.find_by(id: runner_project.id)).to be_present - end - end - end - - describe '#resume' do - context 'when user is an owner' do - before do - group.add_owner(user) - end - - it 'marks the runner as active, ticks the queue, and redirects' do - runner.update!(active: false) - - expect do - post :resume, params: params - end.to change { runner.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:found) - expect(runner.reload.active).to eq(true) - end - - it 'marks the project runner as active, ticks the queue, and redirects' do - runner_project.update!(active: false) - - expect do - post :resume, params: params_runner_project - end.to change { runner_project.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:found) - expect(runner_project.reload.active).to eq(true) - end - end - - context 'when user is not an owner' do - before do - group.add_maintainer(user) - end - - it 'responds 404 and does not activate the runner' do - runner.update!(active: false) - - expect do - post :resume, params: params - end.not_to change { runner.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:not_found) - expect(runner.reload.active).to eq(false) - end - - it 'responds 404 and does not activate the project runner' do - runner_project.update!(active: false) - - expect do - post :resume, params: params_runner_project - end.not_to change { runner_project.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:not_found) - expect(runner_project.reload.active).to eq(false) - end - end - end - - describe '#pause' do - context 'when user is an owner' do - before do - group.add_owner(user) - end - - it 'marks the runner as inactive, ticks the queue, and redirects' do - runner.update!(active: true) - - expect do - post :pause, params: params - end.to change { runner.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:found) - expect(runner.reload.active).to eq(false) - end - - it 'marks the project runner as inactive, ticks the queue, and redirects' do - runner_project.update!(active: true) - - expect do - post :pause, params: params_runner_project - end.to change { runner_project.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:found) - expect(runner_project.reload.active).to eq(false) - end - end - - context 'when user is not an owner' do - before do - # Disable limit checking - allow(runner).to receive(:runner_scope).and_return(nil) - - group.add_maintainer(user) - end - - it 'responds 404 and does not update the runner or queue' do - runner.update!(active: true) - - expect do - post :pause, params: params - end.not_to change { runner.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:not_found) - expect(runner.reload.active).to eq(true) - end - - it 'responds 404 and does not update the project runner or queue' do - runner_project.update!(active: true) - - expect do - post :pause, params: params - end.not_to change { runner_project.ensure_runner_queue_value } - - expect(response).to have_gitlab_http_status(:not_found) - expect(runner_project.reload.active).to eq(true) - end - end - end end diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb index f225d798886..9aa97c37add 100644 --- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb @@ -6,14 +6,7 @@ RSpec.describe Groups::Settings::CiCdController do include ExternalAuthorizationServiceHelpers let_it_be(:group) { create(:group) } - let_it_be(:sub_group) { create(:group, parent: group) } let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, group: group) } - let_it_be(:project_2) { create(:project, group: sub_group) } - let_it_be(:runner_group) { create(:ci_runner, :group, groups: [group]) } - let_it_be(:runner_project_1) { create(:ci_runner, :project, projects: [project])} - let_it_be(:runner_project_2) { create(:ci_runner, :project, projects: [project_2])} - let_it_be(:runner_project_3) { create(:ci_runner, :project, projects: [project, project_2])} before do sign_in(user) @@ -25,23 +18,11 @@ RSpec.describe Groups::Settings::CiCdController do group.add_owner(user) end - it 'renders show with 200 status code and correct runners' do + it 'renders show with 200 status code' do get :show, params: { group_id: group } expect(response).to have_gitlab_http_status(:ok) expect(response).to render_template(:show) - expect(assigns(:group_runners)).to match_array([runner_group, runner_project_1, runner_project_2, runner_project_3]) - end - - it 'paginates runners' do - stub_const("Groups::Settings::CiCdController::NUMBER_OF_RUNNERS_PER_PAGE", 1) - - create(:ci_runner) - - get :show, params: { group_id: group } - - expect(response).to have_gitlab_http_status(:ok) - expect(assigns(:group_runners).count).to be(1) end end @@ -54,7 +35,6 @@ RSpec.describe Groups::Settings::CiCdController do get :show, params: { group_id: group } expect(response).to have_gitlab_http_status(:not_found) - expect(assigns(:group_runners)).to be_nil end end @@ -72,38 +52,6 @@ RSpec.describe Groups::Settings::CiCdController do end end - describe 'PUT #reset_registration_token' do - subject { put :reset_registration_token, params: { group_id: group } } - - context 'when user is owner' do - before do - group.add_owner(user) - end - - it 'resets runner registration token' do - expect { subject }.to change { group.reload.runners_token } - end - - it 'redirects the user to admin runners page' do - subject - - expect(response).to redirect_to(group_settings_ci_cd_path) - end - end - - context 'when user is not owner' do - before do - group.add_maintainer(user) - end - - it 'renders a 404' do - subject - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - describe 'PATCH #update_auto_devops' do let(:auto_devops_param) { '1' } @@ -236,25 +184,4 @@ RSpec.describe Groups::Settings::CiCdController do end end end - - describe 'GET #runner_setup_scripts' do - before do - group.add_owner(user) - end - - it 'renders the setup scripts' do - get :runner_setup_scripts, params: { os: 'linux', arch: 'amd64', group_id: group } - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to have_key("install") - expect(json_response).to have_key("register") - end - - it 'renders errors if they occur' do - get :runner_setup_scripts, params: { os: 'foo', arch: 'bar', group_id: group } - - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response).to have_key("errors") - end - end end diff --git a/spec/controllers/groups/shared_projects_controller_spec.rb b/spec/controllers/groups/shared_projects_controller_spec.rb index 528d5c073b7..0c5a3b9df08 100644 --- a/spec/controllers/groups/shared_projects_controller_spec.rb +++ b/spec/controllers/groups/shared_projects_controller_spec.rb @@ -12,9 +12,10 @@ RSpec.describe Groups::SharedProjectsController do Projects::GroupLinks::CreateService.new( project, + group, user, link_group_access: Gitlab::Access::DEVELOPER - ).execute(group) + ).execute end let!(:group) { create(:group) } diff --git a/spec/controllers/groups/uploads_controller_spec.rb b/spec/controllers/groups/uploads_controller_spec.rb index 7dafb813545..8fcc3a7fccf 100644 --- a/spec/controllers/groups/uploads_controller_spec.rb +++ b/spec/controllers/groups/uploads_controller_spec.rb @@ -35,6 +35,169 @@ RSpec.describe Groups::UploadsController do end end + describe "GET #show" do + let(:filename) { "rails_sample.jpg" } + let(:user) { create(:user) } + let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } + let(:secret) { FileUploader.generate_secret } + let(:uploader_class) { FileUploader } + + let(:upload_service) do + UploadService.new(model, jpg, uploader_class).execute + end + + let(:show_upload) do + get :show, params: params.merge(secret: secret, filename: filename) + end + + before do + allow(FileUploader).to receive(:generate_secret).and_return(secret) + + allow_next_instance_of(FileUploader) do |instance| + allow(instance).to receive(:image?).and_return(true) + end + + upload_service + end + + context 'when the group is public' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with appropriate status" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + + context 'when the group is private' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with appropriate status" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + end + def post_authorize(verified: true) request.headers.merge!(workhorse_internal_api_request_header) if verified diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index be30011905c..4a74eff90dc 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -18,6 +18,7 @@ RSpec.describe GroupsController, factory_default: :keep do let_it_be(:guest) { group.add_guest(create(:user)).user } before do + stub_feature_flags(vue_issues_list: true) enable_admin_mode!(admin_with_admin_mode) end @@ -71,6 +72,17 @@ RSpec.describe GroupsController, factory_default: :keep do context 'when the group is not importing' do it_behaves_like 'details view' + + it 'tracks page views', :snowplow do + subject + + expect_snowplow_event( + category: 'group_overview', + action: 'render', + user: user, + namespace: group + ) + end end context 'when the group is importing' do @@ -81,6 +93,17 @@ RSpec.describe GroupsController, factory_default: :keep do it 'redirects to the import status page' do expect(subject).to redirect_to group_import_path(group) end + + it 'does not track page views', :snowplow do + subject + + expect_no_snowplow_event( + category: 'group_overview', + action: 'render', + user: user, + namespace: group + ) + end end end @@ -466,53 +489,12 @@ RSpec.describe GroupsController, factory_default: :keep do end end - describe 'GET #issues', :sidekiq_might_not_need_inline do - let_it_be(:issue_1) { create(:issue, project: project, title: 'foo') } - let_it_be(:issue_2) { create(:issue, project: project, title: 'bar') } - + describe 'GET #issues' do before do - create_list(:award_emoji, 3, awardable: issue_2) - create_list(:award_emoji, 2, awardable: issue_1) - create_list(:award_emoji, 2, :downvote, awardable: issue_2) - sign_in(user) end - context 'sorting by votes' do - it 'sorts most popular issues' do - get :issues, params: { id: group.to_param, sort: 'upvotes_desc' } - expect(assigns(:issues)).to eq [issue_2, issue_1] - end - - it 'sorts least popular issues' do - get :issues, params: { id: group.to_param, sort: 'downvotes_desc' } - expect(assigns(:issues)).to eq [issue_2, issue_1] - end - end - - context 'searching' do - it 'works with popularity sort' do - get :issues, params: { id: group.to_param, search: 'foo', sort: 'popularity' } - - expect(assigns(:issues)).to eq([issue_1]) - end - - it 'works with priority sort' do - get :issues, params: { id: group.to_param, search: 'foo', sort: 'priority' } - - expect(assigns(:issues)).to eq([issue_1]) - end - - it 'works with label priority sort' do - get :issues, params: { id: group.to_param, search: 'foo', sort: 'label_priority' } - - expect(assigns(:issues)).to eq([issue_1]) - end - end - it 'saves the sort order to user preferences' do - stub_feature_flags(vue_issues_list: true) - get :issues, params: { id: group.to_param, sort: 'priority' } expect(user.reload.user_preference.issues_sort).to eq('priority') @@ -765,7 +747,7 @@ RSpec.describe GroupsController, factory_default: :keep do end it 'does not update the attribute' do - expect { subject }.not_to change { group.namespace_settings.reload.prevent_sharing_groups_outside_hierarchy } + expect { subject }.not_to change { group.reload.prevent_sharing_groups_outside_hierarchy } expect(response).to have_gitlab_http_status(:not_found) end diff --git a/spec/controllers/jira_connect/events_controller_spec.rb b/spec/controllers/jira_connect/events_controller_spec.rb index 5e90ceb0f9c..80375a02b33 100644 --- a/spec/controllers/jira_connect/events_controller_spec.rb +++ b/spec/controllers/jira_connect/events_controller_spec.rb @@ -27,7 +27,7 @@ RSpec.describe JiraConnect::EventsController do shared_context 'valid JWT token' do before do - allow_next_instance_of(Atlassian::JiraConnect::AsymmetricJwt) do |asymmetric_jwt| + allow_next_instance_of(Atlassian::JiraConnect::Jwt::Asymmetric) do |asymmetric_jwt| allow(asymmetric_jwt).to receive(:valid?).and_return(true) allow(asymmetric_jwt).to receive(:iss_claim).and_return(client_key) end @@ -36,7 +36,7 @@ RSpec.describe JiraConnect::EventsController do shared_context 'invalid JWT token' do before do - allow_next_instance_of(Atlassian::JiraConnect::AsymmetricJwt) do |asymmetric_jwt| + allow_next_instance_of(Atlassian::JiraConnect::Jwt::Asymmetric) do |asymmetric_jwt| allow(asymmetric_jwt).to receive(:valid?).and_return(false) end end diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb index e6553c027d6..7489f506674 100644 --- a/spec/controllers/oauth/authorizations_controller_spec.rb +++ b/spec/controllers/oauth/authorizations_controller_spec.rb @@ -56,27 +56,9 @@ RSpec.describe Oauth::AuthorizationsController do end end - shared_examples "Implicit grant can't be used in confidential application" do - context 'when application is confidential' do - before do - application.update!(confidential: true) - params[:response_type] = 'token' - end - - it 'does not allow the implicit flow' do - subject - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to render_template('doorkeeper/authorizations/error') - end - end - end - describe 'GET #new' do subject { get :new, params: params } - include_examples "Implicit grant can't be used in confidential application" - context 'when the user is confirmed' do context 'when there is already an access token for the application with a matching scope' do before do @@ -219,14 +201,12 @@ RSpec.describe Oauth::AuthorizationsController do subject { post :create, params: params } include_examples 'OAuth Authorizations require confirmed user' - include_examples "Implicit grant can't be used in confidential application" end describe 'DELETE #destroy' do subject { delete :destroy, params: params } include_examples 'OAuth Authorizations require confirmed user' - include_examples "Implicit grant can't be used in confidential application" end it 'includes Two-factor enforcement concern' do diff --git a/spec/controllers/profiles/emails_controller_spec.rb b/spec/controllers/profiles/emails_controller_spec.rb index e41ae406d13..b63db831462 100644 --- a/spec/controllers/profiles/emails_controller_spec.rb +++ b/spec/controllers/profiles/emails_controller_spec.rb @@ -62,7 +62,11 @@ RSpec.describe Profiles::EmailsController do end describe '#resend_confirmation_instructions' do - let_it_be(:email) { create(:email, user: user) } + let_it_be(:email) do + travel_to(5.minutes.ago) do + create(:email, user: user) + end + end let(:params) { { id: email.id } } diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb index 9410fe08d0b..958fcd4360c 100644 --- a/spec/controllers/projects/artifacts_controller_spec.rb +++ b/spec/controllers/projects/artifacts_controller_spec.rb @@ -361,6 +361,7 @@ RSpec.describe Projects::ArtifactsController do subject expect(response).to have_gitlab_http_status(:ok) + expect(response.headers['Gitlab-Workhorse-Detect-Content-Type']).to eq('true') expect(send_data).to start_with('artifacts-entry:') expect(params.keys).to eq(%w(Archive Entry)) diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 1580ad9361d..ed11d5936b0 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -307,17 +307,36 @@ RSpec.describe Projects::BranchesController do sign_in(developer) end - it 'returns 303' do - post :destroy, - format: :html, - params: { - id: 'foo/bar/baz', - namespace_id: project.namespace, - project_id: project - } + subject(:post_request) do + post :destroy, format: :html, params: { + id: 'foo/bar/baz', + namespace_id: project.namespace, + project_id: project + } + end + it "returns response code 303" do + post_request expect(response).to have_gitlab_http_status(:see_other) end + + context 'with http referer' do + before do + request.env['HTTP_REFERER'] = '/' + end + + it "redirects to the referer path" do + post_request + expect(response).to redirect_to('/') + end + end + + context 'without http referer' do + it "redirects to the project branches path" do + post_request + expect(response).to redirect_to(project_branches_path(project)) + end + end end describe "POST destroy" do diff --git a/spec/controllers/projects/ci/secure_files_controller_spec.rb b/spec/controllers/projects/ci/secure_files_controller_spec.rb index 1138897bcc6..200997e31b9 100644 --- a/spec/controllers/projects/ci/secure_files_controller_spec.rb +++ b/spec/controllers/projects/ci/secure_files_controller_spec.rb @@ -9,17 +9,35 @@ RSpec.describe Projects::Ci::SecureFilesController do subject(:show_request) { get :show, params: { namespace_id: project.namespace, project_id: project } } describe 'GET #show' do - context 'with enough privileges' do - before do - sign_in(user) - project.add_developer(user) - show_request + context 'when the :ci_secure_files feature flag is enabled' do + context 'with enough privileges' do + before do + stub_feature_flags(ci_secure_files: true) + sign_in(user) + project.add_developer(user) + show_request + end + + it { expect(response).to have_gitlab_http_status(:ok) } + + it 'renders show page' do + expect(response).to render_template :show + end end + end - it { expect(response).to have_gitlab_http_status(:ok) } + context 'when the :ci_secure_files feature flag is disabled' do + context 'with enough privileges' do + before do + stub_feature_flags(ci_secure_files: false) + sign_in(user) + project.add_developer(user) + show_request + end - it 'renders show page' do - expect(response).to render_template :show + it 'responds with 404' do + expect(response).to have_gitlab_http_status(:not_found) + end end end diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb index 44bdc958805..01420e30d24 100644 --- a/spec/controllers/projects/clusters_controller_spec.rb +++ b/spec/controllers/projects/clusters_controller_spec.rb @@ -113,103 +113,6 @@ RSpec.describe Projects::ClustersController do end end - describe 'GET new' do - def go(provider: 'gcp') - get :new, params: { - namespace_id: project.namespace, - project_id: project, - provider: provider - } - end - - include_examples ':certificate_based_clusters feature flag controller responses' do - let(:subject) { go } - end - - describe 'functionality for new cluster' do - context 'when omniauth has been configured' do - let(:key) { 'secret-key' } - let(:session_key_for_redirect_uri) do - GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key) - end - - before do - allow(SecureRandom).to receive(:hex).and_return(key) - end - - it 'redirects to gcp authorize_url' do - go - - expect(assigns(:authorize_url)).to include(key) - expect(session[session_key_for_redirect_uri]).to eq(new_project_cluster_path(project, provider: :gcp)) - expect(response).to redirect_to(assigns(:authorize_url)) - end - end - - context 'when omniauth has not configured' do - before do - stub_omniauth_setting(providers: []) - end - - it 'does not have authorize_url' do - go - - expect(assigns(:authorize_url)).to be_nil - end - end - - context 'when access token is valid' do - before do - stub_google_api_validate_token - end - - it 'has new object' do - go - - expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::ClusterPresenter) - end - end - - context 'when access token is expired' do - before do - stub_google_api_expired_token - end - - it { expect(@valid_gcp_token).to be_falsey } - end - - context 'when access token is not stored in session' do - it { expect(@valid_gcp_token).to be_falsey } - end - end - - describe 'functionality for existing cluster' do - it 'has new object' do - go - - expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::ClusterPresenter) - end - end - - include_examples 'GET new cluster shared examples' - - describe 'security' do - it 'is allowed for admin when admin mode enabled', :enable_admin_mode do - expect { go }.to be_allowed_for(:admin) - end - it 'is disabled for admin when admin mode disabled' do - expect { go }.to be_denied_for(:admin) - end - it { expect { go }.to be_allowed_for(:owner).of(project) } - it { expect { go }.to be_allowed_for(:maintainer).of(project) } - it { expect { go }.to be_denied_for(:developer).of(project) } - it { expect { go }.to be_denied_for(:reporter).of(project) } - it { expect { go }.to be_denied_for(:guest).of(project) } - it { expect { go }.to be_denied_for(:user) } - it { expect { go }.to be_denied_for(:external) } - end - end - describe 'GET #prometheus_proxy' do let(:proxyable) do create(:cluster, :provided_by_gcp, projects: [project]) @@ -252,107 +155,6 @@ RSpec.describe Projects::ClustersController do end end - describe 'POST create for new cluster' do - let(:legacy_abac_param) { 'true' } - let(:params) do - { - cluster: { - name: 'new-cluster', - managed: '1', - namespace_per_environment: '0', - provider_gcp_attributes: { - gcp_project_id: 'gcp-project-12345', - legacy_abac: legacy_abac_param - } - } - } - end - - def go - post :create_gcp, params: params.merge(namespace_id: project.namespace, project_id: project) - end - - include_examples ':certificate_based_clusters feature flag controller responses' do - let(:subject) { go } - end - - describe 'functionality' do - context 'when access token is valid' do - before do - stub_google_api_validate_token - end - - it 'creates a new cluster' do - expect(ClusterProvisionWorker).to receive(:perform_async) - expect { go }.to change { Clusters::Cluster.count } - .and change { Clusters::Providers::Gcp.count } - expect(response).to redirect_to(project_cluster_path(project, project.clusters.first)) - expect(project.clusters.first).to be_gcp - expect(project.clusters.first).to be_kubernetes - expect(project.clusters.first.provider_gcp).to be_legacy_abac - expect(project.clusters.first.managed?).to be_truthy - expect(project.clusters.first.namespace_per_environment?).to be_falsy - end - - context 'when legacy_abac param is false' do - let(:legacy_abac_param) { 'false' } - - it 'creates a new cluster with legacy_abac_disabled' do - expect(ClusterProvisionWorker).to receive(:perform_async) - expect { go }.to change { Clusters::Cluster.count } - .and change { Clusters::Providers::Gcp.count } - expect(project.clusters.first.provider_gcp).not_to be_legacy_abac - end - end - end - - context 'when access token is expired' do - before do - stub_google_api_expired_token - end - - it { expect(@valid_gcp_token).to be_falsey } - end - - context 'when access token is not stored in session' do - it { expect(@valid_gcp_token).to be_falsey } - end - end - - describe 'security' do - before do - allow_any_instance_of(described_class) - .to receive(:token_in_session).and_return('token') - allow_any_instance_of(described_class) - .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s) - allow_any_instance_of(GoogleApi::CloudPlatform::Client) - .to receive(:projects_zones_clusters_create) do - double( - 'secure', - self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', - status: 'RUNNING' - ) - end - - allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil) - end - - it 'is allowed for admin when admin mode enabled', :enable_admin_mode do - expect { go }.to be_allowed_for(:admin) - end - it 'is disabled for admin when admin mode disabled' do - expect { go }.to be_denied_for(:admin) - end - it { expect { go }.to be_allowed_for(:owner).of(project) } - it { expect { go }.to be_allowed_for(:maintainer).of(project) } - it { expect { go }.to be_denied_for(:developer).of(project) } - it { expect { go }.to be_denied_for(:reporter).of(project) } - it { expect { go }.to be_denied_for(:guest).of(project) } - it { expect { go }.to be_denied_for(:user) } - it { expect { go }.to be_denied_for(:external) } - end - end - describe 'POST create for existing cluster' do let(:params) do { diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index f4cad5790a3..f63e0cea04c 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -208,6 +208,17 @@ RSpec.describe Projects::EnvironmentsController do expect(response).to have_gitlab_http_status(:not_found) end end + + it_behaves_like 'avoids N+1 queries on environment detail page' + + def create_deployment_with_associations(sequence:) + commit = project.commit("HEAD~#{sequence}") + create(:user, email: commit.author_email) + + deployer = create(:user) + build = create(:ci_build, environment: environment.name, pipeline: create(:ci_pipeline, project: environment.project), user: deployer) + create(:deployment, :success, environment: environment, deployable: build, user: deployer, project: project, sha: commit.sha) + end end describe 'GET edit' do diff --git a/spec/controllers/projects/error_tracking/projects_controller_spec.rb b/spec/controllers/projects/error_tracking/projects_controller_spec.rb index 67947d1c9d9..7529c701b2b 100644 --- a/spec/controllers/projects/error_tracking/projects_controller_spec.rb +++ b/spec/controllers/projects/error_tracking/projects_controller_spec.rb @@ -6,18 +6,21 @@ RSpec.describe Projects::ErrorTracking::ProjectsController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } + before_all do + project.add_maintainer(user) + end + before do sign_in(user) - project.add_maintainer(user) end describe 'GET #index' do context 'with insufficient permissions' do - before do - project.add_guest(user) - end + let(:user) { create(:user) } it 'returns 404' do + project.add_guest(user) + get :index, params: list_projects_params expect(response).to have_gitlab_http_status(:not_found) @@ -37,8 +40,8 @@ RSpec.describe Projects::ErrorTracking::ProjectsController do end context 'with authorized user' do - let(:list_projects_service) { spy(:list_projects_service) } - let(:sentry_project) { build(:error_tracking_project) } + let(:list_projects_service) { instance_double('ErrorTracking::ListProjectsService') } + let(:sentry_project) { build_stubbed(:error_tracking_project) } let(:query_params) do list_projects_params.slice(:api_host, :token) @@ -50,9 +53,9 @@ RSpec.describe Projects::ErrorTracking::ProjectsController do .and_return(list_projects_service) end - context 'service result is successful' do + context 'when service result is successful' do before do - expect(list_projects_service).to receive(:execute) + allow(list_projects_service).to receive(:execute) .and_return(status: :success, projects: [sentry_project]) end @@ -65,12 +68,12 @@ RSpec.describe Projects::ErrorTracking::ProjectsController do end end - context 'service result is erroneous' do + context 'with service result is erroneous' do let(:error_message) { 'error message' } context 'without http_status' do before do - expect(list_projects_service).to receive(:execute) + allow(list_projects_service).to receive(:execute) .and_return(status: :error, message: error_message) end @@ -86,7 +89,7 @@ RSpec.describe Projects::ErrorTracking::ProjectsController do let(:http_status) { :no_content } before do - expect(list_projects_service).to receive(:execute).and_return( + allow(list_projects_service).to receive(:execute).and_return( status: :error, message: error_message, http_status: http_status @@ -106,11 +109,7 @@ RSpec.describe Projects::ErrorTracking::ProjectsController do private def list_projects_params(opts = {}) - project_params( - format: :json, - api_host: 'gitlab.com', - token: 'token' - ) + project_params(format: :json, api_host: 'gitlab.com', token: 'token') end end diff --git a/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb b/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb index 19b6b597a84..e011428adde 100644 --- a/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb +++ b/spec/controllers/projects/error_tracking/stack_traces_controller_spec.rb @@ -6,30 +6,34 @@ RSpec.describe Projects::ErrorTracking::StackTracesController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } + before_all do + project.add_maintainer(user) + end + before do sign_in(user) - project.add_maintainer(user) end describe 'GET #index' do let(:issue_id) { non_existing_record_id } - let(:issue_stack_trace_service) { spy(:issue_stack_trace_service) } + let(:issue_latest_event_service) { instance_double('ErrorTracking::IssueLatestEventService') } subject(:get_stack_trace) do get :index, params: { namespace_id: project.namespace, project_id: project, issue_id: issue_id, format: :json } end before do - expect(ErrorTracking::IssueLatestEventService) + allow(ErrorTracking::IssueLatestEventService) .to receive(:new).with(project, user, issue_id: issue_id.to_s) - .and_return(issue_stack_trace_service) - expect(issue_stack_trace_service).to receive(:execute).and_return(service_response) + .and_return(issue_latest_event_service) + + allow(issue_latest_event_service).to receive(:execute).and_return(service_response) get_stack_trace end - context 'awaiting data' do - let(:service_response) { { status: :error, http_status: :no_content }} + context 'when awaiting data' do + let(:service_response) { { status: :error, http_status: :no_content } } it 'responds with no data' do expect(response).to have_gitlab_http_status(:no_content) @@ -38,19 +42,14 @@ RSpec.describe Projects::ErrorTracking::StackTracesController do it_behaves_like 'sets the polling header' end - context 'service result is successful' do + context 'when service result is successful' do let(:service_response) { { status: :success, latest_event: error_event } } - let(:error_event) { build(:error_tracking_sentry_error_event) } + let(:error_event) { build_stubbed(:error_tracking_sentry_error_event) } - it 'responds with success' do + it 'highlights stack trace source code' do expect(response).to have_gitlab_http_status(:ok) - end - - it 'responds with error' do expect(response).to match_response_schema('error_tracking/issue_stack_trace') - end - it 'highlights stack trace source code' do expect(json_response['error']).to eq( Gitlab::ErrorTracking::StackTraceHighlightDecorator.decorate(error_event).as_json ) @@ -59,7 +58,7 @@ RSpec.describe Projects::ErrorTracking::StackTracesController do it_behaves_like 'sets the polling header' end - context 'service result is erroneous' do + context 'when service result is erroneous' do let(:error_message) { 'error message' } context 'without http_status' do @@ -67,9 +66,6 @@ RSpec.describe Projects::ErrorTracking::StackTracesController do it 'responds with bad request' do expect(response).to have_gitlab_http_status(:bad_request) - end - - it 'responds with error message' do expect(json_response['message']).to eq(error_message) end end @@ -80,9 +76,6 @@ RSpec.describe Projects::ErrorTracking::StackTracesController do it 'responds with custom http status' do expect(response).to have_gitlab_http_status(http_status) - end - - it 'responds with error message' do expect(json_response['message']).to eq(error_message) end end diff --git a/spec/controllers/projects/error_tracking_controller_spec.rb b/spec/controllers/projects/error_tracking_controller_spec.rb index b4f21e070c6..cf0e481495c 100644 --- a/spec/controllers/projects/error_tracking_controller_spec.rb +++ b/spec/controllers/projects/error_tracking_controller_spec.rb @@ -6,9 +6,12 @@ RSpec.describe Projects::ErrorTrackingController do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } + before_all do + project.add_maintainer(user) + end + before do sign_in(user) - project.add_maintainer(user) end describe 'GET #index' do @@ -46,18 +49,18 @@ RSpec.describe Projects::ErrorTrackingController do end describe 'format json' do - let(:list_issues_service) { spy(:list_issues_service) } + let(:list_issues_service) { instance_double('ErrorTracking::ListIssuesService') } let(:external_url) { 'http://example.com' } - context 'no data' do + context 'with no data' do let(:permitted_params) { permit_index_parameters!({}) } before do - expect(ErrorTracking::ListIssuesService) + allow(ErrorTracking::ListIssuesService) .to receive(:new).with(project, user, permitted_params) .and_return(list_issues_service) - expect(list_issues_service).to receive(:execute) + allow(list_issues_service).to receive(:execute) .and_return(status: :error, http_status: :no_content) end @@ -76,22 +79,22 @@ RSpec.describe Projects::ErrorTrackingController do let(:permitted_params) { permit_index_parameters!(search_term: search_term, sort: sort, cursor: cursor) } before do - expect(ErrorTracking::ListIssuesService) + allow(ErrorTracking::ListIssuesService) .to receive(:new).with(project, user, permitted_params) .and_return(list_issues_service) end - context 'service result is successful' do + context 'when service result is successful' do before do - expect(list_issues_service).to receive(:execute) + allow(list_issues_service).to receive(:execute) .and_return(status: :success, issues: [error], pagination: {}) - expect(list_issues_service).to receive(:external_url) + allow(list_issues_service).to receive(:external_url) .and_return(external_url) get :index, params: params end - let(:error) { build(:error_tracking_sentry_error) } + let(:error) { build_stubbed(:error_tracking_sentry_error) } it 'returns a list of errors' do expect(response).to have_gitlab_http_status(:ok) @@ -109,16 +112,16 @@ RSpec.describe Projects::ErrorTrackingController do context 'without extra params' do before do - expect(ErrorTracking::ListIssuesService) + allow(ErrorTracking::ListIssuesService) .to receive(:new).with(project, user, permit_index_parameters!({})) .and_return(list_issues_service) end - context 'service result is successful' do + context 'when service result is successful' do before do - expect(list_issues_service).to receive(:execute) + allow(list_issues_service).to receive(:execute) .and_return(status: :success, issues: [error], pagination: {}) - expect(list_issues_service).to receive(:external_url) + allow(list_issues_service).to receive(:external_url) .and_return(external_url) end @@ -137,12 +140,12 @@ RSpec.describe Projects::ErrorTrackingController do end end - context 'service result is erroneous' do + context 'when service result is erroneous' do let(:error_message) { 'error message' } context 'without http_status' do before do - expect(list_issues_service).to receive(:execute) + allow(list_issues_service).to receive(:execute) .and_return(status: :error, message: error_message) end @@ -158,7 +161,7 @@ RSpec.describe Projects::ErrorTrackingController do let(:http_status) { :no_content } before do - expect(list_issues_service).to receive(:execute).and_return( + allow(list_issues_service).to receive(:execute).and_return( status: :error, message: error_message, http_status: http_status @@ -189,7 +192,7 @@ RSpec.describe Projects::ErrorTrackingController do describe 'GET #issue_details' do let_it_be(:issue_id) { non_existing_record_id } - let(:issue_details_service) { spy(:issue_details_service) } + let(:issue_details_service) { instance_double('ErrorTracking::IssueDetailsService') } let(:permitted_params) do ActionController::Parameters.new( @@ -199,15 +202,15 @@ RSpec.describe Projects::ErrorTrackingController do end before do - expect(ErrorTracking::IssueDetailsService) + allow(ErrorTracking::IssueDetailsService) .to receive(:new).with(project, user, permitted_params) .and_return(issue_details_service) end describe 'format json' do - context 'no data' do + context 'with no data' do before do - expect(issue_details_service).to receive(:execute) + allow(issue_details_service).to receive(:execute) .and_return(status: :error, http_status: :no_content) get :details, params: issue_params(issue_id: issue_id, format: :json) end @@ -219,15 +222,15 @@ RSpec.describe Projects::ErrorTrackingController do it_behaves_like 'sets the polling header' end - context 'service result is successful' do + context 'when service result is successful' do before do - expect(issue_details_service).to receive(:execute) + allow(issue_details_service).to receive(:execute) .and_return(status: :success, issue: error) get :details, params: issue_params(issue_id: issue_id, format: :json) end - let(:error) { build(:error_tracking_sentry_detailed_error) } + let(:error) { build_stubbed(:error_tracking_sentry_detailed_error) } it 'returns an error' do expected_error = error.as_json.except('first_release_version').merge( @@ -245,12 +248,12 @@ RSpec.describe Projects::ErrorTrackingController do it_behaves_like 'sets the polling header' end - context 'service result is erroneous' do + context 'when service result is erroneous' do let(:error_message) { 'error message' } context 'without http_status' do before do - expect(issue_details_service).to receive(:execute) + allow(issue_details_service).to receive(:execute) .and_return(status: :error, message: error_message) end @@ -266,7 +269,7 @@ RSpec.describe Projects::ErrorTrackingController do let(:http_status) { :no_content } before do - expect(issue_details_service).to receive(:execute).and_return( + allow(issue_details_service).to receive(:execute).and_return( status: :error, message: error_message, http_status: http_status @@ -286,7 +289,7 @@ RSpec.describe Projects::ErrorTrackingController do describe 'PUT #update' do let(:issue_id) { non_existing_record_id } - let(:issue_update_service) { spy(:issue_update_service) } + let(:issue_update_service) { instance_double('ErrorTracking::IssueUpdateService') } let(:permitted_params) do ActionController::Parameters.new( { issue_id: issue_id.to_s, status: 'resolved' } @@ -298,15 +301,15 @@ RSpec.describe Projects::ErrorTrackingController do end before do - expect(ErrorTracking::IssueUpdateService) + allow(ErrorTracking::IssueUpdateService) .to receive(:new).with(project, user, permitted_params) .and_return(issue_update_service) end describe 'format json' do - context 'update result is successful' do + context 'when update result is successful' do before do - expect(issue_update_service).to receive(:execute) + allow(issue_update_service).to receive(:execute) .and_return(status: :success, updated: true, closed_issue_iid: non_existing_record_iid) update_issue @@ -318,11 +321,11 @@ RSpec.describe Projects::ErrorTrackingController do end end - context 'update result is erroneous' do + context 'when update result is erroneous' do let(:error_message) { 'error message' } before do - expect(issue_update_service).to receive(:execute) + allow(issue_update_service).to receive(:execute) .and_return(status: :error, message: error_message) update_issue diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index ce0af784cdf..8a03c1e709b 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -12,6 +12,10 @@ RSpec.describe Projects::IssuesController do let(:issue) { create(:issue, project: project) } let(:spam_action_response_fields) { { 'stub_spam_action_response_fields' => true } } + before do + stub_feature_flags(vue_issues_list: true) + end + describe "GET #index" do context 'external issue tracker' do before do @@ -72,22 +76,6 @@ RSpec.describe Projects::IssuesController do project.add_developer(user) end - context 'when issues_full_text_search is disabled' do - before do - stub_feature_flags(issues_full_text_search: false) - end - - it_behaves_like 'issuables list meta-data', :issue - end - - context 'when issues_full_text_search is enabled' do - before do - stub_feature_flags(issues_full_text_search: true) - end - - it_behaves_like 'issuables list meta-data', :issue - end - it_behaves_like 'set sort order from user preference' do let(:sorting_param) { 'updated_asc' } end @@ -98,16 +86,6 @@ RSpec.describe Projects::IssuesController do expect(response).to have_gitlab_http_status(:ok) end - it 'returns only list type issues' do - issue = create(:issue, project: project) - incident = create(:issue, project: project, issue_type: 'incident') - create(:issue, project: project, issue_type: 'test_case') - - get :index, params: { namespace_id: project.namespace, project_id: project } - - expect(assigns(:issues)).to contain_exactly(issue, incident) - end - it "returns 301 if request path doesn't match project path" do get :index, params: { namespace_id: project.namespace, project_id: project.path.upcase } @@ -123,17 +101,10 @@ RSpec.describe Projects::IssuesController do end end - it_behaves_like 'issuable list with anonymous search disabled' do - let(:params) { { namespace_id: project.namespace, project_id: project } } - - before do - project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) - end - end - - it_behaves_like 'paginated collection' do + describe 'pagination' do let!(:issue_list) { create_list(:issue, 2, project: project) } let(:collection) { project.issues } + let(:last_page) { collection.page.total_pages } let(:params) do { namespace_id: project.namespace.to_param, @@ -154,46 +125,6 @@ RSpec.describe Projects::IssuesController do expect(response).to have_gitlab_http_status(:redirect) expect(response).to redirect_to(action: 'index', format: 'atom', page: last_page, state: 'opened') end - - it 'does not use pagination if disabled' do - allow(controller).to receive(:pagination_disabled?).and_return(true) - - get :index, params: params.merge(page: last_page + 1) - - expect(response).to have_gitlab_http_status(:ok) - expect(assigns(:issues).size).to eq(2) - end - end - - context 'with relative_position sorting' do - let!(:issue_list) { create_list(:issue, 2, project: project) } - - before do - sign_in(user) - project.add_developer(user) - allow(Kaminari.config).to receive(:default_per_page).and_return(1) - end - - it 'overrides the number allowed on the page' do - get :index, - params: { - namespace_id: project.namespace.to_param, - project_id: project, - sort: 'relative_position' - } - - expect(assigns(:issues).count).to eq 2 - end - - it 'allows the default number on the page' do - get :index, - params: { - namespace_id: project.namespace.to_param, - project_id: project - } - - expect(assigns(:issues).count).to eq 1 - end end context 'external authorization' do @@ -746,84 +677,6 @@ RSpec.describe Projects::IssuesController do let_it_be(:unescaped_parameter_value) { create(:issue, :confidential, project: project, author: author) } let_it_be(:request_forgery_timing_attack) { create(:issue, :confidential, project: project, assignees: [assignee]) } - describe 'GET #index' do - it 'does not list confidential issues for guests' do - sign_out(:user) - get_issues - - expect(assigns(:issues)).to eq [issue] - end - - it 'does not list confidential issues for non project members' do - sign_in(non_member) - get_issues - - expect(assigns(:issues)).to eq [issue] - end - - it 'does not list confidential issues for project members with guest role' do - sign_in(member) - project.add_guest(member) - - get_issues - - expect(assigns(:issues)).to eq [issue] - end - - it 'lists confidential issues for author' do - sign_in(author) - get_issues - - expect(assigns(:issues)).to include unescaped_parameter_value - expect(assigns(:issues)).not_to include request_forgery_timing_attack - end - - it 'lists confidential issues for assignee' do - sign_in(assignee) - get_issues - - expect(assigns(:issues)).not_to include unescaped_parameter_value - expect(assigns(:issues)).to include request_forgery_timing_attack - end - - it 'lists confidential issues for project members' do - sign_in(member) - project.add_developer(member) - - get_issues - - expect(assigns(:issues)).to include unescaped_parameter_value - expect(assigns(:issues)).to include request_forgery_timing_attack - end - - context 'when admin mode is enabled', :enable_admin_mode do - it 'lists confidential issues for admin' do - sign_in(admin) - get_issues - - expect(assigns(:issues)).to include unescaped_parameter_value - expect(assigns(:issues)).to include request_forgery_timing_attack - end - end - - context 'when admin mode is disabled' do - it 'does not list confidential issues for admin' do - sign_in(admin) - get_issues - - expect(assigns(:issues)).to eq [issue] - end - end - - def get_issues - get :index, - params: { - namespace_id: project.namespace.to_param, - project_id: project - } - end - end - shared_examples_for 'restricted action' do |http_status| it 'returns 404 for guests' do sign_out(:user) diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb index e9f1232b5e7..162c36f5069 100644 --- a/spec/controllers/projects/jobs_controller_spec.rb +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -929,13 +929,13 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do context 'when continue url is present' do let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) } + before do + post_cancel(continue: { to: url }) + end + context 'when continue to is a safe url' do let(:url) { '/test' } - before do - post_cancel(continue: { to: url }) - end - it 'redirects to the continue url' do expect(response).to have_gitlab_http_status(:found) expect(response).to redirect_to(url) @@ -949,8 +949,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do context 'when continue to is not a safe url' do let(:url) { 'http://example.com' } - it 'raises an error' do - expect { cancel_with_redirect(url) }.to raise_error + it 'redirects to the builds page' do + expect(response).to have_gitlab_http_status(:found) + expect(response).to redirect_to(builds_namespace_project_pipeline_path(id: pipeline.id)) end end end diff --git a/spec/controllers/projects/logs_controller_spec.rb b/spec/controllers/projects/logs_controller_spec.rb index d5c602df41d..1c81ae93b42 100644 --- a/spec/controllers/projects/logs_controller_spec.rb +++ b/spec/controllers/projects/logs_controller_spec.rb @@ -47,6 +47,20 @@ RSpec.describe Projects::LogsController do expect(response).to be_ok expect(response).to render_template 'index' end + + context 'with feature flag disabled' do + before do + stub_feature_flags(monitor_logging: false) + end + + it 'returns 404 with reporter access' do + project.add_developer(user) + + get :index, params: environment_params + + expect(response).to have_gitlab_http_status(:not_found) + end + end end shared_examples 'pod logs service' do |endpoint, service| @@ -103,14 +117,6 @@ RSpec.describe Projects::LogsController do expect(json_response).to eq(service_result_json) end - it 'registers a usage of the endpoint' do - expect(::Gitlab::UsageCounters::PodLogs).to receive(:increment).with(project.id) - - get endpoint, params: environment_params(pod_name: pod_name, format: :json) - - expect(response).to have_gitlab_http_status(:success) - end - it 'sets the polling header' do get endpoint, params: environment_params(pod_name: pod_name, format: :json) diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index 8fae82d54a2..1be4177acd1 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -19,6 +19,27 @@ RSpec.describe Projects::PipelinesController do sign_in(user) end + shared_examples 'the show page' do |param| + it 'redirects to pipeline path with param' do + get param, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + + expect(response).to redirect_to(pipeline_path(pipeline, tab: param)) + end + + context 'when the FF pipeline_tabs_vue is disabled' do + before do + stub_feature_flags(pipeline_tabs_vue: false) + end + + it 'renders the show template' do + get param, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show + end + end + end + describe 'GET index.json' do before do create_all_pipeline_types @@ -625,6 +646,12 @@ RSpec.describe Projects::PipelinesController do end end + describe 'GET dag' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + it_behaves_like 'the show page', 'dag' + end + describe 'GET dag.json' do let(:pipeline) { create(:ci_pipeline, project: project) } @@ -658,6 +685,49 @@ RSpec.describe Projects::PipelinesController do end end + describe 'GET builds' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + it_behaves_like 'the show page', 'builds' + end + + describe 'GET failures' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + context 'with ff `pipeline_tabs_vue` disabled' do + before do + stub_feature_flags(pipeline_tabs_vue: false) + end + + context 'with failed jobs' do + before do + create(:ci_build, :failed, pipeline: pipeline, name: 'hello') + end + + it 'shows the page' do + get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template :show + end + end + + context 'without failed jobs' do + it 'redirects to the main pipeline page' do + get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + + expect(response).to redirect_to(pipeline_path(pipeline)) + end + end + end + + it 'redirects to the pipeline page with `failures` query param' do + get :failures, params: { namespace_id: project.namespace, project_id: project, id: pipeline } + + expect(response).to redirect_to(pipeline_path(pipeline, tab: 'failures')) + end + end + describe 'GET stages.json' do let(:pipeline) { create(:ci_pipeline, project: project) } @@ -988,6 +1058,12 @@ RSpec.describe Projects::PipelinesController do end end + describe 'GET test_report' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + it_behaves_like 'the show page', 'test_report' + end + describe 'GET test_report.json' do let(:pipeline) { create(:ci_pipeline, project: project) } diff --git a/spec/controllers/projects/prometheus/alerts_controller_spec.rb b/spec/controllers/projects/prometheus/alerts_controller_spec.rb index d66ad445c32..f42119e7811 100644 --- a/spec/controllers/projects/prometheus/alerts_controller_spec.rb +++ b/spec/controllers/projects/prometheus/alerts_controller_spec.rb @@ -226,137 +226,6 @@ RSpec.describe Projects::Prometheus::AlertsController do end end - describe 'POST #create' do - let(:schedule_update_service) { spy } - - let(:alert_params) do - { - 'title' => metric.title, - 'query' => metric.query, - 'operator' => '>', - 'threshold' => 1.0, - 'runbook_url' => 'https://sample.runbook.com' - } - end - - def make_request(opts = {}) - post :create, params: request_params( - opts, - operator: '>', - threshold: '1', - runbook_url: 'https://sample.runbook.com', - environment_id: environment, - prometheus_metric_id: metric - ) - end - - it 'creates a new prometheus alert' do - allow(::Clusters::Applications::ScheduleUpdateService) - .to receive(:new).and_return(schedule_update_service) - - make_request - - expect(schedule_update_service).to have_received(:execute) - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to include(alert_params) - end - - it 'returns bad_request for an invalid metric' do - make_request(prometheus_metric_id: 'invalid') - - expect(response).to have_gitlab_http_status(:bad_request) - end - - it_behaves_like 'unprivileged' - it_behaves_like 'project non-specific environment', :bad_request - end - - describe 'PUT #update' do - let(:schedule_update_service) { spy } - - let(:alert) do - create(:prometheus_alert, - project: project, - environment: environment, - prometheus_metric: metric) - end - - let(:alert_params) do - { - 'id' => alert.id, - 'title' => alert.title, - 'query' => alert.query, - 'operator' => '<', - 'threshold' => alert.threshold, - 'alert_path' => alert_path(alert) - } - end - - before do - allow(::Clusters::Applications::ScheduleUpdateService) - .to receive(:new).and_return(schedule_update_service) - end - - def make_request(opts = {}) - put :update, params: request_params( - opts, - id: alert.prometheus_metric_id, - operator: '<', - environment_id: alert.environment - ) - end - - it 'updates an already existing prometheus alert' do - expect { make_request(operator: '<') } - .to change { alert.reload.operator }.to('lt') - - expect(schedule_update_service).to have_received(:execute) - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to include(alert_params) - end - - it 'returns bad_request for an invalid alert data' do - make_request(runbook_url: 'bad-url') - - expect(response).to have_gitlab_http_status(:bad_request) - end - - it_behaves_like 'unprivileged' - it_behaves_like 'project non-specific environment', :not_found - it_behaves_like 'project non-specific metric', :not_found - end - - describe 'DELETE #destroy' do - let(:schedule_update_service) { spy } - - let!(:alert) do - create(:prometheus_alert, project: project, prometheus_metric: metric) - end - - before do - allow(::Clusters::Applications::ScheduleUpdateService) - .to receive(:new).and_return(schedule_update_service) - end - - def make_request(opts = {}) - delete :destroy, params: request_params( - opts, - id: alert.prometheus_metric_id, - environment_id: alert.environment - ) - end - - it 'destroys the specified prometheus alert' do - expect { make_request }.to change { PrometheusAlert.count }.by(-1) - - expect(schedule_update_service).to have_received(:execute) - end - - it_behaves_like 'unprivileged' - it_behaves_like 'project non-specific environment', :not_found - it_behaves_like 'project non-specific metric', :not_found - end - describe 'GET #metrics_dashboard' do let!(:alert) do create(:prometheus_alert, diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb index 9dd18e58109..0dba7dab643 100644 --- a/spec/controllers/projects/releases_controller_spec.rb +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -78,14 +78,12 @@ RSpec.describe Projects::ReleasesController do end describe 'GET #index' do - before do - get_index - end - context 'as html' do let(:format) { :html } it 'returns a text/html content_type' do + get_index + expect(response.media_type).to eq 'text/html' end @@ -95,6 +93,8 @@ RSpec.describe Projects::ReleasesController do let(:project) { private_project } it 'returns a redirect' do + get_index + expect(response).to have_gitlab_http_status(:redirect) end end @@ -104,11 +104,24 @@ RSpec.describe Projects::ReleasesController do let(:format) { :json } it 'returns an application/json content_type' do + get_index + expect(response.media_type).to eq 'application/json' end it "returns the project's releases as JSON, ordered by released_at" do - expect(response.body).to eq([release_2, release_1].to_json) + get_index + + expect(json_response.map { |release| release["id"] } ).to eq([release_2.id, release_1.id]) + end + + # TODO: remove in https://gitlab.com/gitlab-org/gitlab/-/issues/360903 + it "returns release sha when remove_sha_from_releases_json is disabled" do + stub_feature_flags(remove_sha_from_releases_json: false) + + get_index + + expect(json_response).to eq([release_2, release_1].as_json) end it_behaves_like 'common access controls' @@ -117,6 +130,8 @@ RSpec.describe Projects::ReleasesController do let(:project) { private_project } it 'returns a redirect' do + get_index + expect(response).to have_gitlab_http_status(:redirect) end end diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb deleted file mode 100644 index f8cee09006c..00000000000 --- a/spec/controllers/projects/serverless/functions_controller_spec.rb +++ /dev/null @@ -1,341 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Projects::Serverless::FunctionsController do - include KubernetesHelpers - include ReactiveCachingHelpers - - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:cluster) { create(:cluster, :project, :provided_by_gcp, projects: [project]) } - let(:service) { cluster.platform_kubernetes } - let(:environment) { create(:environment, project: project) } - let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) } - let(:knative_services_finder) { environment.knative_services_finder } - let(:function_description) { 'A serverless function' } - let(:function_name) { 'some-function-name' } - let(:knative_stub_options) do - { namespace: namespace.namespace, name: function_name, description: function_description } - end - - let(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } - - let(:namespace) do - create(:cluster_kubernetes_namespace, - cluster: cluster, - cluster_project: cluster.cluster_project, - project: cluster.cluster_project.project, - environment: environment) - end - - before do - project.add_maintainer(user) - sign_in(user) - end - - def params(opts = {}) - opts.reverse_merge(namespace_id: project.namespace.to_param, - project_id: project.to_param) - end - - shared_examples_for 'behind :deprecated_serverless feature flag' do - before do - stub_feature_flags(deprecated_serverless: false) - end - - it 'returns 404' do - action - expect(response).to have_gitlab_http_status(:not_found) - end - end - - describe 'GET #index' do - let(:expected_json) { { 'knative_installed' => knative_state, 'functions' => functions } } - - it_behaves_like 'behind :deprecated_serverless feature flag' do - let(:action) { get :index, params: params({ format: :json }) } - end - - context 'when cache is being read' do - let(:knative_state) { 'checking' } - let(:functions) { [] } - - before do - get :index, params: params({ format: :json }) - end - - it 'returns checking' do - expect(json_response).to eq expected_json - end - - it { expect(response).to have_gitlab_http_status(:ok) } - end - - context 'when cache is ready' do - let(:knative_state) { true } - - before do - allow(Clusters::KnativeServicesFinder) - .to receive(:new) - .and_return(knative_services_finder) - synchronous_reactive_cache(knative_services_finder) - stub_kubeclient_service_pods( - kube_response({ "kind" => "PodList", "items" => [] }), - namespace: namespace.namespace - ) - end - - context 'when no functions were found' do - let(:functions) { [] } - - before do - stub_kubeclient_knative_services( - namespace: namespace.namespace, - response: kube_response({ "kind" => "ServiceList", "items" => [] }) - ) - get :index, params: params({ format: :json }) - end - - it 'returns checking' do - expect(json_response).to eq expected_json - end - - it { expect(response).to have_gitlab_http_status(:ok) } - end - - context 'when functions were found' do - let(:functions) { [{}, {}] } - - before do - stub_kubeclient_knative_services(namespace: namespace.namespace, cluster_id: cluster.id, name: function_name) - end - - it 'returns functions' do - get :index, params: params({ format: :json }) - expect(json_response["functions"]).not_to be_empty - end - - it 'filters out the functions whose cluster the user does not have permission to read' do - allow(controller).to receive(:can?).and_return(true) - expect(controller).to receive(:can?).with(user, :read_cluster, cluster).and_return(false) - - get :index, params: params({ format: :json }) - - expect(json_response["functions"]).to be_empty - end - - it 'returns a successful response status' do - get :index, params: params({ format: :json }) - expect(response).to have_gitlab_http_status(:ok) - end - - context 'when there is serverless domain for a cluster' do - let!(:serverless_domain_cluster) do - create(:serverless_domain_cluster, clusters_applications_knative_id: knative.id) - end - - it 'returns JSON with function details with serverless domain URL' do - get :index, params: params({ format: :json }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response["functions"]).not_to be_empty - - expect(json_response["functions"]).to all( - include( - 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}" - ) - ) - end - end - - context 'when there is no serverless domain for a cluster' do - it 'keeps function URL as it was' do - expect(::Serverless::Domain).not_to receive(:new) - - get :index, params: params({ format: :json }) - expect(response).to have_gitlab_http_status(:ok) - end - end - end - end - end - - describe 'GET #show' do - it_behaves_like 'behind :deprecated_serverless feature flag' do - let(:action) { get :show, params: params({ format: :json, environment_id: "*", id: "foo" }) } - end - - context 'with function that does not exist' do - it 'returns 404' do - get :show, params: params({ format: :json, environment_id: "*", id: "foo" }) - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'with valid data', :use_clean_rails_memory_store_caching do - shared_examples 'GET #show with valid data' do - context 'when there is serverless domain for a cluster' do - let!(:serverless_domain_cluster) do - create(:serverless_domain_cluster, clusters_applications_knative_id: knative.id) - end - - it 'returns JSON with function details with serverless domain URL' do - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to include( - 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}" - ) - end - - it 'returns 404 when user does not have permission to read the cluster' do - allow(controller).to receive(:can?).and_return(true) - expect(controller).to receive(:can?).with(user, :read_cluster, cluster).and_return(false) - - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'when there is no serverless domain for a cluster' do - it 'keeps function URL as it was' do - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to include( - 'url' => "http://#{function_name}.#{namespace.namespace}.example.com" - ) - end - end - - it 'return json with function details' do - get :show, params: params({ format: :json, environment_id: "*", id: function_name }) - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to include( - 'name' => function_name, - 'url' => "http://#{function_name}.#{namespace.namespace}.example.com", - 'description' => function_description, - 'podcount' => 0 - ) - end - end - - context 'on Knative 0.5.0' do - before do - prepare_knative_stubs(knative_05_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - - context 'on Knative 0.6.0' do - before do - prepare_knative_stubs(knative_06_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - - context 'on Knative 0.7.0' do - before do - prepare_knative_stubs(knative_07_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - - context 'on Knative 0.9.0' do - before do - prepare_knative_stubs(knative_09_service(**knative_stub_options)) - end - - include_examples 'GET #show with valid data' - end - end - end - - describe 'GET #metrics' do - it_behaves_like 'behind :deprecated_serverless feature flag' do - let(:action) { get :metrics, params: params({ format: :json, environment_id: "*", id: "foo" }) } - end - - context 'invalid data' do - it 'has a bad function name' do - get :metrics, params: params({ format: :json, environment_id: "*", id: "foo" }) - expect(response).to have_gitlab_http_status(:no_content) - end - end - end - - describe 'GET #index with data', :use_clean_rails_memory_store_caching do - shared_examples 'GET #index with data' do - it 'has data' do - get :index, params: params({ format: :json }) - - expect(response).to have_gitlab_http_status(:ok) - - expect(json_response).to match({ - 'knative_installed' => 'checking', - 'functions' => [ - a_hash_including( - 'name' => function_name, - 'url' => "http://#{function_name}.#{namespace.namespace}.example.com", - 'description' => function_description - ) - ] - }) - end - - it 'has data in html' do - get :index, params: params - - expect(response).to have_gitlab_http_status(:ok) - end - end - - context 'on Knative 0.5.0' do - before do - prepare_knative_stubs(knative_05_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - - context 'on Knative 0.6.0' do - before do - prepare_knative_stubs(knative_06_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - - context 'on Knative 0.7.0' do - before do - prepare_knative_stubs(knative_07_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - - context 'on Knative 0.9.0' do - before do - prepare_knative_stubs(knative_09_service(**knative_stub_options)) - end - - include_examples 'GET #index with data' - end - end - - def prepare_knative_stubs(knative_service) - stub_kubeclient_service_pods - stub_reactive_cache(knative_services_finder, - { - services: [knative_service], - pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"] - }, - *knative_services_finder.cache_args) - end -end diff --git a/spec/controllers/projects/service_ping_controller_spec.rb b/spec/controllers/projects/service_ping_controller_spec.rb index 13b34290962..fa92efee079 100644 --- a/spec/controllers/projects/service_ping_controller_spec.rb +++ b/spec/controllers/projects/service_ping_controller_spec.rb @@ -79,6 +79,18 @@ RSpec.describe Projects::ServicePingController do it_behaves_like 'counter is not increased' it_behaves_like 'counter is increased', 'WEB_IDE_PREVIEWS_SUCCESS_COUNT' + + context 'when the user has access to the project' do + let(:user) { project.owner } + + it 'increases the live preview view counter' do + expect(Gitlab::UsageDataCounters::EditorUniqueCounter).to receive(:track_live_preview_edit_action).with(author: user) + + subject + + expect(response).to have_gitlab_http_status(:ok) + end + end end context 'when web ide clientside preview is not enabled' do diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb index 7e96c59fbb1..6802ebeb63e 100644 --- a/spec/controllers/projects/services_controller_spec.rb +++ b/spec/controllers/projects/services_controller_spec.rb @@ -326,56 +326,6 @@ RSpec.describe Projects::ServicesController do end end end - - context 'with Prometheus integration' do - let_it_be(:prometheus_integration) { create(:prometheus_integration, project: project) } - - let(:integration) { prometheus_integration } - let(:integration_params) { { manual_configuration: '1', api_url: 'http://example.com' } } - - context 'when feature flag :settings_operations_prometheus_service is enabled' do - before do - stub_feature_flags(settings_operations_prometheus_service: true) - end - - it 'redirects user back to edit page with alert' do - put :update, params: project_params.merge(service: integration_params) - - expect(response).to redirect_to(edit_project_integration_path(project, integration)) - expected_alert = [ - "You can now manage your Prometheus settings on the", - %(<a href="#{project_settings_operations_path(project)}">Operations</a> page.), - "Fields on this page have been deprecated." - ].join(' ') - - expect(controller).to set_flash.now[:alert].to(expected_alert) - end - - it 'does not modify integration' do - expect { put :update, params: project_params.merge(service: integration_params) } - .not_to change { prometheus_integration_as_data } - end - - def prometheus_integration_as_data - pi = project.prometheus_integration.reload - attrs = pi.attributes.except('encrypted_properties', - 'encrypted_properties_iv') - - [attrs, pi.properties] - end - end - - context 'when feature flag :settings_operations_prometheus_service is disabled' do - before do - stub_feature_flags(settings_operations_prometheus_service: false) - end - - it 'modifies integration' do - expect { put :update, params: project_params.merge(service: integration_params) } - .to change { project.prometheus_integration.reload.attributes } - end - end - end end describe 'GET #edit' do @@ -392,38 +342,6 @@ RSpec.describe Projects::ServicesController do end end end - - context 'with Prometheus service' do - let(:integration_param) { 'prometheus' } - - context 'when feature flag :settings_operations_prometheus_service is enabled' do - before do - stub_feature_flags(settings_operations_prometheus_service: true) - get :edit, params: project_params(id: integration_param) - end - - it 'renders deprecation warning notice' do - expected_alert = [ - "You can now manage your Prometheus settings on the", - %(<a href="#{project_settings_operations_path(project)}">Operations</a> page.), - "Fields on this page have been deprecated." - ].join(' ') - - expect(controller).to set_flash.now[:alert].to(expected_alert) - end - end - - context 'when feature flag :settings_operations_prometheus_service is disabled' do - before do - stub_feature_flags(settings_operations_prometheus_service: false) - get :edit, params: project_params(id: integration_param) - end - - it 'does not render deprecation warning notice' do - expect(controller).not_to set_flash.now[:alert] - end - end - end end private diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb index 7ef5371f2b5..c1fa91e9f8b 100644 --- a/spec/controllers/projects/settings/operations_controller_spec.rb +++ b/spec/controllers/projects/settings/operations_controller_spec.rb @@ -354,37 +354,6 @@ RSpec.describe Projects::Settings::OperationsController do end context 'prometheus integration' do - describe 'PATCH #update' do - let(:params) do - { - prometheus_integration_attributes: { - manual_configuration: '0', - api_url: 'https://gitlab.prometheus.rocks' - } - } - end - - context 'feature flag :settings_operations_prometheus_service is enabled' do - before do - stub_feature_flags(settings_operations_prometheus_service: true) - end - - it_behaves_like 'PATCHable' - end - - context 'feature flag :settings_operations_prometheus_service is disabled' do - before do - stub_feature_flags(settings_operations_prometheus_service: false) - end - - it_behaves_like 'PATCHable' do - let(:permitted_params) do - ActionController::Parameters.new(params.except(:prometheus_integration_attributes)).permit! - end - end - end - end - describe 'POST #reset_alerting_token' do context 'with existing alerting setting' do let!(:alerting_setting) do diff --git a/spec/controllers/projects/tracings_controller_spec.rb b/spec/controllers/projects/tracings_controller_spec.rb index 1f8a68cc861..80e21349e20 100644 --- a/spec/controllers/projects/tracings_controller_spec.rb +++ b/spec/controllers/projects/tracings_controller_spec.rb @@ -51,6 +51,16 @@ RSpec.describe Projects::TracingsController do it_behaves_like 'user with read access', :public it_behaves_like 'user with read access', :internal it_behaves_like 'user with read access', :private + + context 'feature flag disabled' do + before do + stub_feature_flags(monitor_tracing: false) + end + + it_behaves_like 'user without read access', :public + it_behaves_like 'user without read access', :internal + it_behaves_like 'user without read access', :private + end end context 'without maintainer role' do diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb index c008c7253d8..6d2db25ade2 100644 --- a/spec/controllers/projects/uploads_controller_spec.rb +++ b/spec/controllers/projects/uploads_controller_spec.rb @@ -54,6 +54,241 @@ RSpec.describe Projects::UploadsController do end end + describe "GET #show" do + let(:filename) { "rails_sample.jpg" } + let(:user) { create(:user) } + let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } + let(:secret) { FileUploader.generate_secret } + let(:uploader_class) { FileUploader } + + let(:upload_service) do + UploadService.new(model, jpg, uploader_class).execute + end + + let(:show_upload) do + get :show, params: params.merge(secret: secret, filename: filename) + end + + before do + allow(FileUploader).to receive(:generate_secret).and_return(secret) + + allow_next_instance_of(FileUploader) do |instance| + allow(instance).to receive(:image?).and_return(true) + end + + upload_service + end + + context 'when project is private do' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 302" do + show_upload + + expect(response).to have_gitlab_http_status(:redirect) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 404" do + show_upload + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + + context 'when project is public' do + before do + model.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC) + end + + context "when not signed in" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user doesn't have access to the model" do + context "enforce_auth_checks_on_uploads feature flag" do + context "with flag enabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: true) + end + + context 'when the project has setting enforce_auth_checks_on_uploads true' do + before do + model.update!(enforce_auth_checks_on_uploads: true) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + + context 'when the project has setting enforce_auth_checks_on_uploads false' do + before do + model.update!(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + + context "with flag disabled" do + before do + stub_feature_flags(enforce_auth_checks_on_uploads: false) + end + + it "responds with status 200" do + show_upload + + expect(response).to have_gitlab_http_status(:ok) + end + end + end + end + end + end + def post_authorize(verified: true) request.headers.merge!(workhorse_internal_api_request_header) if verified diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 07bd198137a..537f7aa5fee 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -309,6 +309,35 @@ RSpec.describe ProjectsController do expect(response.body).to have_content('LICENSE') # would be 'MIT license' if stub not works end + describe 'tracking events', :snowplow do + before do + allow(controller).to receive(:current_user).and_return(user) + get_show + end + + it 'tracks page views' do + expect_snowplow_event( + category: 'project_overview', + action: 'render', + user: user, + project: public_project + ) + end + + context 'when the project is importing' do + let_it_be(:public_project) { create(:project, :public, :import_scheduled) } + + it 'does not track page views' do + expect_no_snowplow_event( + category: 'project_overview', + action: 'render', + user: user, + project: public_project + ) + end + end + end + describe "PUC highlighting" do render_views @@ -834,7 +863,8 @@ RSpec.describe ProjectsController do id: project.path, project: { project_setting_attributes: { - show_default_award_emojis: boolean_value + show_default_award_emojis: boolean_value, + enforce_auth_checks_on_uploads: boolean_value } } } @@ -842,6 +872,7 @@ RSpec.describe ProjectsController do project.reload expect(project.show_default_award_emojis?).to eq(result) + expect(project.enforce_auth_checks_on_uploads?).to eq(result) end end end @@ -1423,6 +1454,41 @@ RSpec.describe ProjectsController do expect(response).to have_gitlab_http_status(:found) end + + context 'when the project storage_size exceeds the application setting max_export_size' do + it 'returns 302 with alert' do + stub_application_setting(max_export_size: 1) + project.statistics.update!(lfs_objects_size: 2.megabytes, repository_size: 2.megabytes) + + post action, params: { namespace_id: project.namespace, id: project } + + expect(response).to have_gitlab_http_status(:found) + expect(flash[:alert]).to include('The project size exceeds the export limit.') + end + end + + context 'when the project storage_size does not exceed the application setting max_export_size' do + it 'returns 302 without alert' do + stub_application_setting(max_export_size: 1) + project.statistics.update!(lfs_objects_size: 0.megabytes, repository_size: 0.megabytes) + + post action, params: { namespace_id: project.namespace, id: project } + + expect(response).to have_gitlab_http_status(:found) + expect(flash[:alert]).to be_nil + end + end + + context 'when application setting max_export_size is not set' do + it 'returns 302 without alert' do + project.statistics.update!(lfs_objects_size: 2.megabytes, repository_size: 2.megabytes) + + post action, params: { namespace_id: project.namespace, id: project } + + expect(response).to have_gitlab_http_status(:found) + expect(flash[:alert]).to be_nil + end + end end context 'when project export is disabled' do diff --git a/spec/controllers/repositories/lfs_storage_controller_spec.rb b/spec/controllers/repositories/lfs_storage_controller_spec.rb index 7ddc5723e2e..672e6f1e85b 100644 --- a/spec/controllers/repositories/lfs_storage_controller_spec.rb +++ b/spec/controllers/repositories/lfs_storage_controller_spec.rb @@ -155,7 +155,7 @@ RSpec.describe Repositories::LfsStorageController do context 'with an invalid file' do let(:uploaded_file) { 'test' } - it_behaves_like 'returning response status', :unprocessable_entity + it_behaves_like 'returning response status', :bad_request end context 'when an expected error' do @@ -179,12 +179,10 @@ RSpec.describe Repositories::LfsStorageController do end context 'when existing file has been deleted' do - let(:lfs_object) { create(:lfs_object, :with_file) } + let(:lfs_object) { create(:lfs_object, :with_file, size: params[:size], oid: params[:oid]) } before do FileUtils.rm(lfs_object.file.path) - params[:oid] = lfs_object.oid - params[:size] = lfs_object.size end it 'replaces the file' do @@ -204,10 +202,10 @@ RSpec.describe Repositories::LfsStorageController do end end - it 'renders LFS forbidden' do + it 'renders bad request' do subject - expect(response).to have_gitlab_http_status(:forbidden) + expect(response).to have_gitlab_http_status(:bad_request) expect(lfs_object.reload.file).not_to exist end end @@ -239,8 +237,9 @@ RSpec.describe Repositories::LfsStorageController do FileUtils.mkdir_p(upload_path) File.write(file_path, 'test') + File.truncate(file_path, params[:size].to_i) - UploadedFile.new(file_path, filename: File.basename(file_path)) + UploadedFile.new(file_path, filename: File.basename(file_path), sha256: params[:oid]) end end end diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb index ffcd759435c..c27e58634f6 100644 --- a/spec/controllers/uploads_controller_spec.rb +++ b/spec/controllers/uploads_controller_spec.rb @@ -703,13 +703,16 @@ RSpec.describe UploadsController do end context 'when viewing alert metric images' do - let!(:user) { create(:user) } - let!(:project) { create(:project) } - let(:alert) { create(:alert_management_alert, project: project) } - let(:metric_image) { create(:alert_metric_image, alert: alert) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:alert) { create(:alert_management_alert, project: project) } + let_it_be(:metric_image) { create(:alert_metric_image, alert: alert) } - before do + before_all do project.add_developer(user) + end + + before do sign_in(user) end |