diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-20 12:26:25 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-20 12:26:25 +0000 |
commit | a09983ae35713f5a2bbb100981116d31ce99826e (patch) | |
tree | 2ee2af7bd104d57086db360a7e6d8c9d5d43667a /spec/support/shared_examples/services | |
parent | 18c5ab32b738c0b6ecb4d0df3994000482f34bd8 (diff) | |
download | gitlab-ce-a09983ae35713f5a2bbb100981116d31ce99826e.tar.gz |
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'spec/support/shared_examples/services')
11 files changed, 409 insertions, 48 deletions
diff --git a/spec/support/shared_examples/services/alert_management_shared_examples.rb b/spec/support/shared_examples/services/alert_management_shared_examples.rb new file mode 100644 index 00000000000..a1354a8099b --- /dev/null +++ b/spec/support/shared_examples/services/alert_management_shared_examples.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'creates an alert management alert' do + it { is_expected.to be_success } + + it 'creates AlertManagement::Alert' do + expect { subject }.to change(AlertManagement::Alert, :count).by(1) + end + + it 'executes the alert service hooks' do + slack_service = create(:service, type: 'SlackService', project: project, alert_events: true, active: true) + + subject + + expect(ProjectServiceWorker).to have_received(:perform_async).with(slack_service.id, an_instance_of(Hash)) + end +end + +RSpec.shared_examples 'does not an create alert management alert' do + it 'does not create alert' do + expect { subject }.not_to change(AlertManagement::Alert, :count) + end +end + +RSpec.shared_examples 'adds an alert management alert event' do + it { is_expected.to be_success } + + it 'does not create an alert' do + expect { subject }.not_to change(AlertManagement::Alert, :count) + end + + it 'increases alert events count' do + expect { subject }.to change { alert.reload.events }.by(1) + end + + it 'does not executes the alert service hooks' do + expect(alert).not_to receive(:execute_services) + + subject + end +end diff --git a/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb b/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb new file mode 100644 index 00000000000..cbe20928f98 --- /dev/null +++ b/spec/support/shared_examples/services/clusters/parse_cluster_applications_artifact_shared_examples.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'parse cluster applications artifact' do |release_name| + let(:application_class) { Clusters::Cluster::APPLICATIONS[release_name] } + let(:cluster_application) { cluster.public_send("application_#{release_name}") } + let(:file) { fixture_file_upload(Rails.root.join(fixture)) } + let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } + + context 'release is missing' do + let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_missing.json.gz" } + + context 'application does not exist' do + it 'does not create or destroy an application' do + expect do + described_class.new(job, user).execute(artifact) + end.not_to change(application_class, :count) + end + end + + context 'application exists' do + before do + create("clusters_applications_#{release_name}".to_sym, :installed, cluster: cluster) + end + + it 'marks the application as uninstalled' do + described_class.new(job, user).execute(artifact) + + cluster_application.reload + expect(cluster_application).to be_uninstalled + end + end + end + + context 'release is deployed' do + let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_deployed.json.gz" } + + context 'application does not exist' do + it 'creates an application and marks it as installed' do + expect do + described_class.new(job, user).execute(artifact) + end.to change(application_class, :count) + + expect(cluster_application).to be_persisted + expect(cluster_application).to be_installed + end + end + + context 'application exists' do + before do + create("clusters_applications_#{release_name}".to_sym, :errored, cluster: cluster) + end + + it 'marks the application as installed' do + described_class.new(job, user).execute(artifact) + + expect(cluster_application).to be_installed + end + end + end + + context 'release is failed' do + let(:fixture) { "spec/fixtures/helm/helm_list_v2_#{release_name}_failed.json.gz" } + + context 'application does not exist' do + it 'creates an application and marks it as errored' do + expect do + described_class.new(job, user).execute(artifact) + end.to change(application_class, :count) + + expect(cluster_application).to be_persisted + expect(cluster_application).to be_errored + expect(cluster_application.status_reason).to eq('Helm release failed to install') + end + end + + context 'application exists' do + before do + create("clusters_applications_#{release_name}".to_sym, :installed, cluster: cluster) + end + + it 'marks the application as errored' do + described_class.new(job, user).execute(artifact) + + expect(cluster_application).to be_errored + expect(cluster_application.status_reason).to eq('Helm release failed to install') + end + end + end +end diff --git a/spec/support/shared_examples/services/common_system_notes_shared_examples.rb b/spec/support/shared_examples/services/common_system_notes_shared_examples.rb index 4ce3e32d774..20856b05de6 100644 --- a/spec/support/shared_examples/services/common_system_notes_shared_examples.rb +++ b/spec/support/shared_examples/services/common_system_notes_shared_examples.rb @@ -17,10 +17,10 @@ RSpec.shared_examples 'system note creation' do |update_params, note_text| end end -RSpec.shared_examples 'WIP notes creation' do |wip_action| +RSpec.shared_examples 'draft notes creation' do |wip_action| subject { described_class.new(project, user).execute(issuable, old_labels: []) } - it 'creates WIP toggle and title change notes' do + it 'creates Draft toggle and title change notes' do expect { subject }.to change { Note.count }.from(0).to(2) expect(Note.first.note).to match("#{wip_action} as a **Work In Progress**") diff --git a/spec/support/shared_examples/services/jira_import/start_import_service_shared_examples.rb b/spec/support/shared_examples/services/jira_import/start_import_service_shared_examples.rb index c5e56ed3539..8fd76f7cb1f 100644 --- a/spec/support/shared_examples/services/jira_import/start_import_service_shared_examples.rb +++ b/spec/support/shared_examples/services/jira_import/start_import_service_shared_examples.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -shared_examples 'responds with error' do |message| +RSpec.shared_examples 'responds with error' do |message| it 'returns error' do expect(subject).to be_a(ServiceResponse) expect(subject).to be_error diff --git a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb index 5dd1badbefc..c8fabfe30b9 100644 --- a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb +++ b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb @@ -29,14 +29,43 @@ RSpec.shared_examples 'valid dashboard service response' do end RSpec.shared_examples 'caches the unprocessed dashboard for subsequent calls' do - it do - expect(YAML).to receive(:safe_load).once.and_call_original + specify do + expect_next_instance_of(::Gitlab::Config::Loader::Yaml) do |loader| + expect(loader).to receive(:load_raw!).once.and_call_original + end described_class.new(*service_params).get_dashboard described_class.new(*service_params).get_dashboard end end +# This spec is applicable for predefined/out-of-the-box dashboard services. +RSpec.shared_examples 'refreshes cache when dashboard_version is changed' do + specify do + allow_next_instance_of(described_class) do |service| + allow(service).to receive(:dashboard_version).and_return('1', '2') + end + + expect(File).to receive(:read).twice.and_call_original + + service = described_class.new(*service_params) + + service.get_dashboard + service.get_dashboard + end +end + +# This spec is applicable for predefined/out-of-the-box dashboard services. +# This shared_example requires the following variables to be defined: +# dashboard_path: Relative path to the dashboard, ex: 'config/prometheus/common_metrics.yml' +# dashboard_version: The version string used in the cache_key. +RSpec.shared_examples 'dashboard_version contains SHA256 hash of dashboard file content' do + specify do + dashboard = File.read(Rails.root.join(dashboard_path)) + expect(Digest::SHA256.hexdigest(dashboard)).to eq(dashboard_version) + end +end + RSpec.shared_examples 'valid embedded dashboard service response' do let(:dashboard_schema) { Gitlab::Json.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) } @@ -128,3 +157,50 @@ RSpec.shared_examples 'updates gitlab_metrics_dashboard_processing_time_ms metri expect(metric.get(labels)).to be > 0 end end + +RSpec.shared_examples '#raw_dashboard raises error if dashboard loading fails' do + context 'when yaml is too large' do + before do + allow_next_instance_of(::Gitlab::Config::Loader::Yaml) do |loader| + allow(loader).to receive(:load_raw!) + .and_raise(Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big') + end + end + + it 'raises error' do + expect { subject.raw_dashboard }.to raise_error( + Gitlab::Metrics::Dashboard::Errors::LayoutError, + 'The parsed YAML is too big' + ) + end + end + + context 'when yaml loader returns error' do + before do + allow_next_instance_of(::Gitlab::Config::Loader::Yaml) do |loader| + allow(loader).to receive(:load_raw!) + .and_raise(Gitlab::Config::Loader::FormatError, 'Invalid configuration format') + end + end + + it 'raises error' do + expect { subject.raw_dashboard }.to raise_error( + Gitlab::Metrics::Dashboard::Errors::LayoutError, + 'Invalid yaml' + ) + end + end + + context 'when yaml is not a hash' do + before do + allow_next_instance_of(::Gitlab::Config::Loader::Yaml) do |loader| + allow(loader).to receive(:load_raw!) + .and_raise(Gitlab::Config::Loader::Yaml::NotHashError, 'Invalid configuration format') + end + end + + it 'returns nil' do + expect(subject.raw_dashboard).to eq({}) + end + end +end diff --git a/spec/support/shared_examples/services/packages_shared_examples.rb b/spec/support/shared_examples/services/packages_shared_examples.rb new file mode 100644 index 00000000000..45a4c2bb151 --- /dev/null +++ b/spec/support/shared_examples/services/packages_shared_examples.rb @@ -0,0 +1,193 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'assigns build to package' do + context 'with build info' do + let(:job) { create(:ci_build, user: user) } + let(:params) { super().merge(build: job) } + + it 'assigns the pipeline to the package' do + package = subject + + expect(package.build_info).to be_present + expect(package.build_info.pipeline).to eq job.pipeline + end + end +end + +RSpec.shared_examples 'returns packages' do |container_type, user_type| + context "for #{user_type}" do + before do + send(container_type)&.send("add_#{user_type}", user) unless user_type == :no_type + end + + it 'returns success response' do + subject + + expect(response).to have_gitlab_http_status(:success) + end + + it 'returns a valid response schema' do + subject + + expect(response).to match_response_schema(package_schema) + end + + it 'returns two packages' do + subject + + expect(json_response.length).to eq(2) + expect(json_response.map { |package| package['id'] }).to contain_exactly(package1.id, package2.id) + end + end +end + +RSpec.shared_examples 'returns packages with subgroups' do |container_type, user_type| + context "with subgroups for #{user_type}" do + before do + send(container_type)&.send("add_#{user_type}", user) unless user_type == :no_type + end + + it 'returns success response' do + subject + + expect(response).to have_gitlab_http_status(:success) + end + + it 'returns a valid response schema' do + subject + + expect(response).to match_response_schema(package_schema) + end + + it 'returns three packages' do + subject + + expect(json_response.length).to eq(3) + expect(json_response.map { |package| package['id'] }).to contain_exactly(package1.id, package2.id, package3.id) + end + end +end + +RSpec.shared_examples 'package sorting' do |order_by| + subject { get api(url), params: { sort: sort, order_by: order_by } } + + context "sorting by #{order_by}" do + context 'ascending order' do + let(:sort) { 'asc' } + + it 'returns the sorted packages' do + subject + + expect(json_response.map { |package| package['id'] }).to eq(packages.map(&:id)) + end + end + + context 'descending order' do + let(:sort) { 'desc' } + + it 'returns the sorted packages' do + subject + + expect(json_response.map { |package| package['id'] }).to eq(packages.reverse.map(&:id)) + end + end + end +end + +RSpec.shared_examples 'rejects packages access' do |container_type, user_type, status| + context "for #{user_type}" do + before do + send(container_type)&.send("add_#{user_type}", user) unless user_type == :no_type + end + + it_behaves_like 'returning response status', status + end +end + +RSpec.shared_examples 'returns paginated packages' do + let(:per_page) { 2 } + + context 'when viewing the first page' do + let(:page) { 1 } + + it 'returns first 2 packages' do + get api(url, user), params: { page: page, per_page: per_page } + + expect_paginated_array_response([package1.id, package2.id]) + end + end + + context 'when viewing the second page' do + let(:page) { 2 } + + it 'returns first 2 packages' do + get api(url, user), params: { page: page, per_page: per_page } + + expect_paginated_array_response([package3.id, package4.id]) + end + end +end + +RSpec.shared_examples 'background upload schedules a file migration' do + context 'background upload enabled' do + before do + stub_package_file_object_storage(background_upload: true) + end + + it 'schedules migration of file to object storage' do + expect(ObjectStorage::BackgroundMoveWorker).to receive(:perform_async).with('Packages::PackageFileUploader', 'Packages::PackageFile', :file, kind_of(Numeric)) + + subject + end + end +end + +RSpec.shared_context 'package filter context' do + def package_filter_url(filter, param) + "/projects/#{project.id}/packages?package_#{filter}=#{param}" + end + + def group_filter_url(filter, param) + "/groups/#{group.id}/packages?package_#{filter}=#{param}" + end +end + +RSpec.shared_examples 'filters on each package_type' do |is_project: false| + include_context 'package filter context' + + let_it_be(:package1) { create(:conan_package, project: project) } + let_it_be(:package2) { create(:maven_package, project: project) } + let_it_be(:package3) { create(:npm_package, project: project) } + let_it_be(:package4) { create(:nuget_package, project: project) } + let_it_be(:package5) { create(:pypi_package, project: project) } + let_it_be(:package6) { create(:composer_package, project: project) } + + Packages::Package.package_types.keys.each do |package_type| + context "for package type #{package_type}" do + let(:url) { is_project ? package_filter_url(:type, package_type) : group_filter_url(:type, package_type) } + + subject { get api(url, user) } + + it "returns #{package_type} packages" do + subject + + expect(json_response.length).to eq(1) + expect(json_response.map { |package| package['package_type'] }).to contain_exactly(package_type) + end + end + end +end + +RSpec.shared_examples 'package workhorse uploads' do + context 'without a workhorse header' do + let(:workhorse_token) { JWT.encode({ 'iss' => 'invalid header' }, Gitlab::Workhorse.secret, 'HS256') } + + it_behaves_like 'returning response status', :forbidden + + it 'logs an error' do + expect(Gitlab::ErrorTracking).to receive(:track_exception).once + + subject + end + end +end diff --git a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb index 0e6ecf49cd0..2ddbdebdb97 100644 --- a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb +++ b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb @@ -25,19 +25,18 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('test_second_storage').and_return(SecureRandom.uuid) - allow(project_repository_double).to receive(:create_repository) - .and_return(true) allow(project_repository_double).to receive(:replicate) .with(project.repository.raw) allow(project_repository_double).to receive(:checksum) .and_return(project_repository_checksum) - allow(repository_double).to receive(:create_repository) - .and_return(true) allow(repository_double).to receive(:replicate) .with(repository.raw) allow(repository_double).to receive(:checksum) .and_return(repository_checksum) + + expect(GitlabShellWorker).to receive(:perform_async).with(:mv_repository, 'default', anything, anything) + .twice.and_call_original end it "moves the project and its #{repository_type} repository to the new storage and unmarks the repository as read only" do @@ -48,6 +47,7 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| old_repository_path = repository.full_path result = subject.execute + project.reload expect(result).to be_success expect(project).not_to be_repository_read_only @@ -101,15 +101,11 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| it 'unmarks the repository as read-only without updating the repository storage' do allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('test_second_storage').and_return(SecureRandom.uuid) - allow(project_repository_double).to receive(:create_repository) - .and_return(true) allow(project_repository_double).to receive(:replicate) .with(project.repository.raw) allow(project_repository_double).to receive(:checksum) .and_return(project_repository_checksum) - allow(repository_double).to receive(:create_repository) - .and_return(true) allow(repository_double).to receive(:replicate) .with(repository.raw) .and_raise(Gitlab::Git::CommandError) @@ -128,15 +124,11 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| it 'unmarks the repository as read-only without updating the repository storage' do allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('test_second_storage').and_return(SecureRandom.uuid) - allow(project_repository_double).to receive(:create_repository) - .and_return(true) allow(project_repository_double).to receive(:replicate) .with(project.repository.raw) allow(project_repository_double).to receive(:checksum) .and_return(project_repository_checksum) - allow(repository_double).to receive(:create_repository) - .and_return(true) allow(repository_double).to receive(:replicate) .with(repository.raw) allow(repository_double).to receive(:checksum) diff --git a/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb b/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb index c5f84e205cf..ef41c2fcc13 100644 --- a/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb +++ b/spec/support/shared_examples/services/resource_events/change_milestone_service_shared_examples.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -shared_examples 'a milestone events creator' do +RSpec.shared_examples 'a milestone events creator' do let_it_be(:user) { create(:user) } let(:created_at_time) { Time.utc(2019, 12, 30) } diff --git a/spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb index efcb83a34af..ebe78c299a5 100644 --- a/spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb +++ b/spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb @@ -63,16 +63,6 @@ RSpec.shared_examples 'WikiPages::CreateService#execute' do |container_type| include_examples 'correct event created' end - context 'the feature is disabled' do - before do - stub_feature_flags(wiki_events: false) - end - - it 'does not record the activity' do - expect { service.execute }.not_to change(Event, :count) - end - end - context 'when the options are bad' do let(:page_title) { '' } diff --git a/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb index 1231c012c31..db1b50fdf3c 100644 --- a/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb +++ b/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb @@ -37,14 +37,4 @@ RSpec.shared_examples 'WikiPages::DestroyService#execute' do |container_type| expect { service.execute(nil) }.not_to change { counter.read(:delete) } end - - context 'the feature is disabled' do - before do - stub_feature_flags(wiki_events: false) - end - - it 'does not record the activity' do - expect { service.execute(page) }.not_to change(Event, :count) - end - end end diff --git a/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb index 77354fec069..0191a6dfbc9 100644 --- a/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb +++ b/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb @@ -67,16 +67,6 @@ RSpec.shared_examples 'WikiPages::UpdateService#execute' do |container_type| include_examples 'adds activity event' end - context 'the feature is disabled' do - before do - stub_feature_flags(wiki_events: false) - end - - it 'does not record the activity' do - expect { service.execute(page) }.not_to change(Event, :count) - end - end - context 'when the options are bad' do let(:page_title) { '' } |