diff options
Diffstat (limited to 'spec/controllers')
46 files changed, 1112 insertions, 616 deletions
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb index fb4c0970653..f7b2bab3615 100644 --- a/spec/controllers/admin/application_settings_controller_spec.rb +++ b/spec/controllers/admin/application_settings_controller_spec.rb @@ -81,6 +81,18 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set expect(body).to include('counts') expect(response).to have_gitlab_http_status(:ok) end + + describe 'usage data counter' do + let(:counter) { Gitlab::UsageDataCounters::ServiceUsageDataCounter } + + it 'incremented when json generated' do + expect { get :usage_data, format: :json }.to change { counter.read(:download_payload_click) }.by(1) + end + + it 'not incremented when html format requested' do + expect { get :usage_data }.not_to change { counter.read(:download_payload_click) } + end + end end describe 'PUT #update' do diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb index 25c4830a79a..fed9d2e8588 100644 --- a/spec/controllers/admin/clusters_controller_spec.rb +++ b/spec/controllers/admin/clusters_controller_spec.rb @@ -27,6 +27,10 @@ RSpec.describe Admin::ClustersController do create(:cluster, :disabled, :provided_by_gcp, :production_environment, :instance) end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { get_index } + end + it 'lists available clusters and displays html' do get_index @@ -105,6 +109,10 @@ RSpec.describe Admin::ClustersController do 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' } @@ -226,6 +234,10 @@ RSpec.describe Admin::ClustersController do 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 @@ -318,6 +330,10 @@ RSpec.describe Admin::ClustersController do 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 } @@ -375,6 +391,10 @@ RSpec.describe Admin::ClustersController do post :create_user, params: params end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { post_create_user } + end + describe 'functionality' do context 'when creates a cluster' do it 'creates a new cluster' do @@ -445,6 +465,10 @@ RSpec.describe Admin::ClustersController do post :authorize_aws_role, params: params end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + before do allow(Clusters::Aws::FetchCredentialsService).to receive(:new) .and_return(double(execute: double)) @@ -495,6 +519,10 @@ RSpec.describe Admin::ClustersController do delete :clear_cache, params: { id: cluster } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + it 'deletes the namespaces associated with the cluster' do expect { go }.to change { Clusters::KubernetesNamespace.count } @@ -520,6 +548,10 @@ RSpec.describe Admin::ClustersController do format: :json end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { get_cluster_status } + end + describe 'functionality' do it 'responds with matching schema' do get_cluster_status @@ -555,6 +587,10 @@ RSpec.describe Admin::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { get_show } + end + describe 'functionality' do render_views @@ -603,6 +639,10 @@ RSpec.describe Admin::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { put_update } + end + it 'updates and redirects back to show page' do put_update @@ -694,6 +734,10 @@ RSpec.describe Admin::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { delete_destroy } + end + describe 'functionality' do context 'when cluster is provided by GCP' do context 'when cluster is created' do diff --git a/spec/controllers/admin/runner_projects_controller_spec.rb b/spec/controllers/admin/runner_projects_controller_spec.rb index e5f63025cf7..98f961f66bb 100644 --- a/spec/controllers/admin/runner_projects_controller_spec.rb +++ b/spec/controllers/admin/runner_projects_controller_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Admin::RunnerProjectsController do describe '#create' do let(:project_id) { project.path } - subject do + subject(:send_create) do post :create, params: { namespace_id: group.path, project_id: project_id, @@ -25,7 +25,7 @@ RSpec.describe Admin::RunnerProjectsController do let(:project_runner) { create(:ci_runner, :project, projects: [project]) } it 'redirects to the admin runner edit page' do - subject + send_create expect(response).to have_gitlab_http_status(:redirect) expect(response).to redirect_to edit_admin_runner_url(project_runner) @@ -37,7 +37,7 @@ RSpec.describe Admin::RunnerProjectsController do let(:source_project) { create(:project) } it 'redirects to the admin runner edit page' do - subject + send_create expect(response).to have_gitlab_http_status(:redirect) expect(response).to redirect_to edit_admin_runner_url(project_runner) @@ -50,7 +50,42 @@ RSpec.describe Admin::RunnerProjectsController do let(:project_id) { 0 } it 'shows 404 for unknown project' do - subject + send_create + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + describe '#destroy' do + let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) } + + let(:project_id) { project.path } + + subject(:send_destroy) do + delete :destroy, params: { + namespace_id: group.path, + project_id: project_id, + id: runner_project_id + } + end + + context 'unassigning runner from project' do + let(:runner_project_id) { project_runner.runner_projects.last.id } + + it 'redirects to the admin runner edit page' do + send_destroy + + expect(response).to have_gitlab_http_status(:redirect) + expect(response).to redirect_to edit_admin_runner_url(project_runner) + end + end + + context 'for unknown project runner relationship' do + let(:runner_project_id) { 0 } + + it 'shows 404 for unknown project runner relationship' do + send_destroy expect(response).to have_gitlab_http_status(:not_found) end diff --git a/spec/controllers/admin/runners_controller_spec.rb b/spec/controllers/admin/runners_controller_spec.rb index 74f352e8ec2..8f70cb32d3e 100644 --- a/spec/controllers/admin/runners_controller_spec.rb +++ b/spec/controllers/admin/runners_controller_spec.rb @@ -105,7 +105,7 @@ RSpec.describe Admin::RunnersController do describe '#destroy' do it 'destroys the runner' do - expect_next_instance_of(Ci::UnregisterRunnerService, runner) do |service| + expect_next_instance_of(Ci::Runners::UnregisterRunnerService, runner, user) do |service| expect(service).to receive(:execute).once.and_call_original end diff --git a/spec/controllers/admin/topics_controller_spec.rb b/spec/controllers/admin/topics_controller_spec.rb index 6d66cb43338..ea510f916da 100644 --- a/spec/controllers/admin/topics_controller_spec.rb +++ b/spec/controllers/admin/topics_controller_spec.rb @@ -88,6 +88,13 @@ RSpec.describe Admin::TopicsController do 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 } } + + errors = assigns[:topic].errors + expect(errors).to contain_exactly(errors.full_message(:name, I18n.t('errors.messages.taken'))) + end + context 'as a normal user' do before do sign_in(user) @@ -116,6 +123,15 @@ RSpec.describe Admin::TopicsController do 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 + other_topic = create(:topic, name: 'other-topic') + + put :update, params: { id: topic.id, projects_topic: { name: other_topic.name.upcase } } + + errors = assigns[:topic].errors + expect(errors).to contain_exactly(errors.full_message(:name, I18n.t('errors.messages.taken'))) + end + context 'as a normal user' do before do sign_in(user) diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 004bea02580..ddd80b67639 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -501,6 +501,7 @@ RSpec.describe ApplicationController do describe '#append_info_to_payload' do controller(described_class) do attr_reader :last_payload + urgency :high, [:foo] def index @@ -1058,15 +1059,25 @@ RSpec.describe ApplicationController do describe 'setting permissions-policy header' do controller do skip_before_action :authenticate_user! + before_action :redirect_to_example, only: [:redirect] def index render html: 'It is a flock of sheep, not a floc of sheep.' end + + def redirect + raise 'Should not be reached' + end + + def redirect_to_example + redirect_to('https://example.com') + end end before do routes.draw do get 'index' => 'anonymous#index' + get 'redirect' => 'anonymous#redirect' end end @@ -1092,6 +1103,13 @@ RSpec.describe ApplicationController do expect(response.headers['Permissions-Policy']).to eq('interest-cohort=()') end + + it 'sets the Permissions-Policy header even when redirected before_action' do + get :redirect + + expect(response).to have_gitlab_http_status(:redirect) + expect(response.headers['Permissions-Policy']).to eq('interest-cohort=()') + end end end end diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index 533d3896ee6..0a809e80fcd 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -235,7 +235,7 @@ RSpec.describe AutocompleteController do end end - it_behaves_like 'rate limited endpoint', rate_limit_key: :user_email_lookup do + it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do let(:current_user) { user } def request diff --git a/spec/controllers/boards/lists_controller_spec.rb b/spec/controllers/boards/lists_controller_spec.rb index 29141582c6f..95334974e66 100644 --- a/spec/controllers/boards/lists_controller_spec.rb +++ b/spec/controllers/boards/lists_controller_spec.rb @@ -208,7 +208,7 @@ RSpec.describe Boards::ListsController do sign_in(user) params = { namespace_id: project.namespace.to_param, - project_id: project, + project_id: project.id, board_id: board.to_param, id: list.to_param, list: { position: position }, @@ -221,7 +221,7 @@ RSpec.describe Boards::ListsController do sign_in(user) params = { namespace_id: project.namespace.to_param, - project_id: project, + project_id: project.id, board_id: board.to_param, id: list.to_param, list: setting, diff --git a/spec/controllers/concerns/product_analytics_tracking_spec.rb b/spec/controllers/concerns/product_analytics_tracking_spec.rb new file mode 100644 index 00000000000..250cc3cf2cf --- /dev/null +++ b/spec/controllers/concerns/product_analytics_tracking_spec.rb @@ -0,0 +1,171 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe ProductAnalyticsTracking, :snowplow do + include TrackingHelpers + include SnowplowHelpers + + let(:user) { create(:user) } + let!(:group) { create(:group) } + + before do + allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event) + end + + controller(ApplicationController) do + include ProductAnalyticsTracking + + skip_before_action :authenticate_user!, only: :show + track_event(:index, :show, name: 'g_analytics_valuestream', destinations: [:redis_hll, :snowplow], + conditions: [:custom_condition_one?, :custom_condition_two?]) { |controller| controller.get_custom_id } + + def index + render html: 'index' + end + + def new + render html: 'new' + end + + def show + render html: 'show' + end + + def get_custom_id + 'some_custom_id' + end + + private + + def tracking_namespace_source + Group.first + end + + def custom_condition_one? + true + end + + def custom_condition_two? + true + end + end + + def expect_tracking(user: self.user) + expect(Gitlab::UsageDataCounters::HLLRedisCounter).to have_received(:track_event) + .with('g_analytics_valuestream', values: instance_of(String)) + + expect_snowplow_event( + category: anything, + action: 'g_analytics_valuestream', + namespace: group, + user: user + ) + end + + def expect_no_tracking + expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event) + + expect_no_snowplow_event + end + + context 'when user is logged in' do + before do + sign_in(user) + end + + it 'tracks the event' do + get :index + + expect_tracking + end + + context 'when FF is disabled' do + before do + stub_feature_flags(route_hll_to_snowplow: false) + end + + it 'doesnt track snowplow event' do + get :index + + expect_no_snowplow_event + end + end + + it 'tracks the event if DNT is not enabled' do + stub_do_not_track('0') + + get :index + + expect_tracking + end + + it 'does not track the event if DNT is enabled' do + stub_do_not_track('1') + + get :index + + expect_no_tracking + end + + it 'does not track the event if the format is not HTML' do + get :index, format: :json + + expect_no_tracking + end + + it 'does not track the event if a custom condition returns false' do + allow(controller).to receive(:custom_condition_two?).and_return(false) + + get :index + + expect_no_tracking + end + + it 'does not track the event for untracked actions' do + get :new + + expect_no_tracking + end + end + + context 'when user is not logged in' do + let(:visitor_id) { SecureRandom.uuid } + + it 'tracks the event when there is a visitor id' do + cookies[:visitor_id] = { value: visitor_id, expires: 24.months } + + get :show, params: { id: 1 } + + expect_tracking(user: nil) + end + end + + context 'when user is not logged in and there is no visitor_id' do + it 'does not track the event' do + get :index + + expect_no_tracking + end + + it 'tracks the event when there is custom id' do + get :show, params: { id: 1 } + + expect_tracking(user: nil) + end + + it 'does not track the HLL event when there is no custom id' do + allow(controller).to receive(:get_custom_id).and_return(nil) + + get :show, params: { id: 2 } + + expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event) + expect_snowplow_event( + category: anything, + action: 'g_analytics_valuestream', + namespace: group, + user: nil + ) + end + end +end diff --git a/spec/controllers/concerns/spammable_actions/akismet_mark_as_spam_action_spec.rb b/spec/controllers/concerns/spammable_actions/akismet_mark_as_spam_action_spec.rb index 7c10dccdcb9..caa0fa2d437 100644 --- a/spec/controllers/concerns/spammable_actions/akismet_mark_as_spam_action_spec.rb +++ b/spec/controllers/concerns/spammable_actions/akismet_mark_as_spam_action_spec.rb @@ -7,12 +7,6 @@ RSpec.describe SpammableActions::AkismetMarkAsSpamAction do controller(ActionController::Base) do include SpammableActions::AkismetMarkAsSpamAction - - private - - def spammable_path - '/fake_spammable_path' - end end let(:spammable_type) { 'SpammableType' } @@ -22,7 +16,6 @@ RSpec.describe SpammableActions::AkismetMarkAsSpamAction do before do allow(Gitlab::Recaptcha).to receive(:load_configurations!) { true } routes.draw { get 'mark_as_spam' => 'anonymous#mark_as_spam' } - allow(controller).to receive(:spammable) { spammable } allow(controller).to receive(:current_user) { double(:current_user, admin?: admin) } allow(controller).to receive(:current_user).and_return(current_user) end @@ -31,6 +24,9 @@ RSpec.describe SpammableActions::AkismetMarkAsSpamAction do subject { post :mark_as_spam } before do + allow(controller).to receive(:spammable) { spammable } + allow(controller).to receive(:spammable_path) { '/fake_spammable_path' } + expect_next(Spam::AkismetMarkAsSpamService, target: spammable) .to receive(:execute).and_return(execute_result) end @@ -68,4 +64,16 @@ RSpec.describe SpammableActions::AkismetMarkAsSpamAction do end end end + + describe '#spammable' do + it 'raises when unimplemented' do + expect { controller.send(:spammable) }.to raise_error(NotImplementedError) + end + end + + describe '#spammable_path' do + it 'raises when unimplemented' do + expect { controller.send(:spammable_path) }.to raise_error(NotImplementedError) + end + end end diff --git a/spec/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support_spec.rb b/spec/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support_spec.rb index 53a78326397..c5d17e0232c 100644 --- a/spec/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support_spec.rb +++ b/spec/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support_spec.rb @@ -7,7 +7,7 @@ RSpec.describe SpammableActions::CaptchaCheck::HtmlFormatActionsSupport do include SpammableActions::CaptchaCheck::HtmlFormatActionsSupport def create - with_captcha_check_html_format { render :some_rendered_view } + with_captcha_check_html_format(spammable: spammable) { render :some_rendered_view } end end diff --git a/spec/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support_spec.rb b/spec/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support_spec.rb index d7a44351ad8..7796d9d1273 100644 --- a/spec/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support_spec.rb +++ b/spec/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support_spec.rb @@ -7,7 +7,7 @@ RSpec.describe SpammableActions::CaptchaCheck::JsonFormatActionsSupport do include SpammableActions::CaptchaCheck::JsonFormatActionsSupport def some_action - with_captcha_check_json_format { render :some_rendered_view } + with_captcha_check_json_format(spammable: spammable) { render :some_rendered_view } end end diff --git a/spec/controllers/concerns/spammable_actions/captcha_check/rest_api_actions_support_spec.rb b/spec/controllers/concerns/spammable_actions/captcha_check/rest_api_actions_support_spec.rb new file mode 100644 index 00000000000..07c564b555e --- /dev/null +++ b/spec/controllers/concerns/spammable_actions/captcha_check/rest_api_actions_support_spec.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe SpammableActions::CaptchaCheck::RestApiActionsSupport do + include Rack::Test::Methods + + subject do + Class.new(Grape::API) do + helpers API::Helpers + helpers SpammableActions::CaptchaCheck::RestApiActionsSupport + + get ':id' do + # NOTE: This was the only way that seemed to work to inject the mock spammable into the + # Grape rack app instance. If there's a better way, improvements are welcome. + spammable = Object.fake_spammable_factory + with_captcha_check_rest_api(spammable: spammable) do + render_api_error!(spammable.errors, 400) + end + end + end + end + + def app + subject + end + + before do + allow(Gitlab::Recaptcha).to receive(:load_configurations!) { true } + end + + describe '#with_captcha_check_json_format' do + let(:spammable) { instance_double(Snippet) } + + before do + expect(spammable).to receive(:render_recaptcha?).at_least(:once) { render_recaptcha } + allow(Object).to receive(:fake_spammable_factory) { spammable } + end + + context 'when spammable.render_recaptcha? is true' do + let(:render_recaptcha) { true } + let(:spam_log) { instance_double(SpamLog, id: 1) } + let(:spammable) { instance_double(Snippet, spam?: true, render_recaptcha?: render_recaptcha, spam_log: spam_log) } + let(:recaptcha_site_key) { 'abc123' } + let(:err_msg) { 'You gotta solve the CAPTCHA' } + let(:spam_action_response_fields) do + { + spam: true, + needs_captcha_response: render_recaptcha, + spam_log_id: 1, + captcha_site_key: recaptcha_site_key + } + end + + it 'renders json containing spam_action_response_fields' do + allow(spammable).to receive_message_chain('errors.full_messages.to_sentence') { err_msg } + allow(Gitlab::CurrentSettings).to receive(:recaptcha_site_key) { recaptcha_site_key } + response = get '/test' + expected_response = { + 'needs_captcha_response' => render_recaptcha, + 'spam_log_id' => 1, + 'captcha_site_key' => recaptcha_site_key, + 'message' => { 'error' => err_msg } + } + expect(Gitlab::Json.parse(response.body)).to eq(expected_response) + expect(response.status).to eq(409) + end + end + + context 'when spammable.render_recaptcha? is false' do + let(:render_recaptcha) { false } + let(:errors) { { 'base' => "It's definitely spam" } } + + it 'yields to block' do + allow(spammable).to receive(:errors) { errors } + + response = get 'test' + expected_response = { + 'message' => errors + } + expect(Gitlab::Json.parse(response.body)).to eq(expected_response) + expect(response.status).to eq(400) + end + end + end +end diff --git a/spec/controllers/confirmations_controller_spec.rb b/spec/controllers/confirmations_controller_spec.rb index 1c7f8de32bb..3b5afbcebca 100644 --- a/spec/controllers/confirmations_controller_spec.rb +++ b/spec/controllers/confirmations_controller_spec.rb @@ -152,7 +152,7 @@ RSpec.describe ConfirmationsController do perform_request expect(response).to render_template(:new) - expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.' + expect(flash[:alert]).to include _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.') end it 'successfully sends password reset when reCAPTCHA is solved' do diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb index 8fae617ea65..aed310531e6 100644 --- a/spec/controllers/dashboard_controller_spec.rb +++ b/spec/controllers/dashboard_controller_spec.rb @@ -13,7 +13,22 @@ RSpec.describe DashboardController do end describe 'GET issues' do - it_behaves_like 'issuables list meta-data', :issue, :issues + 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, :issues + 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, :issues + end + it_behaves_like 'issuables requiring filter', :issues end @@ -83,25 +98,49 @@ RSpec.describe DashboardController do context "no filters" do let(:params) { {} } + shared_examples_for 'no filters are set' do + it 'sets @no_filters_set to true' do + expect(assigns[:no_filters_set]).to eq(true) + end + end + + it_behaves_like 'no filters are set' + + context 'when key is present but value is not' do + let(:params) { { author_username: nil } } + + it_behaves_like 'no filters are set' + end + + context 'when in param is set but no search' do + let(:params) { { in: 'title' } } + + it_behaves_like 'no filters are set' + end + end + + shared_examples_for 'filters are set' do it 'sets @no_filters_set to false' do - expect(assigns[:no_filters_set]).to eq(true) + expect(assigns[:no_filters_set]).to eq(false) end end context "scalar filters" do let(:params) { { author_id: user.id } } - it 'sets @no_filters_set to false' do - expect(assigns[:no_filters_set]).to eq(false) - end + it_behaves_like 'filters are set' end context "array filters" do let(:params) { { label_name: ['bug'] } } - it 'sets @no_filters_set to false' do - expect(assigns[:no_filters_set]).to eq(false) - end + it_behaves_like 'filters are set' + end + + context 'search' do + let(:params) { { search: 'test' } } + + it_behaves_like 'filters are set' end end end diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb index 95f60156c40..dbaed8aaa19 100644 --- a/spec/controllers/graphql_controller_spec.rb +++ b/spec/controllers/graphql_controller_spec.rb @@ -139,8 +139,45 @@ RSpec.describe GraphqlController do context 'when user uses an API token' do let(:user) { create(:user, last_activity_on: Date.yesterday) } let(:token) { create(:personal_access_token, user: user, scopes: [:api]) } + let(:query) { '{ __typename }' } - subject { post :execute, params: { access_token: token.token } } + subject { post :execute, params: { query: query, access_token: token.token } } + + context 'when the user is a project bot' do + let(:user) { create(:user, :project_bot, last_activity_on: Date.yesterday) } + + it 'updates the users last_activity_on field' do + expect { subject }.to change { user.reload.last_activity_on } + end + + it "sets context's sessionless value as true" do + subject + + expect(assigns(:context)[:is_sessionless_user]).to be true + end + + it 'executes a simple query with no errors' do + subject + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq({ 'data' => { '__typename' => 'Query' } }) + end + + it 'can access resources the project_bot has access to' do + project_a, project_b = create_list(:project, 2, :private) + project_a.add_developer(user) + + post :execute, params: { query: <<~GQL, access_token: token.token } + query { + a: project(fullPath: "#{project_a.full_path}") { name } + b: project(fullPath: "#{project_b.full_path}") { name } + } + GQL + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq({ 'data' => { 'a' => { 'name' => project_a.name }, 'b' => nil } }) + end + end it 'updates the users last_activity_on field' do expect { subject }.to change { user.reload.last_activity_on } diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb index 710e983dfbd..4eeae64b760 100644 --- a/spec/controllers/groups/clusters_controller_spec.rb +++ b/spec/controllers/groups/clusters_controller_spec.rb @@ -32,6 +32,10 @@ RSpec.describe Groups::ClustersController do create(:cluster, :disabled, :provided_by_gcp, :production_environment, cluster_type: :group_type, groups: [group]) end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + it 'lists available clusters and renders html' do go @@ -116,6 +120,10 @@ RSpec.describe Groups::ClustersController do 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' } @@ -255,6 +263,10 @@ RSpec.describe Groups::ClustersController do 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 @@ -349,6 +361,10 @@ RSpec.describe Groups::ClustersController do post :create_user, 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 creates a cluster' do it 'creates a new cluster' do @@ -457,6 +473,10 @@ RSpec.describe Groups::ClustersController do post :create_aws, params: params.merge(group_id: group) 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 } @@ -519,6 +539,10 @@ RSpec.describe Groups::ClustersController do post :authorize_aws_role, params: params.merge(group_id: group) end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + before do allow(Clusters::Aws::FetchCredentialsService).to receive(:new) .and_return(double(execute: double)) @@ -579,6 +603,10 @@ RSpec.describe Groups::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + it 'deletes the namespaces associated with the cluster' do expect { go }.to change { Clusters::KubernetesNamespace.count } @@ -611,6 +639,10 @@ RSpec.describe Groups::ClustersController do format: :json end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + describe 'functionality' do it 'responds with matching schema' do go @@ -651,6 +683,10 @@ RSpec.describe Groups::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + describe 'functionality' do render_views @@ -705,6 +741,10 @@ RSpec.describe Groups::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + it 'updates and redirects back to show page' do go @@ -802,6 +842,10 @@ RSpec.describe Groups::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + describe 'functionality' do context 'when cluster is provided by GCP' do context 'when cluster is created' do 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 57a83da3425..61445603a2d 100644 --- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb +++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb @@ -170,6 +170,14 @@ RSpec.describe Groups::DependencyProxyForContainersController do end end + shared_examples 'namespace statistics refresh' do + it 'updates namespace statistics' do + expect(Groups::UpdateStatisticsWorker).to receive(:perform_async) + + subject + end + end + before do allow(Gitlab.config.dependency_proxy) .to receive(:enabled).and_return(true) @@ -403,13 +411,15 @@ RSpec.describe Groups::DependencyProxyForContainersController do context 'with a valid user' do before do group.add_guest(user) - - expect_next_found_instance_of(Group) do |instance| - expect(instance).to receive_message_chain(:dependency_proxy_blobs, :create!) - end end it_behaves_like 'a package tracking event', described_class.name, 'pull_blob' + + it 'creates a blob' do + expect { subject }.to change { group.dependency_proxy_blobs.count }.by(1) + end + + it_behaves_like 'namespace statistics refresh' end end @@ -473,6 +483,8 @@ RSpec.describe Groups::DependencyProxyForContainersController do expect(manifest.digest).to eq(digest) expect(manifest.file_name).to eq(file_name) end + + it_behaves_like 'namespace statistics refresh' end context 'with existing stale manifest' do @@ -483,6 +495,8 @@ RSpec.describe Groups::DependencyProxyForContainersController do expect { subject }.to change { group.dependency_proxy_manifests.count }.by(0) .and change { manifest.reload.digest }.from(old_digest).to(digest) end + + it_behaves_like 'namespace statistics refresh' end end end diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index 04a9b9f5250..25d32436d58 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -38,12 +38,6 @@ RSpec.describe Groups::GroupMembersController do expect(assigns(:invited_members).map(&:invite_email)).to match_array(invited.map(&:invite_email)) end - it 'assigns skip groups' do - get :index, params: { group_id: group } - - expect(assigns(:skip_groups)).to match_array(group.related_group_ids) - end - it 'restricts search to one email' do get :index, params: { group_id: group, search_invited: invited.first.invite_email } @@ -68,11 +62,10 @@ RSpec.describe Groups::GroupMembersController do sign_in(user) end - it 'does not assign invited members or skip_groups', :aggregate_failures do + it 'does not assign invited members' do get :index, params: { group_id: group } expect(assigns(:invited_members)).to be_nil - expect(assigns(:skip_groups)).to be_nil end end @@ -106,107 +99,6 @@ RSpec.describe Groups::GroupMembersController do end end - describe 'POST create' do - let_it_be(:group_user) { create(:user) } - - before do - sign_in(user) - end - - context 'when user does not have enough rights' do - before do - group.add_developer(user) - end - - it 'returns 403', :aggregate_failures do - post :create, params: { - group_id: group, - user_ids: group_user.id, - access_level: Gitlab::Access::GUEST - } - - expect(response).to have_gitlab_http_status(:forbidden) - expect(group.users).not_to include group_user - end - end - - context 'when user has enough rights' do - before do - group.add_owner(user) - end - - it 'adds user to members', :aggregate_failures, :snowplow do - post :create, params: { - group_id: group, - user_ids: group_user.id, - access_level: Gitlab::Access::GUEST - } - - expect(controller).to set_flash.to 'Users were successfully added.' - expect(response).to redirect_to(group_group_members_path(group)) - expect(group.users).to include group_user - expect_snowplow_event( - category: 'Members::CreateService', - action: 'create_member', - label: 'group-members-page', - property: 'existing_user', - user: user - ) - end - - it 'adds no user to members', :aggregate_failures do - post :create, params: { - group_id: group, - user_ids: '', - access_level: Gitlab::Access::GUEST - } - - expect(controller).to set_flash.to 'No users specified.' - expect(response).to redirect_to(group_group_members_path(group)) - expect(group.users).not_to include group_user - end - end - - context 'access expiry date' do - before do - group.add_owner(user) - end - - subject do - post :create, params: { - group_id: group, - user_ids: group_user.id, - access_level: Gitlab::Access::GUEST, - expires_at: expires_at - } - end - - context 'when set to a date in the past' do - let(:expires_at) { 2.days.ago } - - it 'does not add user to members', :aggregate_failures do - subject - - expect(flash[:alert]).to include('Expires at cannot be a date in the past') - expect(response).to redirect_to(group_group_members_path(group)) - expect(group.users).not_to include group_user - end - end - - context 'when set to a date in the future' do - let(:expires_at) { 5.days.from_now } - - it 'adds user to members', :aggregate_failures do - subject - - expect(controller).to set_flash.to 'Users were successfully added.' - expect(response).to redirect_to(group_group_members_path(group)) - expect(group.users).to include group_user - end - end - end - end - describe 'PUT update' do let_it_be(:requester) { create(:group_member, :access_request, group: group) } @@ -515,14 +407,6 @@ RSpec.describe Groups::GroupMembersController do end end - describe 'POST #create' do - it 'is successful' do - post :create, params: { group_id: group, users: user, access_level: Gitlab::Access::GUEST } - - expect(response).to have_gitlab_http_status(:found) - end - end - describe 'PUT #update' do it 'is successful' do put :update, diff --git a/spec/controllers/groups/releases_controller_spec.rb b/spec/controllers/groups/releases_controller_spec.rb index 582a77b1c50..8b08f913e10 100644 --- a/spec/controllers/groups/releases_controller_spec.rb +++ b/spec/controllers/groups/releases_controller_spec.rb @@ -20,11 +20,11 @@ RSpec.describe Groups::ReleasesController do context 'as json' do let(:format) { :json } - subject { get :index, params: { group_id: group }, format: format } + subject(:index) { get :index, params: { group_id: group }, format: format } context 'json_response' do before do - subject + index end it 'returns an application/json content_type' do @@ -38,7 +38,7 @@ RSpec.describe Groups::ReleasesController do context 'the user is not authorized' do before do - subject + index end it 'does not return any releases' do @@ -54,12 +54,38 @@ RSpec.describe Groups::ReleasesController do it "returns all group's public and private project's releases as JSON, ordered by released_at" do sign_in(guest) - subject + index expect(json_response.map {|r| r['tag'] } ).to match_array(%w(p2 p1 v2 v1)) 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 9f0615a96ae..b4950b93a3f 100644 --- a/spec/controllers/groups/runners_controller_spec.rb +++ b/spec/controllers/groups/runners_controller_spec.rb @@ -190,7 +190,7 @@ RSpec.describe Groups::RunnersController do end it 'destroys the runner and redirects' do - expect_next_instance_of(Ci::UnregisterRunnerService, runner) do |service| + expect_next_instance_of(Ci::Runners::UnregisterRunnerService, runner, user) do |service| expect(service).to receive(:execute).once.and_call_original end @@ -208,21 +208,39 @@ RSpec.describe Groups::RunnersController do end end - context 'when user is an owner and runner in multiple projects' do - let(:project_2) { create(:project, group: group) } + 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 } } - before do - group.add_owner(user) + 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 - it 'does not destroy the project runner' do - delete :destroy, params: params_runner_project_2 + 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 was not deleted because it is assigned to multiple projects.') - expect(Ci::Runner.find_by(id: runner_project_2.id)).to be_present + 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 diff --git a/spec/controllers/jira_connect/events_controller_spec.rb b/spec/controllers/jira_connect/events_controller_spec.rb index 2a70a2ea683..2129b24b2fb 100644 --- a/spec/controllers/jira_connect/events_controller_spec.rb +++ b/spec/controllers/jira_connect/events_controller_spec.rb @@ -43,14 +43,15 @@ RSpec.describe JiraConnect::EventsController do end describe '#installed' do - let(:client_key) { '1234' } - let(:shared_secret) { 'secret' } + let_it_be(:client_key) { '1234' } + let_it_be(:shared_secret) { 'secret' } + let_it_be(:base_url) { 'https://test.atlassian.net' } let(:params) do { clientKey: client_key, sharedSecret: shared_secret, - baseUrl: 'https://test.atlassian.net' + baseUrl: base_url } end @@ -77,11 +78,11 @@ RSpec.describe JiraConnect::EventsController do expect(installation.base_url).to eq('https://test.atlassian.net') end - context 'when it is a version update and shared_secret is not sent' do + context 'when the shared_secret param is missing' do let(:params) do { clientKey: client_key, - baseUrl: 'https://test.atlassian.net' + baseUrl: base_url } end @@ -90,13 +91,48 @@ RSpec.describe JiraConnect::EventsController do expect(response).to have_gitlab_http_status(:unprocessable_entity) end + end + + context 'when an installation already exists' do + let_it_be(:installation) { create(:jira_connect_installation, base_url: base_url, client_key: client_key, shared_secret: shared_secret) } + + it 'validates the JWT token in authorization header and returns 200 without creating a new installation', :aggregate_failures do + expect { subject }.not_to change { JiraConnectInstallation.count } + expect(response).to have_gitlab_http_status(:ok) + end + + context 'when parameters include a new shared secret and base_url' do + let(:shared_secret) { 'new_secret' } + let(:base_url) { 'https://new_test.atlassian.net' } - context 'and an installation exists' do - let!(:installation) { create(:jira_connect_installation, client_key: client_key, shared_secret: shared_secret) } + it 'updates the installation', :aggregate_failures do + subject - it 'validates the JWT token in authorization header and returns 200 without creating a new installation' do - expect { subject }.not_to change { JiraConnectInstallation.count } expect(response).to have_gitlab_http_status(:ok) + expect(installation.reload).to have_attributes( + shared_secret: shared_secret, + base_url: base_url + ) + end + + context 'when the `jira_connect_installation_update` feature flag is disabled' do + before do + stub_feature_flags(jira_connect_installation_update: false) + end + + it 'does not update the installation', :aggregate_failures do + expect { subject }.not_to change { installation.reload.attributes } + expect(response).to have_gitlab_http_status(:ok) + end + end + end + + context 'when the new base_url is invalid' do + let(:base_url) { 'invalid' } + + it 'renders 422', :aggregate_failures do + expect { subject }.not_to change { installation.reload.base_url } + expect(response).to have_gitlab_http_status(:unprocessable_entity) end end end diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb index 01c032d9e3b..82014282c6e 100644 --- a/spec/controllers/passwords_controller_spec.rb +++ b/spec/controllers/passwords_controller_spec.rb @@ -121,7 +121,7 @@ RSpec.describe PasswordsController do perform_request expect(response).to render_template(:new) - expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.' + expect(flash[:alert]).to include _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.') end it 'successfully sends password reset when reCAPTCHA is solved' do diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 53efcc65066..cc807098498 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -366,8 +366,8 @@ RSpec.describe Projects::BlobController do it_behaves_like 'tracking unique hll events' do subject(:request) { put :update, params: default_params } - let(:target_id) { 'g_edit_by_sfe' } - let(:expected_type) { instance_of(Integer) } + let(:target_event) { 'g_edit_by_sfe' } + let(:expected_value) { instance_of(Integer) } end end @@ -516,8 +516,8 @@ RSpec.describe Projects::BlobController do subject(:request) { post :create, params: default_params } it_behaves_like 'tracking unique hll events' do - let(:target_id) { 'g_edit_by_sfe' } - let(:expected_type) { instance_of(Integer) } + let(:target_event) { 'g_edit_by_sfe' } + let(:expected_value) { instance_of(Integer) } end it 'redirects to blob' do @@ -525,24 +525,5 @@ RSpec.describe Projects::BlobController do expect(response).to redirect_to(project_blob_path(project, 'master/docs/EXAMPLE_FILE')) end - - context 'when code_quality_walkthrough param is present' do - let(:default_params) { super().merge(code_quality_walkthrough: true) } - - it 'redirects to the pipelines page' do - request - - expect(response).to redirect_to(project_pipelines_path(project, code_quality_walkthrough: true)) - end - - it 'creates an "commit_created" experiment tracking event' do - experiment = double(track: true) - expect(controller).to receive(:experiment).with(:code_quality_walkthrough, namespace: project.root_ancestor).and_return(experiment) - - request - - expect(experiment).to have_received(:track).with(:commit_created) - end - end end end diff --git a/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb index d55aad20689..37406d704f1 100644 --- a/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb +++ b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb @@ -36,17 +36,5 @@ RSpec.describe Projects::Ci::PipelineEditorController do expect(response).to have_gitlab_http_status(:not_found) end end - - describe 'pipeline_editor_walkthrough experiment' do - before do - project.add_developer(user) - end - - subject(:action) { show_request } - - it_behaves_like 'tracks assignment and records the subject', :pipeline_editor_walkthrough, :namespace do - subject { project.namespace } - end - end end end diff --git a/spec/controllers/projects/ci/secure_files_controller_spec.rb b/spec/controllers/projects/ci/secure_files_controller_spec.rb new file mode 100644 index 00000000000..1138897bcc6 --- /dev/null +++ b/spec/controllers/projects/ci/secure_files_controller_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::Ci::SecureFilesController do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + + 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 + end + + it { expect(response).to have_gitlab_http_status(:ok) } + + it 'renders show page' do + expect(response).to render_template :show + end + end + + context 'without enough privileges' do + before do + sign_in(user) + project.add_reporter(user) + show_request + end + + it 'responds with 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'an unauthenticated user' do + before do + show_request + end + + it 'redirects to sign in' do + expect(response).to have_gitlab_http_status(:found) + expect(response).to redirect_to('/users/sign_in') + end + end + end +end diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb index d0bef810ec8..44bdc958805 100644 --- a/spec/controllers/projects/clusters_controller_spec.rb +++ b/spec/controllers/projects/clusters_controller_spec.rb @@ -26,6 +26,10 @@ RSpec.describe Projects::ClustersController do let!(:enabled_cluster) { create(:cluster, :provided_by_gcp, projects: [project]) } let!(:disabled_cluster) { create(:cluster, :disabled, :provided_by_gcp, :production_environment, projects: [project]) } + include_examples ':certificate_based_clusters feature flag index responses' do + let(:subject) { go } + end + it 'lists available clusters and renders html' do go @@ -118,6 +122,10 @@ RSpec.describe Projects::ClustersController do } 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' } @@ -264,6 +272,10 @@ RSpec.describe Projects::ClustersController do 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 @@ -360,6 +372,10 @@ RSpec.describe Projects::ClustersController do post :create_user, 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 creates a cluster' do it 'creates a new cluster' do @@ -477,6 +493,10 @@ RSpec.describe Projects::ClustersController do post :create_aws, params: params.merge(namespace_id: project.namespace, project_id: project) 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 } @@ -548,6 +568,10 @@ RSpec.describe Projects::ClustersController do .and_return(double(execute: double)) end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + it 'updates the associated role with the supplied ARN' do go @@ -603,6 +627,10 @@ RSpec.describe Projects::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + it 'deletes the namespaces associated with the cluster' do expect { go }.to change { Clusters::KubernetesNamespace.count } @@ -640,6 +668,10 @@ RSpec.describe Projects::ClustersController do format: :json end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + describe 'functionality' do it "responds with matching schema" do go @@ -685,6 +717,10 @@ RSpec.describe Projects::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + describe 'functionality' do render_views @@ -749,6 +785,10 @@ RSpec.describe Projects::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + it "updates and redirects back to show page" do go @@ -842,6 +882,10 @@ RSpec.describe Projects::ClustersController do } end + include_examples ':certificate_based_clusters feature flag controller responses' do + let(:subject) { go } + end + describe 'functionality' do context 'when cluster is provided by GCP' do context 'when cluster is created' do diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 0fcdeb2edde..fdfc21887a6 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Projects::EnvironmentsController do include MetricsDashboardHelpers include KubernetesHelpers - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user, name: 'main-dos').tap { |u| project.add_maintainer(u) } } let_it_be(:reporter) { create(:user, name: 'repo-dos').tap { |u| project.add_reporter(u) } } @@ -55,11 +55,11 @@ RSpec.describe Projects::EnvironmentsController do let(:environments) { json_response['environments'] } context 'with default parameters' do - before do - get :index, params: environment_params(format: :json) - end + subject { get :index, params: environment_params(format: :json) } it 'responds with a flat payload describing available environments' do + subject + expect(environments.count).to eq 3 expect(environments.first).to include('name' => 'production', 'name_without_type' => 'production') expect(environments.second).to include('name' => 'staging/review-1', 'name_without_type' => 'review-1') @@ -69,9 +69,28 @@ RSpec.describe Projects::EnvironmentsController do end it 'sets the polling interval header' do + subject + expect(response).to have_gitlab_http_status(:ok) expect(response.headers['Poll-Interval']).to eq("3000") end + + context 'validates latest deployment' do + let_it_be(:test_environment) do + create(:environment, project: project, name: 'staging/review-4', state: :available) + end + + before do + create_list(:deployment, 2, :success, environment: test_environment, project: project) + end + + it 'responds with the latest deployment for the environment' do + subject + + environment = environments.find { |env| env['id'] == test_environment.id } + expect(environment['last_deployment']['id']).to eq(test_environment.deployments.last.id) + end + end end context 'when a folder-based nested structure is requested' do diff --git a/spec/controllers/projects/error_tracking_controller_spec.rb b/spec/controllers/projects/error_tracking_controller_spec.rb index 822778779eb..b4f21e070c6 100644 --- a/spec/controllers/projects/error_tracking_controller_spec.rb +++ b/spec/controllers/projects/error_tracking_controller_spec.rb @@ -50,9 +50,7 @@ RSpec.describe Projects::ErrorTrackingController do let(:external_url) { 'http://example.com' } context 'no data' do - let(:permitted_params) do - ActionController::Parameters.new({}).permit! - end + let(:permitted_params) { permit_index_parameters!({}) } before do expect(ErrorTracking::ListIssuesService) @@ -75,9 +73,7 @@ RSpec.describe Projects::ErrorTrackingController do let(:search_term) { 'something' } let(:sort) { 'last_seen' } let(:params) { project_params(format: :json, search_term: search_term, sort: sort, cursor: cursor) } - let(:permitted_params) do - ActionController::Parameters.new(search_term: search_term, sort: sort, cursor: cursor).permit! - end + let(:permitted_params) { permit_index_parameters!(search_term: search_term, sort: sort, cursor: cursor) } before do expect(ErrorTracking::ListIssuesService) @@ -114,7 +110,7 @@ RSpec.describe Projects::ErrorTrackingController do context 'without extra params' do before do expect(ErrorTracking::ListIssuesService) - .to receive(:new).with(project, user, {}) + .to receive(:new).with(project, user, permit_index_parameters!({})) .and_return(list_issues_service) end @@ -179,6 +175,15 @@ RSpec.describe Projects::ErrorTrackingController do end end end + + private + + def permit_index_parameters!(params) + ActionController::Parameters.new( + **params, + tracking_event: :error_tracking_view_list + ).permit! + end end describe 'GET #issue_details' do @@ -188,7 +193,8 @@ RSpec.describe Projects::ErrorTrackingController do let(:permitted_params) do ActionController::Parameters.new( - { issue_id: issue_id.to_s } + issue_id: issue_id.to_s, + tracking_event: :error_tracking_view_details ).permit! end diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index 0f8f3b49e02..962ef93dc72 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -199,15 +199,6 @@ RSpec.describe Projects::ForksController do expect(json_response['namespaces'][1]['id']).to eq(group.id) end - it 'responds with group only when fork_project_form feature flag is disabled' do - stub_feature_flags(fork_project_form: false) - do_request - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['namespaces'].length).to eq(1) - expect(json_response['namespaces'][0]['id']).to eq(group.id) - end - context 'N+1 queries' do before do create(:fork_network, root_project: project) diff --git a/spec/controllers/projects/incidents_controller_spec.rb b/spec/controllers/projects/incidents_controller_spec.rb index 460821634b0..20cf0dcfd3a 100644 --- a/spec/controllers/projects/incidents_controller_spec.rb +++ b/spec/controllers/projects/incidents_controller_spec.rb @@ -43,6 +43,7 @@ RSpec.describe Projects::IncidentsController do expect(response).to have_gitlab_http_status(:ok) expect(response).to render_template(:index) + expect(Gon.features).to include('incidentEscalations' => true) end context 'when user is unauthorized' do diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index bf0b833b311..9d3711d8a96 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -72,7 +72,21 @@ RSpec.describe Projects::IssuesController do project.add_developer(user) end - it_behaves_like "issuables list meta-data", :issue + 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' } @@ -605,11 +619,11 @@ RSpec.describe Projects::IssuesController do end end - context 'when the SpamVerdictService disallows' do + context 'when an issue is identified as spam' do before do stub_application_setting(recaptcha_enabled: true) - expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service| - expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW) + allow_next_instance_of(Spam::AkismetService) do |akismet_service| + allow(akismet_service).to receive(:spam?).and_return(true) end end @@ -926,8 +940,8 @@ RSpec.describe Projects::IssuesController do context 'when an issue is identified as spam' do context 'when recaptcha is not verified' do before do - expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service| - expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW) + allow_next_instance_of(Spam::AkismetService) do |akismet_service| + allow(akismet_service).to receive(:spam?).and_return(true) end end @@ -1004,6 +1018,7 @@ RSpec.describe Projects::IssuesController do end it 'returns 200 status' do + update_verified_issue expect(response).to have_gitlab_http_status(:ok) end @@ -1051,35 +1066,6 @@ RSpec.describe Projects::IssuesController do .not_to exceed_query_limit(control_count + 2 * labels.count) end - context 'real-time sidebar feature flag' do - let_it_be(:project) { create(:project, :public) } - let_it_be(:issue) { create(:issue, project: project) } - - context 'when enabled' do - before do - stub_feature_flags(real_time_issue_sidebar: true) - end - - it 'pushes the correct value to the frontend' do - go(id: issue.to_param) - - expect(Gon.features).to include('realTimeIssueSidebar' => true) - end - end - - context 'when disabled' do - before do - stub_feature_flags(real_time_issue_sidebar: false) - end - - it 'pushes the correct value to the frontend' do - go(id: issue.to_param) - - expect(Gon.features).to include('realTimeIssueSidebar' => false) - end - end - end - it 'logs the view with Gitlab::Search::RecentIssues' do sign_in(user) recent_issues_double = instance_double(::Gitlab::Search::RecentIssues, log_view: nil) @@ -1260,11 +1246,11 @@ RSpec.describe Projects::IssuesController do end end - context 'when SpamVerdictService requires recaptcha' do + context 'when an issue is identified as spam and requires recaptcha' do context 'when captcha is not verified' do before do - expect_next_instance_of(Spam::SpamVerdictService) do |verdict_service| - expect(verdict_service).to receive(:execute).and_return(CONDITIONAL_ALLOW) + allow_next_instance_of(Spam::AkismetService) do |akismet_service| + allow(akismet_service).to receive(:spam?).and_return(true) end end diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb index a5c59b7e22d..367781c0e76 100644 --- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb @@ -220,29 +220,6 @@ RSpec.describe Projects::MergeRequests::DiffsController do end end - context "with the :default_merge_ref_for_diffs flag on" do - let(:diffable_merge_ref) { true } - - subject do - go(diff_head: true, - diff_id: merge_request.merge_request_diff.id, - start_sha: merge_request.merge_request_diff.start_commit_sha) - end - - it "correctly generates the right diff between versions" do - MergeRequests::MergeToRefService.new(project: project, current_user: merge_request.author).execute(merge_request) - - expect_next_instance_of(CompareService) do |service| - expect(service).to receive(:execute).with( - project, - merge_request.merge_request_diff.head_commit_sha, - straight: true) - end - - subject - end - end - context 'with diff_head param passed' do before do allow(merge_request).to receive(:diffable_merge_ref?) @@ -259,6 +236,23 @@ RSpec.describe Projects::MergeRequests::DiffsController do expect(response).to have_gitlab_http_status(:ok) end + + context 'when diff_id and start_sha are set' do + it 'correctly generates the right diff between versions' do + MergeRequests::MergeToRefService.new(project: project, current_user: merge_request.author).execute(merge_request) + + expect_next_instance_of(CompareService) do |service| + expect(service).to receive(:execute).with( + project, + merge_request.merge_request_diff.head_commit_sha, + straight: true) + end + + go(diff_head: true, + diff_id: merge_request.merge_request_diff.id, + start_sha: merge_request.merge_request_diff.start_commit_sha) + end + end end context 'the merge request cannot be compared with head' do diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 2390687c3ea..f6db809c2e3 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -68,6 +68,18 @@ RSpec.describe Projects::MergeRequestsController do end describe 'as html' do + it 'sets the endpoint_metadata_url' do + go + + expect(assigns["endpoint_metadata_url"]).to eq( + diffs_metadata_project_json_merge_request_path( + project, + merge_request, + 'json', + diff_head: true, + view: 'inline')) + end + context 'when diff files were cleaned' do render_views @@ -85,23 +97,6 @@ RSpec.describe Projects::MergeRequestsController do end end - context 'with `default_merge_ref_for_diffs` feature flag enabled' do - before do - stub_feature_flags(default_merge_ref_for_diffs: true) - go - end - - it 'adds the diff_head parameter' do - expect(assigns["endpoint_metadata_url"]).to eq( - diffs_metadata_project_json_merge_request_path( - project, - merge_request, - 'json', - diff_head: true, - view: 'inline')) - end - end - context 'when diff is missing' do render_views diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index 4a51e2ed5a0..8fae82d54a2 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -292,12 +292,8 @@ RSpec.describe Projects::PipelinesController do subject { project.namespace } - context 'code_quality_walkthrough experiment' do - it_behaves_like 'tracks assignment and records the subject', :code_quality_walkthrough, :namespace - end - - context 'ci_runner_templates experiment' do - it_behaves_like 'tracks assignment and records the subject', :ci_runner_templates, :namespace + context 'runners_availability_section experiment' do + it_behaves_like 'tracks assignment and records the subject', :runners_availability_section, :namespace end end @@ -936,6 +932,33 @@ RSpec.describe Projects::PipelinesController do expect(response).to have_gitlab_http_status(:not_found) end end + + context 'when access denied' do + it 'returns an error' do + sign_in(create(:user)) + + post_retry + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when service returns an error' do + before do + service_response = ServiceResponse.error(message: 'some error', http_status: 404) + allow_next_instance_of(::Ci::RetryPipelineService) do |service| + allow(service).to receive(:check_access).and_return(service_response) + end + end + + it 'does not retry' do + post_retry + + expect(response).to have_gitlab_http_status(:not_found) + expect(response.body).to include('some error') + expect(::Ci::RetryPipelineWorker).not_to have_received(:perform_async).with(pipeline.id, user.id) + end + end end describe 'POST cancel.json' do diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index d8ef95cf11a..20a114bbe8c 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -147,137 +147,6 @@ RSpec.describe Projects::ProjectMembersController do end end - describe 'POST create' do - let_it_be(:project_user) { create(:user) } - - before do - sign_in(user) - end - - context 'when user does not have enough rights' do - before do - project.add_developer(user) - end - - it 'returns 404', :aggregate_failures do - post :create, params: { - namespace_id: project.namespace, - project_id: project, - user_ids: project_user.id, - access_level: Gitlab::Access::GUEST - } - - expect(response).to have_gitlab_http_status(:not_found) - expect(project.users).not_to include project_user - end - end - - context 'when user has enough rights' do - before do - project.add_maintainer(user) - end - - it 'adds user to members', :aggregate_failures, :snowplow do - post :create, params: { - namespace_id: project.namespace, - project_id: project, - user_ids: project_user.id, - access_level: Gitlab::Access::GUEST - } - - expect(controller).to set_flash.to 'Users were successfully added.' - expect(response).to redirect_to(project_project_members_path(project)) - expect(project.users).to include project_user - expect_snowplow_event( - category: 'Members::CreateService', - action: 'create_member', - label: 'project-members-page', - property: 'existing_user', - user: user - ) - end - - it 'adds no user to members', :aggregate_failures do - expect_next_instance_of(Members::CreateService) do |instance| - expect(instance).to receive(:execute).and_return(status: :failure, message: 'Message') - end - - post :create, params: { - namespace_id: project.namespace, - project_id: project, - user_ids: '', - access_level: Gitlab::Access::GUEST - } - - expect(controller).to set_flash.to 'Message' - expect(response).to redirect_to(project_project_members_path(project)) - end - end - - context 'adding project bot' do - let_it_be(:project_bot) { create(:user, :project_bot) } - - before do - project.add_maintainer(user) - - unrelated_project = create(:project) - unrelated_project.add_maintainer(project_bot) - end - - it 'returns error', :aggregate_failures do - post :create, params: { - namespace_id: project.namespace, - project_id: project, - user_ids: project_bot.id, - access_level: Gitlab::Access::GUEST - } - - expect(flash[:alert]).to include('project bots cannot be added to other groups / projects') - expect(response).to redirect_to(project_project_members_path(project)) - end - end - - context 'access expiry date' do - before do - project.add_maintainer(user) - end - - subject do - post :create, params: { - namespace_id: project.namespace, - project_id: project, - user_ids: project_user.id, - access_level: Gitlab::Access::GUEST, - expires_at: expires_at - } - end - - context 'when set to a date in the past' do - let(:expires_at) { 2.days.ago } - - it 'does not add user to members', :aggregate_failures do - subject - - expect(flash[:alert]).to include('Expires at cannot be a date in the past') - expect(response).to redirect_to(project_project_members_path(project)) - expect(project.users).not_to include project_user - end - end - - context 'when set to a date in the future' do - let(:expires_at) { 5.days.from_now } - - it 'adds user to members', :aggregate_failures do - subject - - expect(controller).to set_flash.to 'Users were successfully added.' - expect(response).to redirect_to(project_project_members_path(project)) - expect(project.users).to include project_user - end - end - end - end - describe 'PUT update' do let_it_be(:requester) { create(:project_member, :access_request, project: project) } @@ -603,99 +472,6 @@ RSpec.describe Projects::ProjectMembersController do end end - describe 'POST apply_import' do - let_it_be(:another_project) { create(:project, :private) } - let_it_be(:member) { create(:user) } - - before do - project.add_maintainer(user) - another_project.add_guest(member) - sign_in(user) - end - - shared_context 'import applied' do - before do - post(:apply_import, params: { - namespace_id: project.namespace, - project_id: project, - source_project_id: another_project.id - }) - end - end - - context 'when user can admin source project members' do - before do - another_project.add_maintainer(user) - end - - include_context 'import applied' - - it 'imports source project members', :aggregate_failures do - expect(project.team_members).to include member - expect(controller).to set_flash.to 'Successfully imported' - expect(response).to redirect_to( - project_project_members_path(project) - ) - end - end - - context "when user can't admin source project members" do - before do - another_project.add_developer(user) - end - - include_context 'import applied' - - it 'does not import team members' do - expect(project.team_members).not_to include member - end - - it 'responds with not found' do - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - describe 'POST create' do - let_it_be(:stranger) { create(:user) } - - context 'when creating owner' do - before do - project.add_maintainer(user) - sign_in(user) - end - - it 'does not create a member' do - expect do - post :create, params: { - user_ids: stranger.id, - namespace_id: project.namespace, - access_level: Member::OWNER, - project_id: project - } - end.to change { project.members.count }.by(0) - end - end - - context 'when create maintainer' do - before do - project.add_maintainer(user) - sign_in(user) - end - - it 'creates a member' do - expect do - post :create, params: { - user_ids: stranger.id, - namespace_id: project.namespace, - access_level: Member::MAINTAINER, - project_id: project - } - end.to change { project.members.count }.by(1) - end - end - end - describe 'POST resend_invite' do let_it_be(:member) { create(:project_member, project: project) } diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb index 120020273f9..9dd18e58109 100644 --- a/spec/controllers/projects/releases_controller_spec.rb +++ b/spec/controllers/projects/releases_controller_spec.rb @@ -222,6 +222,168 @@ RSpec.describe Projects::ReleasesController do end end + describe 'GET #latest_permalink' do + # Uses default order_by=released_at parameter. + subject do + get :latest_permalink, params: { namespace_id: project.namespace, project_id: project } + end + + before do + sign_in(user) + end + + let(:release) { create(:release, project: project) } + let(:tag) { CGI.escape(release.tag) } + + context 'when user is a guest' do + let(:project) { private_project } + let(:user) { guest } + + it 'proceeds with the redirect' do + subject + + expect(response).to have_gitlab_http_status(:redirect) + end + end + + context 'when user is an external user for the project' do + let(:project) { private_project } + let(:user) { create(:user) } + + it 'behaves like not found' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when there are no releases for the project' do + let(:project) { create(:project, :repository, :public) } + let(:user) { developer } + + before do + project.releases.destroy_all # rubocop: disable Cop/DestroyAll + end + + it 'behaves like not found' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'multiple releases' do + let(:user) { developer } + + it 'redirects to the latest release' do + create(:release, project: project, released_at: 1.day.ago) + latest_release = create(:release, project: project, released_at: Time.current) + + subject + + expect(response).to redirect_to("#{project_releases_path(project)}/#{latest_release.tag}") + end + end + + context 'suffix path redirection' do + let(:user) { developer } + let(:suffix_path) { 'downloads/zips/helm-hello-world.zip' } + let!(:latest_release) { create(:release, project: project, released_at: Time.current) } + + subject do + get :latest_permalink, params: { + namespace_id: project.namespace, + project_id: project, + suffix_path: suffix_path + } + end + + it 'redirects to the latest release with suffix path and format' do + subject + + expect(response).to redirect_to( + "#{project_releases_path(project)}/#{latest_release.tag}/#{suffix_path}") + end + + context 'suffix path abuse' do + let(:suffix_path) { 'downloads/zips/../../../../../../../robots.txt'} + + it 'raises attack error' do + expect do + subject + end.to raise_error(Gitlab::Utils::PathTraversalAttackError) + end + end + + context 'url parameters' do + let(:suffix_path) { 'downloads/zips/helm-hello-world.zip' } + + subject do + get :latest_permalink, params: { + namespace_id: project.namespace, + project_id: project, + suffix_path: suffix_path, + order_by: 'released_at', + param_1: 1, + param_2: 2 + } + end + + it 'carries over query parameters without order_by parameter in the redirect' do + subject + + expect(response).to redirect_to( + "#{project_releases_path(project)}/#{latest_release.tag}/#{suffix_path}?param_1=1¶m_2=2") + end + end + end + + context 'order_by parameter' do + let!(:latest_release) { create(:release, project: project, released_at: Time.current, tag: 'latest') } + + shared_examples_for 'redirects to latest release ordered by using released_at' do + it do + expect(Release).to receive(:order_released_desc).and_call_original + + subject + + expect(response).to redirect_to("#{project_releases_path(project)}/#{latest_release.tag}") + end + end + + before do + create(:release, project: project, released_at: 1.day.ago, tag: 'alpha') + create(:release, project: project, released_at: 2.days.ago, tag: 'beta') + end + + context 'invalid parameter' do + let(:user) { developer } + + subject do + get :latest_permalink, params: { + namespace_id: project.namespace, + project_id: project, + order_by: 'unsupported' + } + end + + it_behaves_like 'redirects to latest release ordered by using released_at' + end + + context 'valid parameter' do + subject do + get :latest_permalink, params: { + namespace_id: project.namespace, + project_id: project, + order_by: 'released_at' + } + end + + it_behaves_like 'redirects to latest release ordered by using released_at' + end + end + end + # `GET #downloads` is addressed in spec/requests/projects/releases_controller_spec.rb private diff --git a/spec/controllers/projects/runners_controller_spec.rb b/spec/controllers/projects/runners_controller_spec.rb index 246a37129d7..57d1695b842 100644 --- a/spec/controllers/projects/runners_controller_spec.rb +++ b/spec/controllers/projects/runners_controller_spec.rb @@ -37,7 +37,7 @@ RSpec.describe Projects::RunnersController do describe '#destroy' do it 'destroys the runner' do - expect_next_instance_of(Ci::UnregisterRunnerService, runner) do |service| + expect_next_instance_of(Ci::Runners::UnregisterRunnerService, runner, user) do |service| expect(service).to receive(:execute).once.and_call_original end diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb index 860bbc1c5cc..f8cee09006c 100644 --- a/spec/controllers/projects/serverless/functions_controller_spec.rb +++ b/spec/controllers/projects/serverless/functions_controller_spec.rb @@ -39,9 +39,24 @@ RSpec.describe Projects::Serverless::FunctionsController do 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) { [] } @@ -147,6 +162,10 @@ RSpec.describe Projects::Serverless::FunctionsController do 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" }) @@ -239,6 +258,10 @@ RSpec.describe Projects::Serverless::FunctionsController do 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" }) diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb index f3c7b501faa..35e5422d072 100644 --- a/spec/controllers/projects/services_controller_spec.rb +++ b/spec/controllers/projects/services_controller_spec.rb @@ -353,7 +353,16 @@ RSpec.describe Projects::ServicesController do it 'does not modify integration' do expect { put :update, params: project_params.merge(service: integration_params) } - .not_to change { project.prometheus_integration.reload.attributes } + .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', + 'encrypted_properties_tmp') + + [attrs, pi.encrypted_properties_tmp] end end diff --git a/spec/controllers/projects/tags/releases_controller_spec.rb b/spec/controllers/projects/tags/releases_controller_spec.rb index b3d4d944440..1d2385f54f9 100644 --- a/spec/controllers/projects/tags/releases_controller_spec.rb +++ b/spec/controllers/projects/tags/releases_controller_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe Projects::Tags::ReleasesController do let!(:project) { create(:project, :repository) } let!(:user) { create(:user) } - let!(:release) { create(:release, project: project) } + let!(:release) { create(:release, project: project, tag: "v1.1.0") } let!(:tag) { release.tag } before do @@ -27,7 +27,7 @@ RSpec.describe Projects::Tags::ReleasesController do end it 'retrieves an existing release' do - response = get :edit, params: { namespace_id: project.namespace, project_id: project, tag_id: release.tag } + response = get :edit, params: { namespace_id: project.namespace, project_id: project, tag_id: tag } release = assigns(:release) expect(release).not_to be_nil diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb index f955f9d0248..d0971e96910 100644 --- a/spec/controllers/projects/tags_controller_spec.rb +++ b/spec/controllers/projects/tags_controller_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe Projects::TagsController do let(:project) { create(:project, :public, :repository) } - let!(:release) { create(:release, project: project) } + let!(:release) { create(:release, project: project, tag: "v1.1.0") } let!(:invalid_release) { create(:release, project: project, tag: 'does-not-exist') } let(:user) { create(:user) } diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 08d1d88fcda..c098ea71f7a 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -1211,16 +1211,6 @@ RSpec.describe ProjectsController do expect(response).to have_gitlab_http_status(:success) end - - context 'when "strong_parameters_for_project_controller" FF is disabled' do - before do - stub_feature_flags(strong_parameters_for_project_controller: false) - end - - it 'raises an exception' do - expect { request }.to raise_error(TypeError) - end - end end end @@ -1600,71 +1590,22 @@ RSpec.describe ProjectsController do get :show, format: :atom, params: { id: public_project, namespace_id: public_project.namespace } - expect(response).to render_template('xml.atom') + expect(response).to have_gitlab_http_status(:success) + expect(response).to render_template(:show) + expect(response).to render_template(layout: :xml) expect(assigns(:events)).to eq([event]) end it 'filters by calling event.visible_to_user?' do get :show, format: :atom, params: { id: public_project, namespace_id: public_project.namespace } - expect(response).to render_template('xml.atom') + expect(response).to have_gitlab_http_status(:success) + expect(response).to render_template(:show) + expect(response).to render_template(layout: :xml) expect(assigns(:events)).to eq([event]) end end - describe 'GET resolve' do - shared_examples 'resolvable endpoint' do - it 'redirects to the project page' do - get :resolve, params: { id: project.id } - - expect(response).to have_gitlab_http_status(:found) - expect(response).to redirect_to(project_path(project)) - end - end - - context 'with an authenticated user' do - before do - sign_in(user) - end - - context 'when user has access to the project' do - before do - project.add_developer(user) - end - - it_behaves_like 'resolvable endpoint' - end - - context 'when user has no access to the project' do - it 'gives 404 for existing project' do - get :resolve, params: { id: project.id } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - it 'gives 404 for non-existing project' do - get :resolve, params: { id: '0' } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'non authenticated user' do - context 'with a public project' do - let(:project) { public_project } - - it_behaves_like 'resolvable endpoint' - end - - it 'gives 404 for private project' do - get :resolve, params: { id: project.id } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - it 'updates Service Desk attributes' do project.add_maintainer(user) sign_in(user) diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb index 0f1501d4c3c..9482448fc03 100644 --- a/spec/controllers/search_controller_spec.rb +++ b/spec/controllers/search_controller_spec.rb @@ -251,8 +251,8 @@ RSpec.describe SearchController do it_behaves_like 'tracking unique hll events' do subject(:request) { get :show, params: { scope: 'projects', search: 'term' } } - let(:target_id) { 'i_search_total' } - let(:expected_type) { instance_of(String) } + let(:target_event) { 'i_search_total' } + let(:expected_value) { instance_of(String) } end end @@ -291,7 +291,7 @@ RSpec.describe SearchController do end end - it_behaves_like 'rate limited endpoint', rate_limit_key: :user_email_lookup do + it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do let(:current_user) { user } def request @@ -355,7 +355,7 @@ RSpec.describe SearchController do expect(json_response).to eq({ 'count' => '0' }) end - it_behaves_like 'rate limited endpoint', rate_limit_key: :user_email_lookup do + it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do let(:current_user) { user } def request @@ -375,7 +375,7 @@ RSpec.describe SearchController do expect(json_response).to match_array([]) end - it_behaves_like 'rate limited endpoint', rate_limit_key: :user_email_lookup do + it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do let(:current_user) { user } def request @@ -445,6 +445,26 @@ RSpec.describe SearchController do end context 'unauthorized user' do + describe 'search rate limits' do + using RSpec::Parameterized::TableSyntax + + let(:project) { create(:project, :public) } + + where(:endpoint, :params) do + :show | { search: 'hello', scope: 'projects' } + :count | { search: 'hello', scope: 'projects' } + :autocomplete | { term: 'hello', scope: 'projects' } + end + + with_them do + it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit_unauthenticated do + def request + get endpoint, params: params.merge(project_id: project.id) + end + end + end + end + describe 'GET #opensearch' do render_views diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 31de00dd8bd..03d053e6f97 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -235,7 +235,7 @@ RSpec.describe SessionsController do unsuccesful_login(user_params) expect(response).to render_template(:new) - expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.' + expect(flash[:alert]).to include _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.') expect(subject.current_user).to be_nil end @@ -259,7 +259,7 @@ RSpec.describe SessionsController do unsuccesful_login(user_params, sesion_params: { failed_login_attempts: 6 }) expect(response).to render_template(:new) - expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.' + expect(flash[:alert]).to include _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.') expect(subject.current_user).to be_nil end @@ -279,7 +279,7 @@ RSpec.describe SessionsController do unsuccesful_login(user_params) expect(response).to render_template(:new) - expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.' + expect(flash[:alert]).to include _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.') expect(subject.current_user).to be_nil end diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index a82c44fcc44..18b2d3b14ec 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -176,8 +176,8 @@ RSpec.describe SnippetsController do it_behaves_like 'tracking unique hll events' do subject(:request) { get :show, params: { id: public_snippet.to_param } } - let(:target_id) { 'i_snippets_show' } - let(:expected_type) { instance_of(String) } + let(:target_event) { 'i_snippets_show' } + let(:expected_value) { instance_of(String) } end end |