diff options
Diffstat (limited to 'spec/requests/projects')
13 files changed, 406 insertions, 406 deletions
diff --git a/spec/requests/projects/environments_controller_spec.rb b/spec/requests/projects/environments_controller_spec.rb index 0890b0c45da..66ab265fc0f 100644 --- a/spec/requests/projects/environments_controller_spec.rb +++ b/spec/requests/projects/environments_controller_spec.rb @@ -30,7 +30,7 @@ RSpec.describe Projects::EnvironmentsController do deployer = create(:user) pipeline = create(:ci_pipeline, project: environment.project) build = create(:ci_build, environment: environment.name, pipeline: pipeline, user: deployer) - create(:deployment, :success, environment: environment, deployable: build, user: deployer, - project: project, sha: commit.sha) + create(:deployment, :success, + environment: environment, deployable: build, user: deployer, project: project, sha: commit.sha) end end diff --git a/spec/requests/projects/google_cloud/configuration_controller_spec.rb b/spec/requests/projects/google_cloud/configuration_controller_spec.rb index 08d4ad2f9ba..41593b8d7a7 100644 --- a/spec/requests/projects/google_cloud/configuration_controller_spec.rb +++ b/spec/requests/projects/google_cloud/configuration_controller_spec.rb @@ -2,9 +2,6 @@ require 'spec_helper' -# Mock Types -MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret) - RSpec.describe Projects::GoogleCloud::ConfigurationController do let_it_be(:project) { create(:project, :public) } let_it_be(:url) { project_google_cloud_configuration_path(project) } @@ -29,10 +26,9 @@ RSpec.describe Projects::GoogleCloud::ConfigurationController do get url expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::ConfigurationController', + action: 'error_invalid_user', + label: nil, project: project, user: unauthorized_member ) @@ -56,7 +52,7 @@ RSpec.describe Projects::GoogleCloud::ConfigurationController do context 'but gitlab instance is not configured for google oauth2' do it 'returns forbidden' do - unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '') + unconfigured_google_oauth2 = Struct.new(:app_id, :app_secret).new('', '') allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for) .with('google_oauth2') .and_return(unconfigured_google_oauth2) @@ -68,11 +64,9 @@ RSpec.describe Projects::GoogleCloud::ConfigurationController do expect(response).to have_gitlab_http_status(:forbidden) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'google_oauth2_enabled!', - label: 'error_access_denied', - extra: { reason: 'google_oauth2_not_configured', - config: unconfigured_google_oauth2 }, + category: 'Projects::GoogleCloud::ConfigurationController', + action: 'error_google_oauth2_not_enabled', + label: nil, project: project, user: authorized_member ) @@ -93,10 +87,9 @@ RSpec.describe Projects::GoogleCloud::ConfigurationController do expect(response).to have_gitlab_http_status(:not_found) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'feature_flag_enabled!', - label: 'error_access_denied', - property: 'feature_flag_not_enabled', + category: 'Projects::GoogleCloud::ConfigurationController', + action: 'error_feature_flag_not_enabled', + label: nil, project: project, user: authorized_member ) @@ -117,20 +110,9 @@ RSpec.describe Projects::GoogleCloud::ConfigurationController do expect(response).to be_successful expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'configuration#index', - label: 'success', - extra: { - configurationUrl: project_google_cloud_configuration_path(project), - deploymentsUrl: project_google_cloud_deployments_path(project), - databasesUrl: project_google_cloud_databases_path(project), - serviceAccounts: [], - createServiceAccountUrl: project_google_cloud_service_accounts_path(project), - emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg'), - configureGcpRegionsUrl: project_google_cloud_gcp_regions_path(project), - gcpRegions: [], - revokeOauthUrl: nil - }, + category: 'Projects::GoogleCloud::ConfigurationController', + action: 'render_page', + label: nil, project: project, user: authorized_member ) diff --git a/spec/requests/projects/google_cloud/databases_controller_spec.rb b/spec/requests/projects/google_cloud/databases_controller_spec.rb index c9335f8f317..4edef71f326 100644 --- a/spec/requests/projects/google_cloud/databases_controller_spec.rb +++ b/spec/requests/projects/google_cloud/databases_controller_spec.rb @@ -2,133 +2,166 @@ require 'spec_helper' -# Mock Types -MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret) +RSpec.describe Projects::GoogleCloud::DatabasesController, :snowplow do + shared_examples 'shared examples for database controller endpoints' do + include_examples 'requires `admin_project_google_cloud` role' -RSpec.describe Projects::GoogleCloud::DatabasesController do - let_it_be(:project) { create(:project, :public) } - let_it_be(:url) { project_google_cloud_databases_path(project) } + include_examples 'requires feature flag `incubation_5mp_google_cloud` enabled' - let_it_be(:user_guest) { create(:user) } - let_it_be(:user_developer) { create(:user) } - let_it_be(:user_maintainer) { create(:user) } + include_examples 'requires valid Google OAuth2 configuration' - let_it_be(:unauthorized_members) { [user_guest, user_developer] } - let_it_be(:authorized_members) { [user_maintainer] } + include_examples 'requires valid Google Oauth2 token' do + let_it_be(:mock_gcp_projects) { [{}, {}, {}] } + let_it_be(:mock_branches) { [] } + let_it_be(:mock_tags) { [] } + end + end + + context '-/google_cloud/databases' do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:renders_template) { 'projects/google_cloud/databases/index' } + let_it_be(:redirects_to) { nil } - before do - project.add_guest(user_guest) - project.add_developer(user_developer) - project.add_maintainer(user_maintainer) + subject { get project_google_cloud_databases_path(project) } + + include_examples 'shared examples for database controller endpoints' end - context 'when accessed by unauthorized members' do - it 'returns not found on GET request' do - unauthorized_members.each do |unauthorized_member| - sign_in(unauthorized_member) + context '-/google_cloud/databases/new/postgres' do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:renders_template) { 'projects/google_cloud/databases/cloudsql_form' } + let_it_be(:redirects_to) { nil } - get url - expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', - project: project, - user: unauthorized_member - ) + subject { get new_project_google_cloud_database_path(project, :postgres) } - expect(response).to have_gitlab_http_status(:not_found) - end - end + include_examples 'shared examples for database controller endpoints' end - context 'when accessed by authorized members' do - it 'returns successful' do - authorized_members.each do |authorized_member| - sign_in(authorized_member) + context '-/google_cloud/databases/new/mysql' do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:renders_template) { 'projects/google_cloud/databases/cloudsql_form' } + let_it_be(:redirects_to) { nil } - get url + subject { get new_project_google_cloud_database_path(project, :mysql) } - expect(response).to be_successful - expect(response).to render_template('projects/google_cloud/databases/index') - end - end + include_examples 'shared examples for database controller endpoints' + end - context 'but gitlab instance is not configured for google oauth2' do - it 'returns forbidden' do - unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '') - allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for) - .with('google_oauth2') - .and_return(unconfigured_google_oauth2) + context '-/google_cloud/databases/new/sqlserver' do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:renders_template) { 'projects/google_cloud/databases/cloudsql_form' } + let_it_be(:redirects_to) { nil } - authorized_members.each do |authorized_member| - sign_in(authorized_member) + subject { get new_project_google_cloud_database_path(project, :sqlserver) } - get url + include_examples 'shared examples for database controller endpoints' + end - expect(response).to have_gitlab_http_status(:forbidden) - expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'google_oauth2_enabled!', - label: 'error_access_denied', - extra: { reason: 'google_oauth2_not_configured', - config: unconfigured_google_oauth2 }, - project: project, - user: authorized_member - ) + context '-/google_cloud/databases/create' do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:renders_template) { nil } + let_it_be(:redirects_to) { project_google_cloud_databases_path(project) } + + subject { post project_google_cloud_databases_path(project) } + + include_examples 'shared examples for database controller endpoints' + + context 'when the request is valid' do + before do + project.add_maintainer(user) + sign_in(user) + + allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client| + allow(client).to receive(:validate_token).and_return(true) + allow(client).to receive(:list_projects).and_return(mock_gcp_projects) + end + + allow_next_instance_of(BranchesFinder) do |finder| + allow(finder).to receive(:execute).and_return(mock_branches) + end + + allow_next_instance_of(TagsFinder) do |finder| + allow(finder).to receive(:execute).and_return(mock_branches) end end - end - context 'but feature flag is disabled' do - before do - stub_feature_flags(incubation_5mp_google_cloud: false) + subject do + post project_google_cloud_databases_path(project) end - it 'returns not found' do - authorized_members.each do |authorized_member| - sign_in(authorized_member) + it 'calls EnableCloudsqlService and redirects on error' do + expect_next_instance_of(::GoogleCloud::EnableCloudsqlService) do |service| + expect(service).to receive(:execute) + .and_return({ status: :error, message: 'error' }) + end - get url + subject - expect(response).to have_gitlab_http_status(:not_found) - expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'feature_flag_enabled!', - label: 'error_access_denied', - property: 'feature_flag_not_enabled', - project: project, - user: authorized_member - ) - end + expect(response).to redirect_to(project_google_cloud_databases_path(project)) + + expect_snowplow_event( + category: 'Projects::GoogleCloud::DatabasesController', + action: 'error_enable_cloudsql_services', + label: nil, + project: project, + user: user + ) end - end - context 'but google oauth2 token is not valid' do - it 'does not return revoke oauth url' do - allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client| - allow(client).to receive(:validate_token).and_return(false) + context 'when EnableCloudsqlService is successful' do + before do + allow_next_instance_of(::GoogleCloud::EnableCloudsqlService) do |service| + allow(service).to receive(:execute) + .and_return({ status: :success, message: 'success' }) + end end - authorized_members.each do |authorized_member| - sign_in(authorized_member) + it 'calls CreateCloudsqlInstanceService and redirects on error' do + expect_next_instance_of(::GoogleCloud::CreateCloudsqlInstanceService) do |service| + expect(service).to receive(:execute) + .and_return({ status: :error, message: 'error' }) + end + + subject - get url + expect(response).to redirect_to(project_google_cloud_databases_path(project)) - expect(response).to be_successful expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'databases#index', - label: 'success', - extra: { - configurationUrl: project_google_cloud_configuration_path(project), - deploymentsUrl: project_google_cloud_deployments_path(project), - databasesUrl: project_google_cloud_databases_path(project) - }, + category: 'Projects::GoogleCloud::DatabasesController', + action: 'error_create_cloudsql_instance', + label: nil, project: project, - user: authorized_member + user: user ) end + + context 'when CreateCloudsqlInstanceService is successful' do + before do + allow_next_instance_of(::GoogleCloud::CreateCloudsqlInstanceService) do |service| + allow(service).to receive(:execute) + .and_return({ status: :success, message: 'success' }) + end + end + + it 'redirects as expected' do + subject + + expect(response).to redirect_to(project_google_cloud_databases_path(project)) + + expect_snowplow_event( + category: 'Projects::GoogleCloud::DatabasesController', + action: 'create_cloudsql_instance', + label: "{}", + project: project, + user: user + ) + end + end end end end diff --git a/spec/requests/projects/google_cloud/deployments_controller_spec.rb b/spec/requests/projects/google_cloud/deployments_controller_spec.rb index 9e854e01516..ad6a3912e0b 100644 --- a/spec/requests/projects/google_cloud/deployments_controller_spec.rb +++ b/spec/requests/projects/google_cloud/deployments_controller_spec.rb @@ -29,10 +29,9 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do expect(response).to have_gitlab_http_status(:not_found) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::DeploymentsController', + action: 'error_invalid_user', + label: nil, project: project, user: nil ) @@ -48,10 +47,9 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do expect(response).to have_gitlab_http_status(:not_found) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::DeploymentsController', + action: 'error_invalid_user', + label: nil, project: project, user: nil ) @@ -75,6 +73,30 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do end end + describe 'Authorized GET project/-/google_cloud/deployments', :snowplow do + before do + sign_in(user_maintainer) + + allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client| + allow(client).to receive(:validate_token).and_return(true) + end + end + + it 'renders template' do + get "#{project_google_cloud_deployments_path(project)}" + + expect(response).to render_template(:index) + + expect_snowplow_event( + category: 'Projects::GoogleCloud::DeploymentsController', + action: 'render_page', + label: nil, + project: project, + user: user_maintainer + ) + end + end + describe 'Authorized GET project/-/google_cloud/deployments/cloud_run', :snowplow do let_it_be(:url) { "#{project_google_cloud_deployments_cloud_run_path(project)}" } @@ -92,11 +114,9 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do expect(response).to redirect_to(project_google_cloud_deployments_path(project)) # since GPC_PROJECT_ID is not set, enable cloud run service should return an error expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'deployments#cloud_run', - label: 'error_enable_cloud_run', - extra: { message: 'No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.', - status: :error }, + category: 'Projects::GoogleCloud::DeploymentsController', + action: 'error_enable_services', + label: nil, project: project, user: user_maintainer ) @@ -113,10 +133,9 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do expect(response).to redirect_to(project_google_cloud_deployments_path(project)) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'deployments#cloud_run', - label: 'error_gcp', - extra: mock_gcp_error, + category: 'Projects::GoogleCloud::DeploymentsController', + action: 'error_google_api', + label: nil, project: project, user: user_maintainer ) @@ -136,10 +155,9 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do expect(response).to redirect_to(project_google_cloud_deployments_path(project)) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'deployments#cloud_run', - label: 'error_generate_pipeline', - extra: { status: :error }, + category: 'Projects::GoogleCloud::DeploymentsController', + action: 'error_generate_cloudrun_pipeline', + label: nil, project: project, user: user_maintainer ) @@ -159,15 +177,9 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController do expect(response).to have_gitlab_http_status(:found) expect(response.location).to include(project_new_merge_request_path(project)) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'deployments#cloud_run', - label: 'success', - extra: { "title": "Enable deployments to Cloud Run", - "description": "This merge request includes a Cloud Run deployment job in the pipeline definition (.gitlab-ci.yml).\n\nThe `deploy-to-cloud-run` job:\n* Requires the following environment variables\n * `GCP_PROJECT_ID`\n * `GCP_SERVICE_ACCOUNT_KEY`\n* Job definition can be found at: https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library\n\nThis pipeline definition has been committed to the branch ``.\nYou may modify the pipeline definition further or accept the changes as-is if suitable.\n", - "source_project_id": project.id, - "target_project_id": project.id, - "source_branch": nil, - "target_branch": project.default_branch }, + category: 'Projects::GoogleCloud::DeploymentsController', + action: 'generate_cloudrun_pipeline', + label: nil, project: project, user: user_maintainer ) diff --git a/spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb b/spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb index f88273080d5..e77bcdb40b8 100644 --- a/spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb +++ b/spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb @@ -13,10 +13,9 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do it "tracks event" do is_expected.to be(404) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::GcpRegionsController', + action: 'error_invalid_user', + label: nil, project: project, user: nil ) @@ -27,10 +26,9 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do it "tracks event" do is_expected.to be(404) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::GcpRegionsController', + action: 'error_invalid_user', + label: nil, project: project, user: nil ) @@ -41,10 +39,9 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do it "tracks event" do is_expected.to be(404) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'feature_flag_enabled!', - label: 'error_access_denied', - property: 'feature_flag_not_enabled', + category: 'Projects::GoogleCloud::GcpRegionsController', + action: 'error_feature_flag_not_enabled', + label: nil, project: project, user: user_maintainer ) @@ -55,10 +52,9 @@ RSpec.describe Projects::GoogleCloud::GcpRegionsController do it "tracks event" do is_expected.to be(403) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'google_oauth2_enabled!', - label: 'error_access_denied', - extra: { reason: 'google_oauth2_not_configured', config: config }, + category: 'Projects::GoogleCloud::GcpRegionsController', + action: 'error_google_oauth2_not_enabled', + label: nil, project: project, user: user_maintainer ) diff --git a/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb index 36441a184cb..9bd8468767d 100644 --- a/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb +++ b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb @@ -50,10 +50,9 @@ RSpec.describe Projects::GoogleCloud::RevokeOauthController do expect(response).to redirect_to(project_google_cloud_configuration_path(project)) expect(flash[:notice]).to eq('Google OAuth2 token revocation requested') expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'revoke_oauth#create', - label: 'success', - property: '{}', + category: 'Projects::GoogleCloud::RevokeOauthController', + action: 'revoke_oauth', + label: nil, project: project, user: user ) @@ -73,10 +72,9 @@ RSpec.describe Projects::GoogleCloud::RevokeOauthController do expect(response).to redirect_to(project_google_cloud_configuration_path(project)) expect(flash[:alert]).to eq('Google OAuth2 token revocation request failed') expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'revoke_oauth#create', - label: 'error', - property: '{}', + category: 'Projects::GoogleCloud::RevokeOauthController', + action: 'error', + label: nil, project: project, user: user ) diff --git a/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb index ae2519855db..133c6f9153d 100644 --- a/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb +++ b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb @@ -30,10 +30,9 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do expect(response).to have_gitlab_http_status(:not_found) expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::ServiceAccountsController', + action: 'error_invalid_user', + label: nil, project: project, user: nil ) @@ -53,10 +52,9 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do get url expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::ServiceAccountsController', + action: 'error_invalid_user', + label: nil, project: project, user: unauthorized_member ) @@ -71,10 +69,9 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do post url expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'admin_project_google_cloud!', - label: 'error_access_denied', - property: 'invalid_user', + category: 'Projects::GoogleCloud::ServiceAccountsController', + action: 'error_invalid_user', + label: nil, project: project, user: unauthorized_member ) @@ -135,10 +132,9 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do expect(response).to redirect_to(project_google_cloud_configuration_path(project)) expect(flash[:warning]).to eq('No Google Cloud projects - You need at least one Google Cloud project') expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'service_accounts#index', - label: 'error_form', - property: 'no_gcp_projects', + category: 'Projects::GoogleCloud::ServiceAccountsController', + action: 'error_no_gcp_projects', + label: nil, project: project, user: authorized_member ) @@ -207,11 +203,10 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do expect(response).to redirect_to(project_google_cloud_configuration_path(project)) expect(flash[:warning]).to eq('Google Cloud Error - client-error') expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'service_accounts#index', - label: 'error_gcp', - extra: google_client_error, + category: 'Projects::GoogleCloud::ServiceAccountsController', + action: 'error_google_api', project: project, + label: nil, user: authorized_member ) end @@ -226,10 +221,9 @@ RSpec.describe Projects::GoogleCloud::ServiceAccountsController do expect(response).to redirect_to(project_google_cloud_configuration_path(project)) expect(flash[:warning]).to eq('Google Cloud Error - client-error') expect_snowplow_event( - category: 'Projects::GoogleCloud', - action: 'service_accounts#create', - label: 'error_gcp', - extra: google_client_error, + category: 'Projects::GoogleCloud::ServiceAccountsController', + action: 'error_google_api', + label: nil, project: project, user: authorized_member ) diff --git a/spec/requests/projects/hook_logs_controller_spec.rb b/spec/requests/projects/hook_logs_controller_spec.rb new file mode 100644 index 00000000000..8b3ec307e53 --- /dev/null +++ b/spec/requests/projects/hook_logs_controller_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::HookLogsController do + let_it_be(:user) { create(:user) } + let_it_be_with_refind(:web_hook) { create(:project_hook) } + let_it_be_with_refind(:web_hook_log) { create(:web_hook_log, web_hook: web_hook) } + + let(:project) { web_hook.project } + + it_behaves_like WebHooks::HookLogActions do + let(:edit_hook_path) { edit_project_hook_url(project, web_hook) } + + before do + project.add_owner(user) + end + end +end diff --git a/spec/requests/projects/merge_requests/context_commit_diffs_spec.rb b/spec/requests/projects/merge_requests/context_commit_diffs_spec.rb index 7be863aae75..c859e91e21a 100644 --- a/spec/requests/projects/merge_requests/context_commit_diffs_spec.rb +++ b/spec/requests/projects/merge_requests/context_commit_diffs_spec.rb @@ -42,7 +42,7 @@ RSpec.describe 'Merge Requests Context Commit Diffs' do } end - def go(extra_params = {}) + def go(headers: {}, **extra_params) params = { namespace_id: project.namespace.to_param, project_id: project, @@ -56,10 +56,20 @@ RSpec.describe 'Merge Requests Context Commit Diffs' do get diffs_batch_namespace_project_json_merge_request_path(params.merge(extra_params)), headers: headers end - context 'with caching', :use_clean_rails_memory_store_caching do - subject { go(page: 0, per_page: 5) } + context 'without caching' do + subject { go(headers: headers, page: 0, per_page: 5) } + + let(:headers) { {} } + let(:collection) { Gitlab::Diff::FileCollection::Compare } + let(:expected_options) { collection_arguments } + it_behaves_like 'serializes diffs with expected arguments' + end + + context 'with caching', :use_clean_rails_memory_store_caching do context 'when the request has not been cached' do + subject { go(headers: { 'If-None-Match' => '' }, page: 0, per_page: 5) } + it_behaves_like 'serializes diffs with expected arguments' do let(:collection) { Gitlab::Diff::FileCollection::Compare } let(:expected_options) { collection_arguments } @@ -67,16 +77,18 @@ RSpec.describe 'Merge Requests Context Commit Diffs' do end context 'when the request has already been cached' do + subject { go(headers: { 'If-None-Match' => response.etag }, page: 0, per_page: 5) } + before do go(page: 0, per_page: 5) end it 'does not serialize diffs' do - expect_next_instance_of(PaginatedDiffSerializer) do |instance| - expect(instance).not_to receive(:represent) - end + expect(PaginatedDiffSerializer).not_to receive(:new) + + go(headers: { 'If-None-Match' => response.etag }, page: 0, per_page: 5) - subject + expect(response).to have_gitlab_http_status(:not_modified) end context 'with the different user' do diff --git a/spec/requests/projects/merge_requests/diffs_spec.rb b/spec/requests/projects/merge_requests/diffs_spec.rb index 937b0f1d713..9f0b9a9cb1b 100644 --- a/spec/requests/projects/merge_requests/diffs_spec.rb +++ b/spec/requests/projects/merge_requests/diffs_spec.rb @@ -53,247 +53,154 @@ RSpec.describe 'Merge Requests Diffs' do get diffs_batch_namespace_project_json_merge_request_path(params.merge(extra_params)), headers: headers end - context 'with caching', :use_clean_rails_memory_store_caching do + context 'without caching' do subject { go(headers: headers, page: 0, per_page: 5) } let(:headers) { {} } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } - context 'when the request has not been cached' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } - - it_behaves_like 'serializes diffs with expected arguments' - end - - context 'when the request has already been cached' do - before do - go(page: 0, per_page: 5) - end - - it 'does not serialize diffs' do - expect_next_instance_of(PaginatedDiffSerializer) do |instance| - expect(instance).not_to receive(:represent) - end - - subject - end - - context 'when using ETags' do - context 'when etag_merge_request_diff_batches is true' do - let(:headers) { { 'If-None-Match' => response.etag } } - - it 'does not serialize diffs' do - expect(PaginatedDiffSerializer).not_to receive(:new) - - go(headers: headers, page: 0, per_page: 5) - - expect(response).to have_gitlab_http_status(:not_modified) - end - end - - context 'when etag_merge_request_diff_batches is false' do - let(:headers) { { 'If-None-Match' => response.etag } } + it_behaves_like 'serializes diffs with expected arguments' + end - before do - stub_feature_flags(etag_merge_request_diff_batches: false) - end + context 'with caching', :use_clean_rails_memory_store_caching do + subject { go(headers: headers, page: 0, per_page: 5) } - it 'does not serialize diffs' do - expect_next_instance_of(PaginatedDiffSerializer) do |instance| - expect(instance).not_to receive(:represent) - end + let(:headers) { { 'If-None-Match' => response.etag } } - subject + before do + go(page: 0, per_page: 5) + end - expect(response).to have_gitlab_http_status(:success) - end - end - end + it 'does not serialize diffs' do + expect(PaginatedDiffSerializer).not_to receive(:new) - context 'with the different user' do - let(:another_user) { create(:user) } - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } + go(headers: headers, page: 0, per_page: 5) - before do - project.add_maintainer(another_user) - sign_in(another_user) - end + expect(response).to have_gitlab_http_status(:not_modified) + end - it_behaves_like 'serializes diffs with expected arguments' + context 'with the different user' do + let(:another_user) { create(:user) } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end - end + before do + project.add_maintainer(another_user) + sign_in(another_user) end - context 'with a new unfoldable diff position' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } - - let(:unfoldable_position) do - create(:diff_position) - end - - before do - expect_next_instance_of(Gitlab::Diff::PositionCollection) do |instance| - expect(instance) - .to receive(:unfoldable) - .and_return([unfoldable_position]) - end - end + it_behaves_like 'serializes diffs with expected arguments' + end - it_behaves_like 'serializes diffs with expected arguments' + context 'with a new unfoldable diff position' do + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end - end + let(:unfoldable_position) do + create(:diff_position) end - context 'with disabled display_merge_conflicts_in_diff feature' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20).merge(allow_tree_conflicts: false) } - - before do - stub_feature_flags(display_merge_conflicts_in_diff: false) - end - - it_behaves_like 'serializes diffs with expected arguments' - - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end + before do + expect_next_instance_of(Gitlab::Diff::PositionCollection) do |instance| + expect(instance) + .to receive(:unfoldable) + .and_return([unfoldable_position]) end end - context 'with diff_head option' do - subject { go(page: 0, per_page: 5, diff_head: true) } - - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20).merge(merge_ref_head_diff: true) } - - before do - merge_request.create_merge_head_diff! - end + it_behaves_like 'serializes diffs with expected arguments' + end - it_behaves_like 'serializes diffs with expected arguments' + context 'with disabled display_merge_conflicts_in_diff feature' do + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20).merge(allow_tree_conflicts: false) } - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end - end + before do + stub_feature_flags(display_merge_conflicts_in_diff: false) end - context 'with the different pagination option' do - subject { go(page: 5, per_page: 5) } + it_behaves_like 'serializes diffs with expected arguments' + end - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } + context 'with diff_head option' do + subject { go(page: 0, per_page: 5, diff_head: true) } - it_behaves_like 'serializes diffs with expected arguments' + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20).merge(merge_ref_head_diff: true) } - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end - end + before do + merge_request.create_merge_head_diff! end - context 'with the different diff_view' do - subject { go(page: 0, per_page: 5, view: :parallel) } - - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20).merge(diff_view: :parallel) } - - it_behaves_like 'serializes diffs with expected arguments' + it_behaves_like 'serializes diffs with expected arguments' + end - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end - end - end + context 'with the different pagination option' do + subject { go(page: 5, per_page: 5) } - context 'with the different expanded option' do - subject { go(page: 0, per_page: 5, expanded: true ) } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } + it_behaves_like 'serializes diffs with expected arguments' + end - it_behaves_like 'serializes diffs with expected arguments' + context 'with the different diff_view' do + subject { go(page: 0, per_page: 5, view: :parallel) } - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end - end - end + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20).merge(diff_view: :parallel) } - context 'with the different ignore_whitespace_change option' do - subject { go(page: 0, per_page: 5, w: 1) } + it_behaves_like 'serializes diffs with expected arguments' + end - let(:collection) { Gitlab::Diff::FileCollection::Compare } - let(:expected_options) { collection_arguments(total_pages: 20) } + context 'with the different expanded option' do + subject { go(page: 0, per_page: 5, expanded: true ) } - it_behaves_like 'serializes diffs with expected arguments' + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } - context 'when using ETag caching' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:headers) { { 'If-None-Match' => response.etag } } - end - end - end + it_behaves_like 'serializes diffs with expected arguments' end - context 'when the paths is given' do - subject { go(headers: headers, page: 0, per_page: 5, paths: %w[README CHANGELOG]) } - - before do - go(page: 0, per_page: 5, paths: %w[README CHANGELOG]) - end + context 'with the different ignore_whitespace_change option' do + subject { go(page: 0, per_page: 5, w: 1) } - context 'when using ETag caching' do - let(:headers) { { 'If-None-Match' => response.etag } } + let(:collection) { Gitlab::Diff::FileCollection::Compare } + let(:expected_options) { collection_arguments(total_pages: 20) } - context 'when etag_merge_request_diff_batches is true' do - it 'does not serialize diffs' do - expect(PaginatedDiffSerializer).not_to receive(:new) + it_behaves_like 'serializes diffs with expected arguments' + end + end - subject + context 'when the paths is given' do + subject { go(headers: headers, page: 0, per_page: 5, paths: %w[README CHANGELOG]) } - expect(response).to have_gitlab_http_status(:not_modified) - end - end + before do + go(page: 0, per_page: 5, paths: %w[README CHANGELOG]) + end - context 'when etag_merge_request_diff_batches is false' do - before do - stub_feature_flags(etag_merge_request_diff_batches: false) - end + context 'when using ETag caching' do + let(:headers) { { 'If-None-Match' => response.etag } } - it 'does not use cache' do - expect(Rails.cache).not_to receive(:fetch).with(/cache:gitlab:PaginatedDiffSerializer/).and_call_original + it 'does not serialize diffs' do + expect(PaginatedDiffSerializer).not_to receive(:new) - subject + subject - expect(response).to have_gitlab_http_status(:success) - end - end + expect(response).to have_gitlab_http_status(:not_modified) end + end - context 'when not using ETag caching' do - it 'does not use cache' do - expect(Rails.cache).not_to receive(:fetch).with(/cache:gitlab:PaginatedDiffSerializer/).and_call_original + context 'when not using ETag caching' do + let(:headers) { {} } - subject + it 'does not use cache' do + expect(Rails.cache).not_to receive(:fetch).with(/cache:gitlab:PaginatedDiffSerializer/).and_call_original - expect(response).to have_gitlab_http_status(:success) - end + subject + + expect(response).to have_gitlab_http_status(:success) end end end diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb index 9503dafcf2a..305ca6147be 100644 --- a/spec/requests/projects/merge_requests_discussions_spec.rb +++ b/spec/requests/projects/merge_requests_discussions_spec.rb @@ -37,12 +37,10 @@ RSpec.describe 'merge requests discussions' do it 'avoids N+1 DB queries', :request_store do send_request # warm up - create(:diff_note_on_merge_request, noteable: merge_request, - project: merge_request.project) + create(:diff_note_on_merge_request, noteable: merge_request, project: merge_request.project) control = ActiveRecord::QueryRecorder.new { send_request } - create(:diff_note_on_merge_request, noteable: merge_request, - project: merge_request.project) + create(:diff_note_on_merge_request, noteable: merge_request, project: merge_request.project) expect do send_request @@ -51,8 +49,7 @@ RSpec.describe 'merge requests discussions' do it 'limits Gitaly queries', :request_store do Gitlab::GitalyClient.allow_n_plus_1_calls do - create_list(:diff_note_on_merge_request, 7, noteable: merge_request, - project: merge_request.project) + create_list(:diff_note_on_merge_request, 7, noteable: merge_request, project: merge_request.project) end # The creations above write into the Gitaly counts diff --git a/spec/requests/projects/packages/package_files_controller_spec.rb b/spec/requests/projects/packages/package_files_controller_spec.rb new file mode 100644 index 00000000000..a6daf57f0fa --- /dev/null +++ b/spec/requests/projects/packages/package_files_controller_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::Packages::PackageFilesController do + let_it_be(:project) { create(:project, :public) } + let_it_be(:package) { create(:package, project: project) } + let_it_be(:package_file) { create(:package_file, package: package) } + + let(:filename) { package_file.file_name } + + describe 'GET download' do + subject do + get download_namespace_project_package_file_url( + id: package_file.id, + namespace_id: project.namespace, + project_id: project + ) + end + + it 'sends the package file' do + subject + + expect(response.headers['Content-Disposition']) + .to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) + end + + it_behaves_like 'bumping the package last downloaded at field' + end +end diff --git a/spec/requests/projects/settings/integration_hook_logs_controller_spec.rb b/spec/requests/projects/settings/integration_hook_logs_controller_spec.rb new file mode 100644 index 00000000000..77daff901a1 --- /dev/null +++ b/spec/requests/projects/settings/integration_hook_logs_controller_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::Settings::IntegrationHookLogsController do + let_it_be(:user) { create(:user) } + let_it_be(:integration) { create(:datadog_integration) } + let_it_be_with_refind(:web_hook) { integration.service_hook } + let_it_be_with_refind(:web_hook_log) { create(:web_hook_log, web_hook: web_hook) } + + let(:project) { integration.project } + + it_behaves_like WebHooks::HookLogActions do + let(:edit_hook_path) { edit_project_settings_integration_url(project, integration) } + + before do + project.add_owner(user) + end + end +end |