diff options
Diffstat (limited to 'spec/lib')
51 files changed, 1008 insertions, 225 deletions
diff --git a/spec/lib/banzai/filter/autolink_filter_spec.rb b/spec/lib/banzai/filter/autolink_filter_spec.rb index a50329473ad..7a457403b51 100644 --- a/spec/lib/banzai/filter/autolink_filter_spec.rb +++ b/spec/lib/banzai/filter/autolink_filter_spec.rb @@ -76,7 +76,7 @@ describe Banzai::Filter::AutolinkFilter do expect(doc.at_css('a')['href']).to eq link end - it 'autolinks multiple occurences of smb' do + it 'autolinks multiple occurrences of smb' do link1 = 'smb:///Volumes/shared/foo.pdf' link2 = 'smb:///Volumes/shared/bar.pdf' diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb index 0d0554a2259..a0270d93d50 100644 --- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb @@ -101,15 +101,24 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do context "redmine project" do let(:project) { create(:redmine_project) } - let(:issue) { ExternalIssue.new("#123", project) } - let(:reference) { issue.to_reference } before do - project.issues_enabled = false - project.save! + project.update!(issues_enabled: false) + end + + context "with a hash prefix" do + let(:issue) { ExternalIssue.new("#123", project) } + let(:reference) { issue.to_reference } + + it_behaves_like "external issue tracker" end - it_behaves_like "external issue tracker" + context "with a single-letter prefix" do + let(:issue) { ExternalIssue.new("T-123", project) } + let(:reference) { issue.to_reference } + + it_behaves_like "external issue tracker" + end end context "jira project" do @@ -122,6 +131,15 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do it_behaves_like "external issue tracker" end + context "with a single-letter prefix" do + let(:issue) { ExternalIssue.new("J-123", project) } + + it "ignores reference" do + exp = act = "Issue #{reference}" + expect(filter(act).to_html).to eq exp + end + end + context "with wrong markdown" do let(:issue) { ExternalIssue.new("#123", project) } diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb index ed1ebe9ebf6..415ded05e6e 100644 --- a/spec/lib/banzai/filter/relative_link_filter_spec.rb +++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb @@ -226,7 +226,7 @@ describe Banzai::Filter::RelativeLinkFilter do let(:ref) {'mark#\'@],+;-._/#@!$&()+down'} it 'correctly escapes the ref' do - # Adressable won't escape the '#', so we do this manually + # Addressable won't escape the '#', so we do this manually ref_escaped = 'mark%23\'@%5D,+;-._/%23@!$&()+down' # Stub this method so the branch doesn't actually need to be in the repo diff --git a/spec/lib/bitbucket_server/client_spec.rb b/spec/lib/bitbucket_server/client_spec.rb index f926ae963a4..5de0a9a65b5 100644 --- a/spec/lib/bitbucket_server/client_spec.rb +++ b/spec/lib/bitbucket_server/client_spec.rb @@ -13,7 +13,7 @@ describe BitbucketServer::Client do let(:path) { "/projects/#{project}/repos/#{repo_slug}/pull-requests?state=ALL" } it 'requests a collection' do - expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :pull_request) + expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :pull_request, page_offset: 0, limit: nil) subject.pull_requests(project, repo_slug) end @@ -29,7 +29,7 @@ describe BitbucketServer::Client do let(:path) { "/projects/#{project}/repos/#{repo_slug}/pull-requests/1/activities" } it 'requests a collection' do - expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :activity) + expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :activity, page_offset: 0, limit: nil) subject.activities(project, repo_slug, 1) end @@ -52,10 +52,16 @@ describe BitbucketServer::Client do let(:path) { "/repos" } it 'requests a collection' do - expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :repo) + expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :repo, page_offset: 0, limit: nil) subject.repos end + + it 'requests a collection with an offset and limit' do + expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :repo, page_offset: 10, limit: 25) + + subject.repos(page_offset: 10, limit: 25) + end end describe '#create_branch' do diff --git a/spec/lib/bitbucket_server/collection_spec.rb b/spec/lib/bitbucket_server/collection_spec.rb new file mode 100644 index 00000000000..ddd02bac88a --- /dev/null +++ b/spec/lib/bitbucket_server/collection_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe BitbucketServer::Collection do + let(:connection) { instance_double(BitbucketServer::Connection) } + let(:page) { 1 } + let(:paginator) { BitbucketServer::Paginator.new(connection, 'http://more-data', :pull_request, page_offset: page) } + + subject { described_class.new(paginator) } + + describe '#current_page' do + it 'returns 1' do + expect(subject.current_page).to eq(1) + end + end + + describe '#prev_page' do + it 'returns nil' do + expect(subject.prev_page).to be_nil + end + end + + describe '#next_page' do + it 'returns 2' do + expect(subject.next_page).to eq(2) + end + end +end diff --git a/spec/lib/bitbucket_server/paginator_spec.rb b/spec/lib/bitbucket_server/paginator_spec.rb index 2de50eba3c4..d268d4f23cf 100644 --- a/spec/lib/bitbucket_server/paginator_spec.rb +++ b/spec/lib/bitbucket_server/paginator_spec.rb @@ -20,6 +20,16 @@ describe BitbucketServer::Paginator do expect { paginator.items }.to raise_error(StopIteration) end + it 'obeys limits' do + limited = described_class.new(connection, 'http://more-data', :pull_request, page_offset: 0, limit: 1) + allow(limited).to receive(:fetch_next_page).and_return(first_page) + + expect(limited.has_next_page?).to be_truthy + expect(limited.items).to match(['item_1']) + expect(limited.has_next_page?).to be_truthy + expect { limited.items }.to raise_error(StopIteration) + end + it 'calls the connection with different offsets' do expect(connection).to receive(:get).with('http://more-data', start: 0, limit: BitbucketServer::Paginator::PAGE_LENGTH).and_return(page_attrs) diff --git a/spec/lib/container_registry/blob_spec.rb b/spec/lib/container_registry/blob_spec.rb index c73faa55513..d3fff5bad42 100644 --- a/spec/lib/container_registry/blob_spec.rb +++ b/spec/lib/container_registry/blob_spec.rb @@ -64,7 +64,7 @@ describe ContainerRegistry::Blob do .to_return(status: 200) end - it 'returns true when blob has been successfuly deleted' do + it 'returns true when blob has been successfully deleted' do expect(blob.delete).to be_truthy end end diff --git a/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb b/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb index e1c4f9cfea7..5076996474f 100644 --- a/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb +++ b/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb @@ -118,7 +118,7 @@ describe Gitlab::BackgroundMigration::CreateForkNetworkMembershipsRange, :migrat expect(fork_network_members.count).to eq(12) end - it 'knows when not all memberships withing a batch have been created' do + it 'knows when not all memberships within a batch have been created' do expect(migration.missing_members?(8, 10)).to be_truthy end end diff --git a/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb b/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb new file mode 100644 index 00000000000..4f1b01eed41 --- /dev/null +++ b/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::BackgroundMigration::PopulateClusterKubernetesNamespaceTable, :migration, schema: 20181022173835 do + let(:migration) { described_class.new } + let(:clusters) { create_list(:cluster, 10, :project, :provided_by_gcp) } + + before do + clusters + end + + shared_examples 'consistent kubernetes namespace attributes' do + it 'should populate namespace and service account information' do + subject + + clusters_with_namespace.each do |cluster| + project = cluster.project + cluster_project = cluster.cluster_projects.first + namespace = "#{project.path}-#{project.id}" + kubernetes_namespace = cluster.reload.kubernetes_namespace + + expect(kubernetes_namespace).to be_present + expect(kubernetes_namespace.cluster_project).to eq(cluster_project) + expect(kubernetes_namespace.project).to eq(cluster_project.project) + expect(kubernetes_namespace.cluster).to eq(cluster_project.cluster) + expect(kubernetes_namespace.namespace).to eq(namespace) + expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account") + end + end + end + + subject { migration.perform } + + context 'when no Clusters::Project has a Clusters::KubernetesNamespace' do + let(:cluster_projects) { Clusters::Project.all } + + it 'should create a Clusters::KubernetesNamespace per Clusters::Project' do + expect do + subject + end.to change(Clusters::KubernetesNamespace, :count).by(cluster_projects.count) + end + + it_behaves_like 'consistent kubernetes namespace attributes' do + let(:clusters_with_namespace) { clusters } + end + end + + context 'when every Clusters::Project has Clusters::KubernetesNamespace' do + before do + clusters.each do |cluster| + create(:cluster_kubernetes_namespace, + cluster_project: cluster.cluster_projects.first, + cluster: cluster, + project: cluster.project) + end + end + + it 'should not create any Clusters::KubernetesNamespace' do + expect do + subject + end.not_to change(Clusters::KubernetesNamespace, :count) + end + end + + context 'when only some Clusters::Project have Clusters::KubernetesNamespace related' do + let(:with_kubernetes_namespace) { clusters.first(6) } + let(:with_no_kubernetes_namespace) { clusters.last(4) } + + before do + with_kubernetes_namespace.each do |cluster| + create(:cluster_kubernetes_namespace, + cluster_project: cluster.cluster_projects.first, + cluster: cluster, + project: cluster.project) + end + end + + it 'creates limited number of Clusters::KubernetesNamespace' do + expect do + subject + end.to change(Clusters::KubernetesNamespace, :count).by(with_no_kubernetes_namespace.count) + end + + it 'should not modify clusters with Clusters::KubernetesNamespace' do + subject + + with_kubernetes_namespace.each do |cluster| + expect(cluster.kubernetes_namespaces.count).to eq(1) + end + end + + it_behaves_like 'consistent kubernetes namespace attributes' do + let(:clusters_with_namespace) { with_no_kubernetes_namespace } + end + end +end diff --git a/spec/lib/gitlab/checks/lfs_integrity_spec.rb b/spec/lib/gitlab/checks/lfs_integrity_spec.rb index 0488720cec8..887ea8fc1e0 100644 --- a/spec/lib/gitlab/checks/lfs_integrity_spec.rb +++ b/spec/lib/gitlab/checks/lfs_integrity_spec.rb @@ -68,7 +68,7 @@ describe Gitlab::Checks::LfsIntegrity do expect(subject.objects_missing?).to be_truthy end - it 'is false parent project already conatins LFS objects for the fork' do + it 'is false parent project already contains LFS objects for the fork' do lfs_object = create(:lfs_object, oid: blob_object.lfs_oid) create(:lfs_objects_project, project: parent_project, lfs_object: lfs_object) diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb index 7549e9941b6..5a5c071c639 100644 --- a/spec/lib/gitlab/ci/ansi2html_spec.rb +++ b/spec/lib/gitlab/ci/ansi2html_spec.rb @@ -7,7 +7,7 @@ describe Gitlab::Ci::Ansi2html do expect(convert_html("Hello")).to eq('Hello') end - it "strips non-color-changing controll sequences" do + it "strips non-color-changing control sequences" do expect(convert_html("Hello \e[2Kworld")).to eq('Hello world') end diff --git a/spec/lib/gitlab/ci/build/policy/variables_spec.rb b/spec/lib/gitlab/ci/build/policy/variables_spec.rb index 854c4cb718c..c2c0742efc3 100644 --- a/spec/lib/gitlab/ci/build/policy/variables_spec.rb +++ b/spec/lib/gitlab/ci/build/policy/variables_spec.rb @@ -24,7 +24,7 @@ describe Gitlab::Ci::Build::Policy::Variables do expect(policy).to be_satisfied_by(pipeline, seed) end - it 'is not satisfied by an overriden empty variable' do + it 'is not satisfied by an overridden empty variable' do policy = described_class.new(['$CI_PROJECT_NAME']) expect(policy).not_to be_satisfied_by(pipeline, seed) diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index 1860ed79bfd..7c18514934e 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -219,7 +219,7 @@ describe Gitlab::Ci::Config::Entry::Global do ## # When nodes are specified but not defined, we assume that - # configuration is valid, and we asume that entry is simply undefined, + # configuration is valid, and we assume that entry is simply undefined, # despite the fact, that key is present. See issue #18775 for more # details. # diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index 1169938b80c..57d4577a90c 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -1,5 +1,4 @@ -require 'fast_spec_helper' -require_dependency 'active_model' +require 'spec_helper' describe Gitlab::Ci::Config::Entry::Job do let(:entry) { described_class.new(config, name: :rspec) } @@ -11,7 +10,7 @@ describe Gitlab::Ci::Config::Entry::Job do let(:result) do %i[before_script script stage type after_script cache image services only except variables artifacts - environment coverage] + environment coverage retry] end it { is_expected.to match_array result } @@ -99,41 +98,42 @@ describe Gitlab::Ci::Config::Entry::Job do end end - context 'when retry value is not correct' do + context 'when parallel value is not correct' do context 'when it is not a numeric value' do - let(:config) { { retry: true } } + let(:config) { { parallel: true } } it 'returns error about invalid type' do expect(entry).not_to be_valid - expect(entry.errors).to include 'job retry is not a number' + expect(entry.errors).to include 'job parallel is not a number' end end - context 'when it is lower than zero' do - let(:config) { { retry: -1 } } + context 'when it is lower than two' do + let(:config) { { parallel: 1 } } it 'returns error about value too low' do expect(entry).not_to be_valid expect(entry.errors) - .to include 'job retry must be greater than or equal to 0' + .to include 'job parallel must be greater than or equal to 2' end end - context 'when it is not an integer' do - let(:config) { { retry: 1.5 } } + context 'when it is bigger than 50' do + let(:config) { { parallel: 51 } } - it 'returns error about wrong value' do + it 'returns error about value too high' do expect(entry).not_to be_valid - expect(entry.errors).to include 'job retry must be an integer' + expect(entry.errors) + .to include 'job parallel must be less than or equal to 50' end end - context 'when the value is too high' do - let(:config) { { retry: 10 } } + context 'when it is not an integer' do + let(:config) { { parallel: 1.5 } } - it 'returns error about value too high' do + it 'returns error about wrong value' do expect(entry).not_to be_valid - expect(entry.errors).to include 'job retry must be less than or equal to 2' + expect(entry.errors).to include 'job parallel must be an integer' end end end diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb index 8095a231cf3..1140bfdf6c3 100644 --- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb @@ -33,7 +33,7 @@ describe Gitlab::Ci::Config::Entry::Reports do where(:keyword, :file) do :junit | 'junit.xml' - :codequality | 'codequality.json' + :codequality | 'gl-code-quality-report.json' :sast | 'gl-sast-report.json' :dependency_scanning | 'gl-dependency-scanning-report.json' :container_scanning | 'gl-container-scanning-report.json' diff --git a/spec/lib/gitlab/ci/config/entry/retry_spec.rb b/spec/lib/gitlab/ci/config/entry/retry_spec.rb new file mode 100644 index 00000000000..164a9ed4c3d --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/retry_spec.rb @@ -0,0 +1,236 @@ +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Retry do + let(:entry) { described_class.new(config) } + + shared_context 'when retry value is a numeric', :numeric do + let(:config) { max } + let(:max) {} + end + + shared_context 'when retry value is a hash', :hash do + let(:config) { { max: max, when: public_send(:when) }.compact } + let(:when) {} + let(:max) {} + end + + describe '#value' do + subject(:value) { entry.value } + + context 'when retry value is a numeric', :numeric do + let(:max) { 2 } + + it 'is returned as a hash with max key' do + expect(value).to eq(max: 2) + end + end + + context 'when retry value is a hash', :hash do + context 'and `when` is a string' do + let(:when) { 'unknown_failure' } + + it 'returns when wrapped in an array' do + expect(value).to eq(when: ['unknown_failure']) + end + end + + context 'and `when` is an array' do + let(:when) { %w[unknown_failure runner_system_failure] } + + it 'returns when as it was passed' do + expect(value).to eq(when: %w[unknown_failure runner_system_failure]) + end + end + end + end + + describe 'validation' do + context 'when retry value is correct' do + context 'when it is a numeric', :numeric do + let(:max) { 2 } + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'when it is a hash', :hash do + context 'with max' do + let(:max) { 2 } + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'with string when' do + let(:when) { 'unknown_failure' } + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'with string when always' do + let(:when) { 'always' } + + it 'is valid' do + expect(entry).to be_valid + end + end + + context 'with array when' do + let(:when) { %w[unknown_failure runner_system_failure] } + + it 'is valid' do + expect(entry).to be_valid + end + end + + # Those values are documented at `doc/ci/yaml/README.md`. If any of + # those values gets invalid, documentation must be updated. To make + # sure this is catched, check explicitly that all of the documented + # values are valid. If they are not it means the documentation and this + # array must be updated. + RETRY_WHEN_IN_DOCUMENTATION = %w[ + always + unknown_failure + script_failure + api_failure + stuck_or_timeout_failure + runner_system_failure + missing_dependency_failure + runner_unsupported + ].freeze + + RETRY_WHEN_IN_DOCUMENTATION.each do |reason| + context "with when from documentation `#{reason}`" do + let(:when) { reason } + + it 'is valid' do + expect(entry).to be_valid + end + end + end + + ::Ci::Build.failure_reasons.each_key do |reason| + context "with when from CommitStatus.failure_reasons `#{reason}`" do + let(:when) { reason } + + it 'is valid' do + expect(entry).to be_valid + end + end + end + end + end + + context 'when retry value is not correct' do + context 'when it is not a numeric nor an array' do + let(:config) { true } + + it 'returns error about invalid type' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry config has to be either an integer or a hash' + end + end + + context 'when it is a numeric', :numeric do + context 'when it is lower than zero' do + let(:max) { -1 } + + it 'returns error about value too low' do + expect(entry).not_to be_valid + expect(entry.errors) + .to include 'retry config must be greater than or equal to 0' + end + end + + context 'when it is not an integer' do + let(:max) { 1.5 } + + it 'returns error about wrong value' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry config has to be either an integer or a hash' + end + end + + context 'when the value is too high' do + let(:max) { 10 } + + it 'returns error about value too high' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry config must be less than or equal to 2' + end + end + end + + context 'when it is a hash', :hash do + context 'with unknown keys' do + let(:config) { { max: 2, unknown_key: :something, one_more: :key } } + + it 'returns error about the unknown key' do + expect(entry).not_to be_valid + expect(entry.errors) + .to include 'retry config contains unknown keys: unknown_key, one_more' + end + end + + context 'with max lower than zero' do + let(:max) { -1 } + + it 'returns error about value too low' do + expect(entry).not_to be_valid + expect(entry.errors) + .to include 'retry max must be greater than or equal to 0' + end + end + + context 'with max not an integer' do + let(:max) { 1.5 } + + it 'returns error about wrong value' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry max must be an integer' + end + end + + context 'iwth max too high' do + let(:max) { 10 } + + it 'returns error about value too high' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry max must be less than or equal to 2' + end + end + + context 'with when in wrong format' do + let(:when) { true } + + it 'returns error about the wrong format' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry when should be an array of strings or a string' + end + end + + context 'with an unknown when string' do + let(:when) { 'unknown_reason' } + + it 'returns error about the wrong format' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry when is not included in the list' + end + end + + context 'with an unknown failure reason in a when array' do + let(:when) { %w[unknown_reason runner_system_failure] } + + it 'returns error about the wrong format' do + expect(entry).not_to be_valid + expect(entry.errors).to include 'retry when contains unknown values: unknown_reason' + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/normalizer_spec.rb b/spec/lib/gitlab/ci/config/normalizer_spec.rb new file mode 100644 index 00000000000..97926695b6e --- /dev/null +++ b/spec/lib/gitlab/ci/config/normalizer_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +describe Gitlab::Ci::Config::Normalizer do + let(:job_name) { :rspec } + let(:job_config) { { script: 'rspec', parallel: 5, name: 'rspec' } } + let(:config) { { job_name => job_config } } + + describe '.normalize_jobs' do + subject { described_class.new(config).normalize_jobs } + + it 'does not have original job' do + is_expected.not_to include(job_name) + end + + it 'has parallelized jobs' do + job_names = [:"rspec 1/5", :"rspec 2/5", :"rspec 3/5", :"rspec 4/5", :"rspec 5/5"] + + is_expected.to include(*job_names) + end + + it 'sets job instance in options' do + expect(subject.values).to all(include(:instance)) + end + + it 'parallelizes jobs with original config' do + original_config = config[job_name].except(:name) + configs = subject.values.map { |config| config.except(:name, :instance) } + + expect(configs).to all(eq(original_config)) + end + + context 'when the job is not parallelized' do + let(:job_config) { { script: 'rspec', name: 'rspec' } } + + it 'returns the same hash' do + is_expected.to eq(config) + end + end + + context 'when there is a job with a slash in it' do + let(:job_name) { :"rspec 35/2" } + + it 'properly parallelizes job names' do + job_names = [:"rspec 35/2 1/5", :"rspec 35/2 2/5", :"rspec 35/2 3/5", :"rspec 35/2 4/5", :"rspec 35/2 5/5"] + + is_expected.to include(*job_names) + end + end + + context 'when jobs depend on parallelized jobs' do + let(:config) { { job_name => job_config, other_job: { script: 'echo 1', dependencies: [job_name.to_s] } } } + + it 'parallelizes dependencies' do + job_names = ["rspec 1/5", "rspec 2/5", "rspec 3/5", "rspec 4/5", "rspec 5/5"] + + expect(subject[:other_job][:dependencies]).to include(*job_names) + end + + it 'does not include original job name in dependencies' do + expect(subject[:other_job][:dependencies]).not_to include(job_name) + end + end + end +end diff --git a/spec/lib/gitlab/ci/status/build/scheduled_spec.rb b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb index 4a52b3ab8de..68b87fea75d 100644 --- a/spec/lib/gitlab/ci/status/build/scheduled_spec.rb +++ b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb @@ -13,24 +13,10 @@ describe Gitlab::Ci::Status::Build::Scheduled do end describe '#status_tooltip' do - context 'when scheduled_at is not expired' do - let(:build) { create(:ci_build, scheduled_at: 1.minute.since, project: project) } - - it 'shows execute_in of the scheduled job' do - Timecop.freeze(Time.now.change(usec: 0)) do - expect(subject.status_tooltip).to include('00:01:00') - end - end - end - - context 'when scheduled_at is expired' do - let(:build) { create(:ci_build, :expired_scheduled, project: project) } + let(:build) { create(:ci_build, scheduled_at: 1.minute.since, project: project) } - it 'shows 00:00' do - Timecop.freeze do - expect(subject.status_tooltip).to include('00:00') - end - end + it 'has a placeholder for the remaining time' do + expect(subject.status_tooltip).to include('%{remainingTime}') end end diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index 85b23edce9f..441e8214181 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -53,11 +53,11 @@ module Gitlab describe 'retry entry' do context 'when retry count is specified' do let(:config) do - YAML.dump(rspec: { script: 'rspec', retry: 1 }) + YAML.dump(rspec: { script: 'rspec', retry: { max: 1 } }) end it 'includes retry count in build options attribute' do - expect(subject[:options]).to include(retry: 1) + expect(subject[:options]).to include(retry: { max: 1 }) end end @@ -645,6 +645,33 @@ module Gitlab end end + describe 'Parallel' do + context 'when job is parallelized' do + let(:parallel) { 5 } + + let(:config) do + YAML.dump(rspec: { script: 'rspec', + parallel: parallel }) + end + + it 'returns parallelized jobs' do + config_processor = Gitlab::Ci::YamlProcessor.new(config) + builds = config_processor.stage_builds_attributes('test') + build_options = builds.map { |build| build[:options] } + + expect(builds.size).to eq(5) + expect(build_options).to all(include(:instance, parallel: parallel)) + end + + it 'does not have the original job' do + config_processor = Gitlab::Ci::YamlProcessor.new(config) + builds = config_processor.stage_builds_attributes('test') + + expect(builds).not_to include(:rspec) + end + end + end + describe 'cache' do context 'when cache definition has unknown keys' do it 'raises relevant validation error' do diff --git a/spec/lib/gitlab/cross_project_access/check_info_spec.rb b/spec/lib/gitlab/cross_project_access/check_info_spec.rb index bc9dbf2bece..239fa364f5e 100644 --- a/spec/lib/gitlab/cross_project_access/check_info_spec.rb +++ b/spec/lib/gitlab/cross_project_access/check_info_spec.rb @@ -50,7 +50,7 @@ describe Gitlab::CrossProjectAccess::CheckInfo do expect(info.should_run?(dummy_controller)).to be_truthy end - it 'returns the the oposite of #should_skip? when the check is a skip' do + it 'returns the the opposite of #should_skip? when the check is a skip' do info = described_class.new({}, nil, nil, true) expect(info).to receive(:should_skip?).with(dummy_controller).and_return(false) @@ -101,7 +101,7 @@ describe Gitlab::CrossProjectAccess::CheckInfo do expect(info.should_skip?(dummy_controller)).to be_truthy end - it 'returns the the oposite of #should_run? when the check is not a skip' do + it 'returns the the opposite of #should_run? when the check is not a skip' do info = described_class.new({}, nil, nil, false) expect(info).to receive(:should_run?).with(dummy_controller).and_return(false) diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb index 2e67c1c7f78..f8009709ce2 100644 --- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb @@ -44,15 +44,15 @@ describe Gitlab::CycleAnalytics::StageSummary do describe "#deploys" do it "finds the number of deploys made created after the 'from date'" do - Timecop.freeze(5.days.ago) { create(:deployment, project: project) } - Timecop.freeze(5.days.from_now) { create(:deployment, project: project) } + Timecop.freeze(5.days.ago) { create(:deployment, :success, project: project) } + Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project) } expect(subject.third[:value]).to eq(1) end it "doesn't find commits from other projects" do Timecop.freeze(5.days.from_now) do - create(:deployment, project: create(:project, :repository)) + create(:deployment, :success, project: create(:project, :repository)) end expect(subject.third[:value]).to eq(0) diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb index cc7cb3f23fd..248cca25a2c 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb @@ -20,7 +20,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete end describe "#remove_last_ocurrence" do - it "removes only the last occurance of a string" do + it "removes only the last occurrence of a string" do input = "this/is/a-word-to-replace/namespace/with/a-word-to-replace" expect(subject.remove_last_occurrence(input, "a-word-to-replace")) diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb index 2d94356f386..cc4faf6f10b 100644 --- a/spec/lib/gitlab/diff/position_spec.rb +++ b/spec/lib/gitlab/diff/position_spec.rb @@ -566,13 +566,13 @@ describe Gitlab::Diff::Position do end end - context "for text positon" do + context "for text position" do let(:args) { args_for_text } it_behaves_like "diff position json" end - context "for image positon" do + context "for image position" do let(:args) { args_for_img } it_behaves_like "diff position json" @@ -592,13 +592,13 @@ describe Gitlab::Diff::Position do end end - context "for text positon" do + context "for text position" do let(:args) { args_for_text } it_behaves_like "diff position json" end - context "for image positon" do + context "for image position" do let(:args) { args_for_img } it_behaves_like "diff position json" diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb index ddc4f6c5b5c..a2eed07ca55 100644 --- a/spec/lib/gitlab/diff/position_tracer_spec.rb +++ b/spec/lib/gitlab/diff/position_tracer_spec.rb @@ -43,7 +43,7 @@ describe Gitlab::Diff::PositionTracer do # # In any case, all of this means that the tests below will be extremely # (excessively, unjustifiably) thorough for scenarios where "the file was - # created in the old diff" and then drop off to comparitively lackluster + # created in the old diff" and then drop off to comparatively lackluster # testing of other scenarios. # # I did still try to cover most of the obvious and potentially tricky diff --git a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb index ace3104f36f..f276f1a8ddf 100644 --- a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb @@ -93,5 +93,74 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do end end end + + context 'when the email contains patch attachments' do + let(:email_raw) { fixture_file("emails/valid_merge_request_with_patch.eml") } + + it 'creates the source branch and applies the patches' do + receiver.execute + + branch = project.repository.find_branch('new-branch-with-a-patch') + + expect(branch).not_to be_nil + expect(branch.dereferenced_target.message).to include('A commit from a patch') + end + + it 'creates the merge request' do + expect { receiver.execute } + .to change { project.merge_requests.where(source_branch: 'new-branch-with-a-patch').size }.by(1) + end + + it 'does not mention the patches in the created merge request' do + receiver.execute + + merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch') + + expect(merge_request.description).not_to include('0001-A-commit-from-a-patch.patch') + end + + context 'when the patch could not be applied' do + let(:email_raw) { fixture_file("emails/merge_request_with_conflicting_patch.eml") } + + it 'raises an error' do + expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidAttachment) + end + end + + context 'when specifying the target branch using quick actions' do + let(:email_raw) { fixture_file('emails/merge_request_with_patch_and_target_branch.eml') } + + it 'creates the merge request with the correct target branch' do + receiver.execute + + merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch') + + expect(merge_request.target_branch).to eq('with-codeowners') + end + + it 'based the merge request of the target_branch' do + receiver.execute + + merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch') + + expect(merge_request.diff_base_commit).to eq(project.repository.commit('with-codeowners')) + end + end + end + end + + describe '#patch_attachments' do + let(:email_raw) { fixture_file('emails/merge_request_multiple_patches.eml') } + let(:mail) { Mail::Message.new(email_raw) } + subject(:handler) { described_class.new(mail, mail_key) } + + it 'orders attachments ending in `.patch` by name' do + expected_filenames = ["0001-A-commit-from-a-patch.patch", + "0002-This-does-not-apply-to-the-feature-branch.patch"] + + attachments = handler.__send__(:patch_attachments).map(&:filename) + + expect(attachments).to eq(expected_filenames) + end end end diff --git a/spec/lib/gitlab/file_detector_spec.rb b/spec/lib/gitlab/file_detector_spec.rb index 294ec2c2fd6..edab53247e9 100644 --- a/spec/lib/gitlab/file_detector_spec.rb +++ b/spec/lib/gitlab/file_detector_spec.rb @@ -15,7 +15,12 @@ describe Gitlab::FileDetector do describe '.type_of' do it 'returns the type of a README file' do - expect(described_class.type_of('README.md')).to eq(:readme) + %w[README readme INDEX index].each do |filename| + expect(described_class.type_of(filename)).to eq(:readme) + %w[.md .adoc .rst].each do |extname| + expect(described_class.type_of(filename + extname)).to eq(:readme) + end + end end it 'returns nil for a README file in a directory' do diff --git a/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb index ca067a29174..134bd5657e7 100644 --- a/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb +++ b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb @@ -17,7 +17,7 @@ describe Gitlab::Git::AttributesAtRefParser, :seed_helper do end it 'handles missing blobs' do - expect { described_class.new(repository, 'non-existant-branch') }.not_to raise_error + expect { described_class.new(repository, 'non-existent-branch') }.not_to raise_error end describe '#attributes' do diff --git a/spec/lib/gitlab/git/patches/collection_spec.rb b/spec/lib/gitlab/git/patches/collection_spec.rb new file mode 100644 index 00000000000..080be141c59 --- /dev/null +++ b/spec/lib/gitlab/git/patches/collection_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::Git::Patches::Collection do + let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') } + let(:patch_content1) do + File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch")) + end + let(:patch_content2) do + File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch")) + end + + subject(:collection) { described_class.new([patch_content1, patch_content2]) } + + describe '#size' do + it 'combines the size of the patches' do + expect(collection.size).to eq(549.bytes + 424.bytes) + end + end + + describe '#valid_size?' do + it 'is not valid if the total size is bigger than 2MB' do + expect(collection).to receive(:size).and_return(2500.kilobytes) + + expect(collection).not_to be_valid_size + end + end +end diff --git a/spec/lib/gitlab/git/patches/commit_patches_spec.rb b/spec/lib/gitlab/git/patches/commit_patches_spec.rb new file mode 100644 index 00000000000..760112155ce --- /dev/null +++ b/spec/lib/gitlab/git/patches/commit_patches_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::Git::Patches::CommitPatches do + describe '#commit' do + let(:patches) do + patches_folder = Rails.root.join('spec/fixtures/patchfiles') + content_1 = File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch")) + content_2 = File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch")) + + Gitlab::Git::Patches::Collection.new([content_1, content_2]) + end + let(:user) { build(:user) } + let(:branch_name) { 'branch-with-patches' } + let(:repository) { create(:project, :repository).repository } + + subject(:commit_patches) do + described_class.new(user, repository, branch_name, patches) + end + + it 'applies the patches' do + new_rev = commit_patches.commit + + expect(repository.commit(new_rev)).not_to be_nil + end + + it 'updates the branch cache' do + expect(repository).to receive(:after_create_branch) + + commit_patches.commit + end + + context 'when the repository does not exist' do + let(:repository) { create(:project).repository } + + it 'raises the correct error' do + expect { commit_patches.commit }.to raise_error(Gitlab::Git::Repository::NoRepository) + end + end + + context 'when the patch does not apply' do + let(:branch_name) { 'feature' } + + it 'raises the correct error' do + expect { commit_patches.commit }.to raise_error(Gitlab::Git::CommandError) + end + end + end +end diff --git a/spec/lib/gitlab/git/patches/patch_spec.rb b/spec/lib/gitlab/git/patches/patch_spec.rb new file mode 100644 index 00000000000..7466e853b65 --- /dev/null +++ b/spec/lib/gitlab/git/patches/patch_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::Git::Patches::Patch do + let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') } + let(:patch_content) do + File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch")) + end + let(:patch) { described_class.new(patch_content) } + + describe '#size' do + it 'is correct' do + expect(patch.size).to eq(549.bytes) + end + end +end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 9a443fa7f20..54291e847d8 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -476,6 +476,27 @@ describe Gitlab::Git::Repository, :seed_helper do end end + describe '#fetch_remote' do + it 'delegates to the gitaly RepositoryService' do + ssh_auth = double(:ssh_auth) + expected_opts = { + ssh_auth: ssh_auth, + forced: true, + no_tags: true, + timeout: described_class::GITLAB_PROJECTS_TIMEOUT, + prune: false + } + + expect(repository.gitaly_repository_client).to receive(:fetch_remote).with('remote-name', expected_opts) + + repository.fetch_remote('remote-name', ssh_auth: ssh_auth, forced: true, no_tags: true, prune: false) + end + + it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RepositoryService, :fetch_remote do + subject { repository.fetch_remote('remote-name') } + end + end + describe '#find_remote_root_ref' do it 'gets the remote root ref from GitalyClient' do expect_any_instance_of(Gitlab::GitalyClient::RemoteService) diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb index eaf64e3c9b4..b37fe2686b6 100644 --- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb @@ -335,4 +335,37 @@ describe Gitlab::GitalyClient::OperationService do end end end + + describe '#user_commit_patches' do + let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') } + let(:patch_content) do + patch_names.map { |name| File.read(File.join(patches_folder, name)) }.join("\n") + end + let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) } + let(:branch_name) { 'branch-with-patches' } + + subject(:commit_patches) do + client.user_commit_patches(user, branch_name, patch_content) + end + + it 'applies the patch correctly' do + branch_update = commit_patches + + expect(branch_update).to be_branch_created + + commit = repository.commit(branch_update.newrev) + expect(commit.author_email).to eq('patchuser@gitlab.org') + expect(commit.committer_email).to eq(user.email) + expect(commit.message.chomp).to eq('This does not apply to the `feature` branch') + end + + context 'when the patch could not be applied' do + let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) } + let(:branch_name) { 'feature' } + + it 'raises the correct error' do + expect { commit_patches }.to raise_error(GRPC::FailedPrecondition) + end + end + end end diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb index 1547d447197..d605fcbafee 100644 --- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe Gitlab::GitalyClient::RepositoryService do + using RSpec::Parameterized::TableSyntax + let(:project) { create(:project) } let(:storage_name) { project.repository_storage } let(:relative_path) { project.disk_path + '.git' } @@ -107,16 +109,67 @@ describe Gitlab::GitalyClient::RepositoryService do end describe '#fetch_remote' do - let(:ssh_auth) { double(:ssh_auth, ssh_import?: true, ssh_key_auth?: false, ssh_known_hosts: nil) } - let(:import_url) { 'ssh://example.com' } + let(:remote) { 'remote-name' } it 'sends a fetch_remote_request message' do + expected_request = gitaly_request_with_params( + remote: remote, + ssh_key: '', + known_hosts: '', + force: false, + no_tags: false, + no_prune: false + ) + expect_any_instance_of(Gitaly::RepositoryService::Stub) .to receive(:fetch_remote) - .with(gitaly_request_with_params(no_prune: false), kind_of(Hash)) + .with(expected_request, kind_of(Hash)) .and_return(double(value: true)) - client.fetch_remote(import_url, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 60) + client.fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, timeout: 1) + end + + context 'SSH auth' do + where(:ssh_import, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do + false | false | 'key' | 'known_hosts' | {} + false | true | 'key' | 'known_hosts' | {} + true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' } + true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' } + true | true | 'key' | nil | { ssh_key: 'key' } + true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' } + true | true | nil | nil | {} + true | true | '' | '' | {} + end + + with_them do + let(:ssh_auth) do + double( + :ssh_auth, + ssh_import?: ssh_import, + ssh_key_auth?: ssh_key_auth, + ssh_private_key: ssh_private_key, + ssh_known_hosts: ssh_known_hosts + ) + end + + it do + expected_request = gitaly_request_with_params({ + remote: remote, + ssh_key: '', + known_hosts: '', + force: false, + no_tags: false, + no_prune: false + }.update(expected_params)) + + expect_any_instance_of(Gitaly::RepositoryService::Stub) + .to receive(:fetch_remote) + .with(expected_request, kind_of(Hash)) + .and_return(double(value: true)) + + client.fetch_remote(remote, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1) + end + end end end diff --git a/spec/lib/gitlab/gpg_spec.rb b/spec/lib/gitlab/gpg_spec.rb index 47f37cae98f..39d09c49989 100644 --- a/spec/lib/gitlab/gpg_spec.rb +++ b/spec/lib/gitlab/gpg_spec.rb @@ -96,7 +96,7 @@ describe Gitlab::Gpg do expect(described_class.current_home_dir).to eq default_home_dir end - it 'returns the explicitely set home dir' do + it 'returns the explicitly set home dir' do GPGME::Engine.home_dir = '/tmp/gpg' expect(described_class.current_home_dir).to eq '/tmp/gpg' @@ -104,7 +104,7 @@ describe Gitlab::Gpg do GPGME::Engine.home_dir = GPGME::Engine.dirinfo('homedir') end - it 'returns the default value when explicitely setting the home dir to nil' do + it 'returns the default value when explicitly setting the home dir to nil' do GPGME::Engine.home_dir = nil expect(described_class.current_home_dir).to eq default_home_dir diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index a63f34b5536..f4efa450cca 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -299,6 +299,7 @@ project: - ci_cd_settings - import_export_upload - repository_languages +- pool_repository award_emoji: - awardable - user diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb index 65f073b2df3..87ab81d8169 100644 --- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb +++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb @@ -23,15 +23,23 @@ describe 'Import/Export attribute configuration' do let(:safe_attributes_file) { 'spec/lib/gitlab/import_export/safe_model_attributes.yml' } let(:safe_model_attributes) { YAML.load_file(safe_attributes_file) } + let(:ee_safe_attributes_file) { 'ee/spec/lib/gitlab/import_export/safe_model_attributes.yml' } + let(:ee_safe_model_attributes) { File.exist?(ee_safe_attributes_file) ? YAML.load_file(ee_safe_attributes_file) : {} } + it 'has no new columns' do relation_names.each do |relation_name| relation_class = relation_class_for_name(relation_name) relation_attributes = relation_class.new.attributes.keys - expect(safe_model_attributes[relation_class.to_s]).not_to be_nil, "Expected exported class #{relation_class} to exist in safe_model_attributes" - current_attributes = parsed_attributes(relation_name, relation_attributes) - safe_attributes = safe_model_attributes[relation_class.to_s] + safe_attributes = safe_model_attributes[relation_class.to_s].dup || [] + + ee_safe_model_attributes[relation_class.to_s].to_a.each do |attribute| + safe_attributes << attribute + end + + expect(safe_attributes).not_to be_nil, "Expected exported class #{relation_class} to exist in safe_model_attributes" + new_attributes = current_attributes - safe_attributes expect(new_attributes).to be_empty, failure_message(relation_class.to_s, new_attributes) @@ -43,6 +51,7 @@ describe 'Import/Export attribute configuration' do It looks like #{relation_class}, which is exported using the project Import/Export, has new attributes: #{new_attributes.join(',')} Please add the attribute(s) to SAFE_MODEL_ATTRIBUTES if you consider this can be exported. + #{"If the model/associations are EE-specific, use `#{File.expand_path(ee_safe_attributes_file)}`.\n" if ee_safe_model_attributes.any?} Otherwise, please blacklist the attribute(s) in IMPORT_EXPORT_CONFIG by adding it to its correspondent model in the +excluded_attributes+ section. diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index b0570680d5a..365bfae0d88 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -321,7 +321,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end end - context 'when the project has overriden params in import data' do + context 'when the project has overridden params in import data' do it 'overwrites the params stored in the JSON' do project.create_import_data(data: { override_params: { description: "Overridden" } }) diff --git a/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb index 72dc1817936..4a3b9d4bf6a 100644 --- a/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb @@ -8,7 +8,7 @@ describe Gitlab::Kubernetes::Helm::InitCommand do let(:commands) do <<~EOS - helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem >/dev/null + helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem EOS end @@ -22,7 +22,7 @@ describe Gitlab::Kubernetes::Helm::InitCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem --service-account tiller >/dev/null + helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem --service-account tiller EOS end end diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb index f28941ce58f..2b7e3ea6def 100644 --- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb @@ -5,6 +5,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do let(:repository) { 'https://repository.example.com' } let(:rbac) { false } let(:version) { '1.2.3' } + let(:preinstall) { nil } + let(:postinstall) { nil } let(:install_command) do described_class.new( @@ -13,7 +15,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do rbac: rbac, files: files, version: version, - repository: repository + repository: repository, + preinstall: preinstall, + postinstall: postinstall ) end @@ -22,8 +26,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null + helm init --client-only helm repo add app-name https://repository.example.com + helm repo update #{helm_install_comand} EOS end @@ -38,7 +43,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --namespace gitlab-managed-apps - -f /data/helm/app-name/config/values.yaml >/dev/null + -f /data/helm/app-name/config/values.yaml EOS end end @@ -49,8 +54,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null + helm init --client-only helm repo add app-name https://repository.example.com + helm repo update #{helm_install_command} EOS end @@ -66,7 +72,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do --version 1.2.3 --set rbac.create\\=true,rbac.enabled\\=true --namespace gitlab-managed-apps - -f /data/helm/app-name/config/values.yaml >/dev/null + -f /data/helm/app-name/config/values.yaml EOS end end @@ -78,7 +84,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null + helm init --client-only #{helm_install_command} EOS end @@ -93,7 +99,53 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --namespace gitlab-managed-apps - -f /data/helm/app-name/config/values.yaml >/dev/null + -f /data/helm/app-name/config/values.yaml + EOS + end + end + end + + context 'when there is a pre-install script' do + let(:preinstall) { ['/bin/date', '/bin/true'] } + + it_behaves_like 'helm commands' do + let(:commands) do + <<~EOS + helm init --client-only + helm repo add app-name https://repository.example.com + helm repo update + #{helm_install_command} + EOS + end + + let(:helm_install_command) do + <<~EOS.strip + /bin/date + /bin/true + helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml + EOS + end + end + end + + context 'when there is a post-install script' do + let(:postinstall) { ['/bin/date', "/bin/false\n"] } + + it_behaves_like 'helm commands' do + let(:commands) do + <<~EOS + helm init --client-only + helm repo add app-name https://repository.example.com + helm repo update + #{helm_install_command} + EOS + end + + let(:helm_install_command) do + <<~EOS.strip + helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml + /bin/date + /bin/false EOS end end @@ -105,8 +157,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null + helm init --client-only helm repo add app-name https://repository.example.com + helm repo update #{helm_install_command} EOS end @@ -117,7 +170,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do --name app-name --version 1.2.3 --namespace gitlab-managed-apps - -f /data/helm/app-name/config/values.yaml >/dev/null + -f /data/helm/app-name/config/values.yaml EOS end end @@ -129,8 +182,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null + helm init --client-only helm repo add app-name https://repository.example.com + helm repo update #{helm_install_command} EOS end @@ -144,7 +198,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --namespace gitlab-managed-apps - -f /data/helm/app-name/config/values.yaml >/dev/null + -f /data/helm/app-name/config/values.yaml EOS end end diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb index b333b334f36..c92bc92c42d 100644 --- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb @@ -30,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::Pod do it 'should generate the appropriate specifications for the container' do container = subject.generate.spec.containers.first expect(container.name).to eq('helm') - expect(container.image).to eq('alpine:3.6') + expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.7.2-kube-1.11.0') expect(container.env.count).to eq(3) expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT]) expect(container.command).to match_array(["/bin/sh"]) diff --git a/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb index 3dabf04413e..9c9fc91ef3c 100644 --- a/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb @@ -21,8 +21,8 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null - helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm init --client-only + helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS end end @@ -33,8 +33,8 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null - helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm init --client-only + helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS end end @@ -56,9 +56,9 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null + helm init --client-only helm repo add #{application.name} #{application.repository} - helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS end end @@ -70,8 +70,8 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null - helm upgrade #{application.name} #{application.chart} --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm init --client-only + helm upgrade #{application.name} #{application.chart} --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml EOS end end diff --git a/spec/lib/gitlab/kubernetes/role_binding_spec.rb b/spec/lib/gitlab/kubernetes/role_binding_spec.rb index da3f5d27b25..a1a59533bfb 100644 --- a/spec/lib/gitlab/kubernetes/role_binding_spec.rb +++ b/spec/lib/gitlab/kubernetes/role_binding_spec.rb @@ -20,7 +20,7 @@ describe Gitlab::Kubernetes::RoleBinding, '#generate' do let(:role_ref) do { apiGroup: 'rbac.authorization.k8s.io', - kind: 'Role', + kind: 'ClusterRole', name: role_name } end @@ -35,6 +35,7 @@ describe Gitlab::Kubernetes::RoleBinding, '#generate' do subject do described_class.new( + name: "gitlab-#{namespace}", role_name: role_name, namespace: namespace, service_account_name: service_account_name diff --git a/spec/lib/gitlab/private_commit_email_spec.rb b/spec/lib/gitlab/private_commit_email_spec.rb new file mode 100644 index 00000000000..bc86cd3842a --- /dev/null +++ b/spec/lib/gitlab/private_commit_email_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::PrivateCommitEmail do + let(:hostname) { Gitlab::CurrentSettings.current_application_settings.commit_email_hostname } + + context '.regex' do + subject { described_class.regex } + + it { is_expected.to match("1-foo@#{hostname}") } + it { is_expected.not_to match("1-foo@#{hostname}.foo") } + it { is_expected.not_to match('1-foo@users.noreply.gitlab.com') } + it { is_expected.not_to match('foo-1@users.noreply.gitlab.com') } + it { is_expected.not_to match('foobar@gitlab.com') } + end + + context '.user_id_for_email' do + let(:id) { 1 } + + it 'parses user id from email' do + email = "#{id}-foo@#{hostname}" + + expect(described_class.user_id_for_email(email)).to eq(id) + end + + it 'returns nil on invalid commit email' do + email = "#{id}-foo@users.noreply.bar.com" + + expect(described_class.user_id_for_email(email)).to be_nil + end + end + + context '.for_user' do + it 'returns email in the format id-username@hostname' do + user = create(:user) + + expect(described_class.for_user(user)).to eq("#{user.id}-#{user.username}@#{hostname}") + end + end +end diff --git a/spec/lib/gitlab/quick_actions/extractor_spec.rb b/spec/lib/gitlab/quick_actions/extractor_spec.rb index 0166f6c2ee0..873bb359d6e 100644 --- a/spec/lib/gitlab/quick_actions/extractor_spec.rb +++ b/spec/lib/gitlab/quick_actions/extractor_spec.rb @@ -272,5 +272,24 @@ describe Gitlab::QuickActions::Extractor do expect(commands).to be_empty expect(msg).to eq expected end + + it 'limits to passed commands when they are passed' do + msg = <<~MSG.strip + Hello, we should only extract the commands passed + /reopen + /labels hello world + /power + MSG + expected_msg = <<~EXPECTED.strip + Hello, we should only extract the commands passed + /power + EXPECTED + expected_commands = [['reopen'], ['labels', 'hello world']] + + msg, commands = extractor.extract_commands(msg, only: [:open, :labels]) + + expect(commands).to eq(expected_commands) + expect(msg).to eq expected_msg + end end end diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb index b1b7c427313..6ce9d515a0f 100644 --- a/spec/lib/gitlab/shell_spec.rb +++ b/spec/lib/gitlab/shell_spec.rb @@ -498,126 +498,6 @@ describe Gitlab::Shell do end end - describe '#fetch_remote' do - def fetch_remote(ssh_auth = nil, prune = true) - gitlab_shell.fetch_remote(repository.raw_repository, 'remote-name', ssh_auth: ssh_auth, prune: prune) - end - - def expect_call(fail, options = {}) - receive_fetch_remote = - if fail - receive(:fetch_remote).and_raise(GRPC::NotFound) - else - receive(:fetch_remote).and_return(true) - end - - expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive_fetch_remote - end - - def build_ssh_auth(opts = {}) - defaults = { - ssh_import?: true, - ssh_key_auth?: false, - ssh_known_hosts: nil, - ssh_private_key: nil - } - - double(:ssh_auth, defaults.merge(opts)) - end - - it 'returns true when the command succeeds' do - expect_call(false, force: false, tags: true, prune: true) - - expect(fetch_remote).to be_truthy - end - - it 'returns true when the command succeeds' do - expect_call(false, force: false, tags: true, prune: false) - - expect(fetch_remote(nil, false)).to be_truthy - end - - it 'raises an exception when the command fails' do - expect_call(true, force: false, tags: true, prune: true) - - expect { fetch_remote }.to raise_error(Gitlab::Shell::Error) - end - - it 'allows forced and no_tags to be changed' do - expect_call(false, force: true, tags: false, prune: true) - - result = gitlab_shell.fetch_remote(repository.raw_repository, 'remote-name', forced: true, no_tags: true, prune: true) - expect(result).to be_truthy - end - - context 'SSH auth' do - it 'passes the SSH key if specified' do - expect_call(false, force: false, tags: true, prune: true, ssh_key: 'foo') - - ssh_auth = build_ssh_auth(ssh_key_auth?: true, ssh_private_key: 'foo') - - expect(fetch_remote(ssh_auth)).to be_truthy - end - - it 'does not pass an empty SSH key' do - expect_call(false, force: false, tags: true, prune: true) - - ssh_auth = build_ssh_auth(ssh_key_auth: true, ssh_private_key: '') - - expect(fetch_remote(ssh_auth)).to be_truthy - end - - it 'does not pass the key unless SSH key auth is to be used' do - expect_call(false, force: false, tags: true, prune: true) - - ssh_auth = build_ssh_auth(ssh_key_auth: false, ssh_private_key: 'foo') - - expect(fetch_remote(ssh_auth)).to be_truthy - end - - it 'passes the known_hosts data if specified' do - expect_call(false, force: false, tags: true, prune: true, known_hosts: 'foo') - - ssh_auth = build_ssh_auth(ssh_known_hosts: 'foo') - - expect(fetch_remote(ssh_auth)).to be_truthy - end - - it 'does not pass empty known_hosts data' do - expect_call(false, force: false, tags: true, prune: true) - - ssh_auth = build_ssh_auth(ssh_known_hosts: '') - - expect(fetch_remote(ssh_auth)).to be_truthy - end - - it 'does not pass known_hosts data unless SSH is to be used' do - expect_call(false, force: false, tags: true, prune: true) - - ssh_auth = build_ssh_auth(ssh_import?: false, ssh_known_hosts: 'foo') - - expect(fetch_remote(ssh_auth)).to be_truthy - end - end - - context 'gitaly call' do - let(:remote_name) { 'remote-name' } - let(:ssh_auth) { double(:ssh_auth) } - - subject do - gitlab_shell.fetch_remote(repository.raw_repository, remote_name, - forced: true, no_tags: true, ssh_auth: ssh_auth) - end - - it 'passes the correct params to the gitaly service' do - expect(repository.gitaly_repository_client).to receive(:fetch_remote) - .with(remote_name, ssh_auth: ssh_auth, forced: true, no_tags: true, prune: true, timeout: timeout) - - subject - end - end - end - describe '#import_repository' do let(:import_url) { 'https://gitlab.com/gitlab-org/gitlab-ce.git' } diff --git a/spec/lib/gitlab/slash_commands/command_spec.rb b/spec/lib/gitlab/slash_commands/command_spec.rb index 194cae8c645..eceacac58af 100644 --- a/spec/lib/gitlab/slash_commands/command_spec.rb +++ b/spec/lib/gitlab/slash_commands/command_spec.rb @@ -44,7 +44,7 @@ describe Gitlab::SlashCommands::Command do let!(:build) { create(:ci_build, pipeline: pipeline) } let!(:pipeline) { create(:ci_pipeline, project: project) } let!(:staging) { create(:environment, name: 'staging', project: project) } - let!(:deployment) { create(:deployment, environment: staging, deployable: build) } + let!(:deployment) { create(:deployment, :success, environment: staging, deployable: build) } let!(:manual) do create(:ci_build, :manual, pipeline: pipeline, diff --git a/spec/lib/gitlab/slash_commands/deploy_spec.rb b/spec/lib/gitlab/slash_commands/deploy_spec.rb index 0d57334aa4c..25f3e8a0409 100644 --- a/spec/lib/gitlab/slash_commands/deploy_spec.rb +++ b/spec/lib/gitlab/slash_commands/deploy_spec.rb @@ -31,7 +31,7 @@ describe Gitlab::SlashCommands::Deploy do let!(:staging) { create(:environment, name: 'staging', project: project) } let!(:pipeline) { create(:ci_pipeline, project: project) } let!(:build) { create(:ci_build, pipeline: pipeline) } - let!(:deployment) { create(:deployment, environment: staging, deployable: build) } + let!(:deployment) { create(:deployment, :success, environment: staging, deployable: build) } context 'without actions' do it 'does not execute an action' do diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 69ee5ff4bcd..b212d2b05f2 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -8,6 +8,7 @@ describe Gitlab::UsageData do before do create(:jira_service, project: projects[0]) create(:jira_service, project: projects[1]) + create(:jira_cloud_service, project: projects[2]) create(:prometheus_service, project: projects[1]) create(:service, project: projects[0], type: 'SlackSlashCommandsService', active: true) create(:service, project: projects[1], type: 'SlackService', active: true) @@ -20,6 +21,7 @@ describe Gitlab::UsageData do create(:clusters_applications_ingress, :installed, cluster: gcp_cluster) create(:clusters_applications_prometheus, :installed, cluster: gcp_cluster) create(:clusters_applications_runner, :installed, cluster: gcp_cluster) + create(:clusters_applications_knative, :installed, cluster: gcp_cluster) end subject { described_class.data } @@ -81,6 +83,7 @@ describe Gitlab::UsageData do clusters_applications_ingress clusters_applications_prometheus clusters_applications_runner + clusters_applications_knative in_review_folder groups issues @@ -95,6 +98,8 @@ describe Gitlab::UsageData do projects projects_imported_from_github projects_jira_active + projects_jira_server_active + projects_jira_cloud_active projects_slack_notifications_active projects_slack_slash_active projects_prometheus_active @@ -114,7 +119,9 @@ describe Gitlab::UsageData do expect(count_data[:projects]).to eq(3) expect(count_data[:projects_prometheus_active]).to eq(1) - expect(count_data[:projects_jira_active]).to eq(2) + expect(count_data[:projects_jira_active]).to eq(3) + expect(count_data[:projects_jira_server_active]).to eq(2) + expect(count_data[:projects_jira_cloud_active]).to eq(1) expect(count_data[:projects_slack_notifications_active]).to eq(2) expect(count_data[:projects_slack_slash_active]).to eq(1) @@ -126,6 +133,7 @@ describe Gitlab::UsageData do expect(count_data[:clusters_applications_ingress]).to eq(1) expect(count_data[:clusters_applications_prometheus]).to eq(1) expect(count_data[:clusters_applications_runner]).to eq(1) + expect(count_data[:clusters_applications_knative]).to eq(1) end it 'works when queries time out' do diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb index 4ba99009855..ad2c9d7f2af 100644 --- a/spec/lib/gitlab/utils_spec.rb +++ b/spec/lib/gitlab/utils_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Gitlab::Utils do delegate :to_boolean, :boolean_to_yes_no, :slugify, :random_string, :which, :ensure_array_from_string, - :bytes_to_megabytes, to: :described_class + :bytes_to_megabytes, :append_path, to: :described_class describe '.slugify' do { @@ -106,4 +106,25 @@ describe Gitlab::Utils do expect(bytes_to_megabytes(bytes)).to eq(1) end end + + describe '.append_path' do + using RSpec::Parameterized::TableSyntax + + where(:host, :path, :result) do + 'http://test/' | '/foo/bar' | 'http://test/foo/bar' + 'http://test/' | '//foo/bar' | 'http://test/foo/bar' + 'http://test//' | '/foo/bar' | 'http://test/foo/bar' + 'http://test' | 'foo/bar' | 'http://test/foo/bar' + 'http://test//' | '' | 'http://test/' + 'http://test//' | nil | 'http://test/' + '' | '/foo/bar' | '/foo/bar' + nil | '/foo/bar' | '/foo/bar' + end + + with_them do + it 'makes sure there is only one slash as path separator' do + expect(append_path(host, path)).to eq(result) + end + end + end end diff --git a/spec/lib/gitlab/view/presenter/base_spec.rb b/spec/lib/gitlab/view/presenter/base_spec.rb index 4eca53032a2..02c2fd47197 100644 --- a/spec/lib/gitlab/view/presenter/base_spec.rb +++ b/spec/lib/gitlab/view/presenter/base_spec.rb @@ -40,7 +40,7 @@ describe Gitlab::View::Presenter::Base do end end - context 'subject is overriden' do + context 'subject is overridden' do it 'returns true' do presenter = presenter_class.new(build_stubbed(:project, :public)) diff --git a/spec/lib/microsoft_teams/notifier_spec.rb b/spec/lib/microsoft_teams/notifier_spec.rb index c9756544bd6..2aaa7c24ad8 100644 --- a/spec/lib/microsoft_teams/notifier_spec.rb +++ b/spec/lib/microsoft_teams/notifier_spec.rb @@ -48,7 +48,7 @@ describe MicrosoftTeams::Notifier do stub_request(:post, webhook_url).with(body: JSON(body), headers: { 'Content-Type' => 'application/json' }).to_return(status: 200, body: "", headers: {}) end - it 'expects to receive successfull answer' do + it 'expects to receive successful answer' do expect(subject.ping(options)).to be true end end |