summaryrefslogtreecommitdiff
path: root/spec/finders
diff options
context:
space:
mode:
Diffstat (limited to 'spec/finders')
-rw-r--r--spec/finders/admin/plans_finder_spec.rb54
-rw-r--r--spec/finders/boards/boards_finder_spec.rb24
-rw-r--r--spec/finders/ci/daily_build_group_report_results_finder_spec.rb91
-rw-r--r--spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb99
-rw-r--r--spec/finders/issues_finder_spec.rb59
-rw-r--r--spec/finders/merge_request_target_project_finder_spec.rb11
-rw-r--r--spec/finders/merge_requests/oldest_per_commit_finder_spec.rb61
-rw-r--r--spec/finders/merge_requests_finder_spec.rb55
-rw-r--r--spec/finders/namespaces/projects_finder_spec.rb83
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb2
-rw-r--r--spec/finders/packages/npm/package_finder_spec.rb130
-rw-r--r--spec/finders/packages/package_finder_spec.rb2
-rw-r--r--spec/finders/packages/packages_finder_spec.rb2
-rw-r--r--spec/finders/projects/groups_finder_spec.rb103
-rw-r--r--spec/finders/repositories/changelog_commits_finder_spec.rb93
-rw-r--r--spec/finders/repositories/commits_with_trailer_finder_spec.rb38
-rw-r--r--spec/finders/repositories/previous_tag_finder_spec.rb8
-rw-r--r--spec/finders/security/license_compliance_jobs_finder_spec.rb5
-rw-r--r--spec/finders/users_finder_spec.rb20
19 files changed, 698 insertions, 242 deletions
diff --git a/spec/finders/admin/plans_finder_spec.rb b/spec/finders/admin/plans_finder_spec.rb
new file mode 100644
index 00000000000..9ea5944147c
--- /dev/null
+++ b/spec/finders/admin/plans_finder_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::PlansFinder do
+ let_it_be(:plan1) { create(:plan, name: 'plan1') }
+ let_it_be(:plan2) { create(:plan, name: 'plan2') }
+
+ describe '#execute' do
+ context 'with no params' do
+ it 'returns all plans' do
+ found = described_class.new.execute
+
+ expect(found).to match_array([plan1, plan2])
+ end
+ end
+
+ context 'with missing name in params' do
+ before do
+ @params = { title: 'plan2' }
+ end
+
+ it 'returns all plans' do
+ found = described_class.new(@params).execute
+
+ expect(found).to match_array([plan1, plan2])
+ end
+ end
+
+ context 'with existing name in params' do
+ before do
+ @params = { name: 'plan2' }
+ end
+
+ it 'returns the plan' do
+ found = described_class.new(@params).execute
+
+ expect(found).to match(plan2)
+ end
+ end
+
+ context 'with non-existing name in params' do
+ before do
+ @params = { name: 'non-existing-plan' }
+ end
+
+ it 'returns nil' do
+ found = described_class.new(@params).execute
+
+ expect(found).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/finders/boards/boards_finder_spec.rb b/spec/finders/boards/boards_finder_spec.rb
new file mode 100644
index 00000000000..2249c69df1b
--- /dev/null
+++ b/spec/finders/boards/boards_finder_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Boards::BoardsFinder do
+ describe '#execute' do
+ context 'when board parent is a project' do
+ let(:parent) { create(:project) }
+
+ subject(:service) { described_class.new(parent, double) }
+
+ it_behaves_like 'boards list service'
+ it_behaves_like 'multiple boards list service'
+ end
+
+ context 'when board parent is a group' do
+ let(:parent) { create(:group) }
+
+ subject(:service) { described_class.new(parent, double) }
+
+ it_behaves_like 'boards list service'
+ end
+ end
+end
diff --git a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
index 2a6e44673e3..cf15a00323b 100644
--- a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
+++ b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
@@ -5,10 +5,14 @@ require 'spec_helper'
RSpec.describe Ci::DailyBuildGroupReportResultsFinder do
describe '#execute' do
let_it_be(:project) { create(:project, :private) }
- let_it_be(:current_user) { project.owner }
+ let(:user_without_permission) { create(:user) }
+ let_it_be(:user_with_permission) { project.owner }
let_it_be(:ref_path) { 'refs/heads/master' }
let(:limit) { nil }
let_it_be(:default_branch) { false }
+ let(:start_date) { '2020-03-09' }
+ let(:end_date) { '2020-03-10' }
+ let(:sort) { true }
let_it_be(:rspec_coverage_1) { create_daily_coverage('rspec', 79.0, '2020-03-09') }
let_it_be(:karma_coverage_1) { create_daily_coverage('karma', 89.0, '2020-03-09') }
@@ -17,24 +21,35 @@ RSpec.describe Ci::DailyBuildGroupReportResultsFinder do
let_it_be(:rspec_coverage_3) { create_daily_coverage('rspec', 97.0, '2020-03-11') }
let_it_be(:karma_coverage_3) { create_daily_coverage('karma', 99.0, '2020-03-11') }
- let(:attributes) do
+ let(:finder) { described_class.new(params: params, current_user: current_user) }
+
+ let(:params) do
{
- current_user: current_user,
project: project,
+ coverage: true,
ref_path: ref_path,
- start_date: '2020-03-09',
- end_date: '2020-03-10',
- limit: limit
+ start_date: start_date,
+ end_date: end_date,
+ limit: limit,
+ sort: sort
}
end
- subject(:coverages) do
- described_class.new(**attributes).execute
- end
+ subject(:coverages) { finder.execute }
+
+ context 'when params are provided' do
+ context 'when current user is not allowed to read data' do
+ let(:current_user) { user_without_permission }
+
+ it 'returns an empty collection' do
+ expect(coverages).to be_empty
+ end
+ end
+
+ context 'when current user is allowed to read data' do
+ let(:current_user) { user_with_permission }
- context 'when ref_path is present' do
- context 'when current user is allowed to read build report results' do
- it 'returns all matching results within the given date range' do
+ it 'returns matching coverages within the given date range' do
expect(coverages).to match_array([
karma_coverage_2,
rspec_coverage_2,
@@ -43,37 +58,45 @@ RSpec.describe Ci::DailyBuildGroupReportResultsFinder do
])
end
- context 'and limit is specified' do
+ context 'when ref_path is nil' do
+ let(:default_branch) { true }
+ let(:ref_path) { nil }
+
+ it 'returns coverages for the default branch' do
+ rspec_coverage_4 = create_daily_coverage('rspec', 66.0, '2020-03-10')
+
+ expect(coverages).to contain_exactly(rspec_coverage_4)
+ end
+ end
+
+ context 'when limit is specified' do
let(:limit) { 2 }
- it 'returns limited number of matching results within the given date range' do
+ it 'returns limited number of matching coverages within the given date range' do
expect(coverages).to match_array([
karma_coverage_2,
rspec_coverage_2
])
end
end
- end
-
- context 'when current user is not allowed to read build report results' do
- let(:current_user) { create(:user) }
-
- it 'returns an empty result' do
- expect(coverages).to be_empty
- end
- end
- end
-
- context 'when ref_path query parameter is not present' do
- let(:ref_path) { nil }
- context 'when records with cover data from the default branch exist' do
- let(:default_branch) { true }
-
- it 'returns records with default_branch:true, irrespective of ref_path' do
- rspec_coverage_4 = create_daily_coverage('rspec', 66.0, '2020-03-10')
-
- expect(coverages).to contain_exactly(rspec_coverage_4)
+ context 'when provided dates are nil' do
+ let(:start_date) { nil }
+ let(:end_date) { nil }
+ let(:rspec_coverage_4) { create_daily_coverage('rspec', 98.0, 91.days.ago.to_date.to_s) }
+
+ it 'returns all coverages from the last 90 days' do
+ expect(coverages).to match_array(
+ [
+ karma_coverage_3,
+ rspec_coverage_3,
+ karma_coverage_2,
+ rspec_coverage_2,
+ karma_coverage_1,
+ rspec_coverage_1
+ ]
+ )
+ end
end
end
end
diff --git a/spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb b/spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb
deleted file mode 100644
index a703f3b800c..00000000000
--- a/spec/finders/ci/testing/daily_build_group_report_results_finder_spec.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::Testing::DailyBuildGroupReportResultsFinder do
- describe '#execute' do
- let_it_be(:project) { create(:project, :private) }
- let(:user_without_permission) { create(:user) }
- let_it_be(:user_with_permission) { project.owner }
- let_it_be(:ref_path) { 'refs/heads/master' }
- let(:limit) { nil }
- let_it_be(:default_branch) { false }
- let(:start_date) { '2020-03-09' }
- let(:end_date) { '2020-03-10' }
- let(:sort) { true }
-
- let_it_be(:rspec_coverage_1) { create_daily_coverage('rspec', 79.0, '2020-03-09') }
- let_it_be(:karma_coverage_1) { create_daily_coverage('karma', 89.0, '2020-03-09') }
- let_it_be(:rspec_coverage_2) { create_daily_coverage('rspec', 95.0, '2020-03-10') }
- let_it_be(:karma_coverage_2) { create_daily_coverage('karma', 92.0, '2020-03-10') }
- let_it_be(:rspec_coverage_3) { create_daily_coverage('rspec', 97.0, '2020-03-11') }
- let_it_be(:karma_coverage_3) { create_daily_coverage('karma', 99.0, '2020-03-11') }
-
- let(:finder) { described_class.new(params: params, current_user: current_user) }
-
- let(:params) do
- {
- project: project,
- coverage: true,
- ref_path: ref_path,
- start_date: start_date,
- end_date: end_date,
- limit: limit,
- sort: sort
- }
- end
-
- subject(:coverages) { finder.execute }
-
- context 'when params are provided' do
- context 'when current user is not allowed to read data' do
- let(:current_user) { user_without_permission }
-
- it 'returns an empty collection' do
- expect(coverages).to be_empty
- end
- end
-
- context 'when current user is allowed to read data' do
- let(:current_user) { user_with_permission }
-
- it 'returns matching coverages within the given date range' do
- expect(coverages).to match_array([
- karma_coverage_2,
- rspec_coverage_2,
- karma_coverage_1,
- rspec_coverage_1
- ])
- end
-
- context 'when ref_path is nil' do
- let(:default_branch) { true }
- let(:ref_path) { nil }
-
- it 'returns coverages for the default branch' do
- rspec_coverage_4 = create_daily_coverage('rspec', 66.0, '2020-03-10')
-
- expect(coverages).to contain_exactly(rspec_coverage_4)
- end
- end
-
- context 'when limit is specified' do
- let(:limit) { 2 }
-
- it 'returns limited number of matching coverages within the given date range' do
- expect(coverages).to match_array([
- karma_coverage_2,
- rspec_coverage_2
- ])
- end
- end
- end
- end
- end
-
- private
-
- def create_daily_coverage(group_name, coverage, date)
- create(
- :ci_daily_build_group_report_result,
- project: project,
- ref_path: ref_path || 'feature-branch',
- group_name: group_name,
- data: { 'coverage' => coverage },
- date: date,
- default_branch: default_branch
- )
- end
-end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 33b8a5954ae..b794ab626bf 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -179,33 +179,54 @@ RSpec.describe IssuesFinder do
end
end
- context 'filtering by author ID' do
- let(:params) { { author_id: user2.id } }
+ context 'filtering by author' do
+ context 'by author ID' do
+ let(:params) { { author_id: user2.id } }
- it 'returns issues created by that user' do
- expect(issues).to contain_exactly(issue3)
+ it 'returns issues created by that user' do
+ expect(issues).to contain_exactly(issue3)
+ end
end
- end
- context 'filtering by not author ID' do
- let(:params) { { not: { author_id: user2.id } } }
+ context 'using OR' do
+ let(:issue6) { create(:issue, project: project2) }
+ let(:params) { { or: { author_username: [issue3.author.username, issue6.author.username] } } }
+
+ it 'returns issues created by any of the given users' do
+ expect(issues).to contain_exactly(issue3, issue6)
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(or_issuable_queries: false)
+ end
- it 'returns issues not created by that user' do
- expect(issues).to contain_exactly(issue1, issue2, issue4, issue5)
+ it 'does not add any filter' do
+ expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, issue5, issue6)
+ end
+ end
end
- end
- context 'filtering by nonexistent author ID and issue term using CTE for search' do
- let(:params) do
- {
- author_id: 'does-not-exist',
- search: 'git',
- attempt_group_search_optimizations: true
- }
+ context 'filtering by NOT author ID' do
+ let(:params) { { not: { author_id: user2.id } } }
+
+ it 'returns issues not created by that user' do
+ expect(issues).to contain_exactly(issue1, issue2, issue4, issue5)
+ end
end
- it 'returns no results' do
- expect(issues).to be_empty
+ context 'filtering by nonexistent author ID and issue term using CTE for search' do
+ let(:params) do
+ {
+ author_id: 'does-not-exist',
+ search: 'git',
+ attempt_group_search_optimizations: true
+ }
+ end
+
+ it 'returns no results' do
+ expect(issues).to be_empty
+ end
end
end
diff --git a/spec/finders/merge_request_target_project_finder_spec.rb b/spec/finders/merge_request_target_project_finder_spec.rb
index dfb4d86fbb6..08fbfd7229a 100644
--- a/spec/finders/merge_request_target_project_finder_spec.rb
+++ b/spec/finders/merge_request_target_project_finder_spec.rb
@@ -16,13 +16,22 @@ RSpec.describe MergeRequestTargetProjectFinder do
expect(finder.execute).to contain_exactly(base_project, other_fork, forked_project)
end
- it 'does not include projects that have merge requests turned off' do
+ it 'does not include projects that have merge requests turned off by default' do
other_fork.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
base_project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
expect(finder.execute).to contain_exactly(forked_project)
end
+ it 'includes projects that have merge requests turned off by default with a more-permissive project feature' do
+ finder = described_class.new(current_user: user, source_project: forked_project, project_feature: :repository)
+
+ other_fork.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
+ base_project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
+
+ expect(finder.execute).to contain_exactly(base_project, other_fork, forked_project)
+ end
+
it 'does not contain archived projects' do
base_project.update!(archived: true)
diff --git a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
index 4e9d021fa5d..4724a8eb5c7 100644
--- a/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
+++ b/spec/finders/merge_requests/oldest_per_commit_finder_spec.rb
@@ -6,12 +6,20 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
describe '#execute' do
it 'returns a Hash mapping commit SHAs to their oldest merge requests' do
project = create(:project)
+ sha1 = Digest::SHA1.hexdigest('foo')
+ sha2 = Digest::SHA1.hexdigest('bar')
+ sha3 = Digest::SHA1.hexdigest('baz')
mr1 = create(:merge_request, :merged, target_project: project)
mr2 = create(:merge_request, :merged, target_project: project)
+ mr3 = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ merge_commit_sha: sha3
+ )
+
mr1_diff = create(:merge_request_diff, merge_request: mr1)
mr2_diff = create(:merge_request_diff, merge_request: mr2)
- sha1 = Digest::SHA1.hexdigest('foo')
- sha2 = Digest::SHA1.hexdigest('bar')
create(:merge_request_diff_commit, merge_request_diff: mr1_diff, sha: sha1)
create(:merge_request_diff_commit, merge_request_diff: mr2_diff, sha: sha1)
@@ -22,11 +30,16 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
relative_order: 1
)
- commits = [double(:commit, id: sha1), double(:commit, id: sha2)]
+ commits = [
+ double(:commit, id: sha1),
+ double(:commit, id: sha2),
+ double(:commit, id: sha3)
+ ]
expect(described_class.new(project).execute(commits)).to eq(
sha1 => mr1,
- sha2 => mr2
+ sha2 => mr2,
+ sha3 => mr3
)
end
@@ -42,5 +55,45 @@ RSpec.describe MergeRequests::OldestPerCommitFinder do
expect(described_class.new(mr.target_project).execute(commits))
.to be_empty
end
+
+ it 'includes the merge request for a merge commit' do
+ project = create(:project)
+ sha = Digest::SHA1.hexdigest('foo')
+ mr = create(
+ :merge_request,
+ :merged,
+ target_project: project,
+ merge_commit_sha: sha
+ )
+
+ commits = [double(:commit, id: sha)]
+
+ # This expectation is set so we're certain that the merge commit SHAs (if
+ # a matching merge request is found) aren't also used for finding MRs
+ # according to diffs.
+ expect(MergeRequestDiffCommit)
+ .not_to receive(:oldest_merge_request_id_per_commit)
+
+ expect(described_class.new(project).execute(commits)).to eq(sha => mr)
+ end
+
+ it 'includes the oldest merge request when a merge commit is present in a newer merge request' do
+ project = create(:project)
+ sha = Digest::SHA1.hexdigest('foo')
+ mr1 = create(
+ :merge_request,
+ :merged,
+ target_project: project, merge_commit_sha: sha
+ )
+
+ mr2 = create(:merge_request, :merged, target_project: project)
+ mr_diff = create(:merge_request_diff, merge_request: mr2)
+
+ create(:merge_request_diff_commit, merge_request_diff: mr_diff, sha: sha)
+
+ commits = [double(:commit, id: sha)]
+
+ expect(described_class.new(project).execute(commits)).to eq(sha => mr1)
+ end
end
end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 6fdfe780463..b3000498bb6 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -41,30 +41,51 @@ RSpec.describe MergeRequestsFinder do
expect(merge_requests).to contain_exactly(merge_request1)
end
- it 'filters by nonexistent author ID and MR term using CTE for search' do
- params = {
- author_id: 'does-not-exist',
- search: 'git',
- attempt_group_search_optimizations: true
- }
+ context 'filtering by author' do
+ subject(:merge_requests) { described_class.new(user, params).execute }
- merge_requests = described_class.new(user, params).execute
+ context 'using OR' do
+ let(:params) { { or: { author_username: [merge_request1.author.username, merge_request2.author.username] } } }
- expect(merge_requests).to be_empty
- end
+ before do
+ merge_request1.update!(author: create(:user))
+ merge_request2.update!(author: create(:user))
+ end
+
+ it 'returns merge requests created by any of the given users' do
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2)
+ end
- context 'filtering by not author ID' do
- let(:params) { { not: { author_id: user2.id } } }
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(or_issuable_queries: false)
+ end
- before do
- merge_request2.update!(author: user2)
- merge_request3.update!(author: user2)
+ it 'does not add any filter' do
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5)
+ end
+ end
end
- it 'returns merge requests not created by that user' do
- merge_requests = described_class.new(user, params).execute
+ context 'with nonexistent author ID and MR term using CTE for search' do
+ let(:params) { { author_id: 'does-not-exist', search: 'git', attempt_group_search_optimizations: true } }
+
+ it 'returns no results' do
+ expect(merge_requests).to be_empty
+ end
+ end
- expect(merge_requests).to contain_exactly(merge_request1, merge_request4, merge_request5)
+ context 'filtering by not author ID' do
+ let(:params) { { not: { author_id: user2.id } } }
+
+ before do
+ merge_request2.update!(author: user2)
+ merge_request3.update!(author: user2)
+ end
+
+ it 'returns merge requests not created by that user' do
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request4, merge_request5)
+ end
end
end
diff --git a/spec/finders/namespaces/projects_finder_spec.rb b/spec/finders/namespaces/projects_finder_spec.rb
new file mode 100644
index 00000000000..0f48aa6a9f4
--- /dev/null
+++ b/spec/finders/namespaces/projects_finder_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::ProjectsFinder do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:namespace) { create(:group, :public) }
+ let_it_be(:subgroup) { create(:group, parent: namespace) }
+ let_it_be(:project_1) { create(:project, :public, group: namespace, path: 'project', name: 'Project') }
+ let_it_be(:project_2) { create(:project, :public, group: namespace, path: 'test-project', name: 'Test Project') }
+ let_it_be(:project_3) { create(:project, :public, path: 'sub-test-project', group: subgroup, name: 'Sub Test Project') }
+ let_it_be(:project_4) { create(:project, :public, path: 'test-project-2', group: namespace, name: 'Test Project 2') }
+
+ let(:params) { {} }
+
+ let(:finder) { described_class.new(namespace: namespace, params: params, current_user: current_user) }
+
+ subject(:projects) { finder.execute }
+
+ describe '#execute' do
+ context 'without a namespace' do
+ let(:namespace) { nil }
+
+ it 'returns an empty array' do
+ expect(projects).to be_empty
+ end
+ end
+
+ context 'with a namespace' do
+ it 'returns the project for the namespace' do
+ expect(projects).to contain_exactly(project_1, project_2, project_4)
+ end
+
+ context 'when include_subgroups is provided' do
+ let(:params) { { include_subgroups: true } }
+
+ it 'returns all projects for the namespace' do
+ expect(projects).to contain_exactly(project_1, project_2, project_3, project_4)
+ end
+
+ context 'when ids are provided' do
+ let(:params) { { include_subgroups: true, ids: [project_3.id] } }
+
+ it 'returns all projects for the ids' do
+ expect(projects).to contain_exactly(project_3)
+ end
+ end
+ end
+
+ context 'when ids are provided' do
+ let(:params) { { ids: [project_1.id] } }
+
+ it 'returns all projects for the ids' do
+ expect(projects).to contain_exactly(project_1)
+ end
+ end
+
+ context 'when sort is similarity' do
+ let(:params) { { sort: :similarity, search: 'test' } }
+
+ it 'returns projects by similarity' do
+ expect(projects).to contain_exactly(project_2, project_4)
+ end
+ end
+
+ context 'when search parameter is missing' do
+ let(:params) { { sort: :similarity } }
+
+ it 'returns all projects' do
+ expect(projects).to contain_exactly(project_1, project_2, project_4)
+ end
+ end
+
+ context 'when sort parameter is missing' do
+ let(:params) { { search: 'test' } }
+
+ it 'returns matching projects' do
+ expect(projects).to contain_exactly(project_2, project_4)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index 445482a5a96..d6daf73aba2 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -122,7 +122,7 @@ RSpec.describe Packages::GroupPackagesFinder do
end
context 'when there are processing packages' do
- let_it_be(:package4) { create(:nuget_package, project: project, name: Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) }
+ let_it_be(:package4) { create(:nuget_package, project: project, name: Packages::Nuget::TEMPORARY_PACKAGE_NAME) }
it { is_expected.to match_array([package1, package2]) }
end
diff --git a/spec/finders/packages/npm/package_finder_spec.rb b/spec/finders/packages/npm/package_finder_spec.rb
index 78c23971f92..f021d800f31 100644
--- a/spec/finders/packages/npm/package_finder_spec.rb
+++ b/spec/finders/packages/npm/package_finder_spec.rb
@@ -2,39 +2,139 @@
require 'spec_helper'
RSpec.describe ::Packages::Npm::PackageFinder do
- let(:package) { create(:npm_package) }
+ let_it_be_with_reload(:project) { create(:project)}
+ let_it_be(:package) { create(:npm_package, project: project) }
+
let(:project) { package.project }
let(:package_name) { package.name }
- describe '#execute!' do
- subject { described_class.new(project, package_name).execute }
+ shared_examples 'accepting a namespace for' do |example_name|
+ before do
+ project.update!(namespace: namespace)
+ end
+
+ context 'that is a group' do
+ let_it_be(:namespace) { create(:group) }
+
+ it_behaves_like example_name
+
+ context 'within another group' do
+ let_it_be(:subgroup) { create(:group, parent: namespace) }
+
+ before do
+ project.update!(namespace: subgroup)
+ end
+
+ it_behaves_like example_name
+ end
+ end
+
+ context 'that is a user namespace' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:namespace) { user.namespace }
+
+ it_behaves_like example_name
+ end
+ end
+
+ describe '#execute' do
+ shared_examples 'finding packages by name' do
+ it { is_expected.to eq([package]) }
+
+ context 'with unknown package name' do
+ let(:package_name) { 'baz' }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ subject { finder.execute }
+
+ context 'with a project' do
+ let(:finder) { described_class.new(package_name, project: project) }
- it { is_expected.to eq([package]) }
+ it_behaves_like 'finding packages by name'
- context 'with unknown package name' do
- let(:package_name) { 'baz' }
+ context 'set to nil' do
+ let(:project) { nil }
- it { is_expected.to be_empty }
+ it { is_expected.to be_empty }
+ end
end
- context 'with nil project' do
- let(:project) { nil }
+ context 'with a namespace' do
+ let(:finder) { described_class.new(package_name, namespace: namespace) }
+
+ it_behaves_like 'accepting a namespace for', 'finding packages by name'
+
+ context 'set to nil' do
+ let_it_be(:namespace) { nil }
- it { is_expected.to be_empty }
+ it { is_expected.to be_empty }
+ end
end
end
describe '#find_by_version' do
let(:version) { package.version }
- subject { described_class.new(project, package.name).find_by_version(version) }
+ subject { finder.find_by_version(version) }
+
+ shared_examples 'finding packages by version' do
+ it { is_expected.to eq(package) }
+
+ context 'with unknown version' do
+ let(:version) { 'foobar' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context 'with a project' do
+ let(:finder) { described_class.new(package_name, project: project) }
+
+ it_behaves_like 'finding packages by version'
+ end
+
+ context 'with a namespace' do
+ let(:finder) { described_class.new(package_name, namespace: namespace) }
+
+ it_behaves_like 'accepting a namespace for', 'finding packages by version'
+ end
+ end
+
+ describe '#last' do
+ subject { finder.last }
+
+ shared_examples 'finding package by last' do
+ it { is_expected.to eq(package) }
+ end
+
+ context 'with a project' do
+ let(:finder) { described_class.new(package_name, project: project) }
+
+ it_behaves_like 'finding package by last'
+ end
+
+ context 'with a namespace' do
+ let(:finder) { described_class.new(package_name, namespace: namespace) }
+
+ it_behaves_like 'accepting a namespace for', 'finding package by last'
- it { is_expected.to eq(package) }
+ context 'with duplicate packages' do
+ let_it_be(:namespace) { create(:group) }
+ let_it_be(:subgroup1) { create(:group, parent: namespace) }
+ let_it_be(:subgroup2) { create(:group, parent: namespace) }
+ let_it_be(:project2) { create(:project, namespace: subgroup2) }
+ let_it_be(:package2) { create(:npm_package, name: package.name, project: project2) }
- context 'with unknown version' do
- let(:version) { 'foobar' }
+ before do
+ project.update!(namespace: subgroup1)
+ end
- it { is_expected.to be_nil }
+ # the most recent one is returned
+ it { is_expected.to eq(package2) }
+ end
end
end
end
diff --git a/spec/finders/packages/package_finder_spec.rb b/spec/finders/packages/package_finder_spec.rb
index ef07e7575d1..e8c7404a612 100644
--- a/spec/finders/packages/package_finder_spec.rb
+++ b/spec/finders/packages/package_finder_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe ::Packages::PackageFinder do
it { is_expected.to eq(maven_package) }
context 'processing packages' do
- let_it_be(:nuget_package) { create(:nuget_package, project: project, name: Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) }
+ let_it_be(:nuget_package) { create(:nuget_package, project: project, name: Packages::Nuget::TEMPORARY_PACKAGE_NAME) }
let(:package_id) { nuget_package.id }
it 'are not returned' do
diff --git a/spec/finders/packages/packages_finder_spec.rb b/spec/finders/packages/packages_finder_spec.rb
index 6e92616bafa..0add77a8478 100644
--- a/spec/finders/packages/packages_finder_spec.rb
+++ b/spec/finders/packages/packages_finder_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe ::Packages::PackagesFinder do
end
context 'with processing packages' do
- let_it_be(:nuget_package) { create(:nuget_package, project: project, name: Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) }
+ let_it_be(:nuget_package) { create(:nuget_package, project: project, name: Packages::Nuget::TEMPORARY_PACKAGE_NAME) }
it { is_expected.to match_array([conan_package, maven_package]) }
end
diff --git a/spec/finders/projects/groups_finder_spec.rb b/spec/finders/projects/groups_finder_spec.rb
new file mode 100644
index 00000000000..89d4edaec7c
--- /dev/null
+++ b/spec/finders/projects/groups_finder_spec.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::GroupsFinder do
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:root_group) { create(:group, :public) }
+ let_it_be(:project_group) { create(:group, :public, parent: root_group) }
+ let_it_be(:shared_group_with_dev_access) { create(:group, :private, parent: root_group) }
+ let_it_be(:shared_group_with_reporter_access) { create(:group, :private) }
+
+ let_it_be(:public_project) { create(:project, :public, group: project_group) }
+ let_it_be(:private_project) { create(:project, :private, group: project_group) }
+
+ before_all do
+ [public_project, private_project].each do |project|
+ create(:project_group_link, :developer, group: shared_group_with_dev_access, project: project)
+ create(:project_group_link, :reporter, group: shared_group_with_reporter_access, project: project)
+ end
+ end
+
+ let(:params) { {} }
+ let(:current_user) { user }
+ let(:finder) { described_class.new(project: project, current_user: current_user, params: params) }
+
+ subject { finder.execute }
+
+ shared_examples 'finding related groups' do
+ it 'returns ancestor groups for this project' do
+ is_expected.to match_array([project_group, root_group])
+ end
+
+ context 'when the project does not belong to any group' do
+ before do
+ allow(project).to receive(:group) { nil }
+ end
+
+ it { is_expected.to eq([]) }
+ end
+
+ context 'when shared groups option is on' do
+ let(:params) { { with_shared: true } }
+
+ it 'returns ancestor and all shared groups' do
+ is_expected.to match_array([project_group, root_group, shared_group_with_dev_access, shared_group_with_reporter_access])
+ end
+
+ context 'when shared_min_access_level is developer' do
+ let(:params) { super().merge(shared_min_access_level: Gitlab::Access::DEVELOPER) }
+
+ it 'returns ancestor and shared groups with at least developer access' do
+ is_expected.to match_array([project_group, root_group, shared_group_with_dev_access])
+ end
+ end
+ end
+
+ context 'when skip group option is on' do
+ let(:params) { { skip_groups: [project_group.id] } }
+
+ it 'excludes provided groups' do
+ is_expected.to match_array([root_group])
+ end
+ end
+ end
+
+ context 'Public project' do
+ it_behaves_like 'finding related groups' do
+ let(:project) { public_project }
+
+ context 'when user is not authorized' do
+ let(:current_user) { nil }
+
+ it 'returns ancestor groups for this project' do
+ is_expected.to match_array([project_group, root_group])
+ end
+ end
+ end
+ end
+
+ context 'Private project' do
+ it_behaves_like 'finding related groups' do
+ let(:project) { private_project }
+
+ before do
+ project.add_developer(user)
+ end
+
+ context 'when user is not authorized' do
+ let(:current_user) { nil }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+ end
+
+ context 'Missing project' do
+ let(:project) { nil }
+
+ it { is_expected.to eq([]) }
+ end
+ end
+end
diff --git a/spec/finders/repositories/changelog_commits_finder_spec.rb b/spec/finders/repositories/changelog_commits_finder_spec.rb
new file mode 100644
index 00000000000..8665d36144a
--- /dev/null
+++ b/spec/finders/repositories/changelog_commits_finder_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Repositories::ChangelogCommitsFinder do
+ let_it_be(:project) { create(:project, :repository) }
+
+ describe '#each_page' do
+ it 'only yields commits with the given trailer' do
+ finder = described_class.new(
+ project: project,
+ from: '570e7b2abdd848b95f2f578043fc23bd6f6fd24d',
+ to: 'c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd'
+ )
+
+ commits = finder.each_page('Signed-off-by').to_a.flatten
+
+ expect(commits.length).to eq(1)
+ expect(commits.first.id).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
+ expect(commits.first.trailers).to eq(
+ 'Signed-off-by' => 'Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>'
+ )
+ end
+
+ it 'ignores commits that are reverted' do
+ # This range of commits is found on the branch
+ # https://gitlab.com/gitlab-org/gitlab-test/-/commits/trailers.
+ finder = described_class.new(
+ project: project,
+ from: 'ddd0f15ae83993f5cb66a927a28673882e99100b',
+ to: '694e6c2f08cad00d183682d9dede99615998a630'
+ )
+
+ commits = finder.each_page('Changelog').to_a.flatten
+
+ expect(commits).to be_empty
+ end
+
+ it 'includes revert commits if they have a trailer' do
+ finder = described_class.new(
+ project: project,
+ from: 'ddd0f15ae83993f5cb66a927a28673882e99100b',
+ to: 'f0a5ed60d24c98ec6d00ac010c1f3f01ee0a8373'
+ )
+
+ initial_commit = project.commit('ed2e92bf50b3da2c7cbbab053f4977a4ecbd109a')
+ revert_commit = project.commit('f0a5ed60d24c98ec6d00ac010c1f3f01ee0a8373')
+
+ commits = finder.each_page('Changelog').to_a.flatten
+
+ expect(commits).to eq([revert_commit, initial_commit])
+ end
+
+ it 'supports paginating of commits' do
+ finder = described_class.new(
+ project: project,
+ from: 'c1acaa58bbcbc3eafe538cb8274ba387047b69f8',
+ to: '5937ac0a7beb003549fc5fd26fc247adbce4a52e',
+ per_page: 1
+ )
+
+ commits = finder.each_page('Signed-off-by')
+
+ expect(commits.count).to eq(4)
+ end
+ end
+
+ describe '#revert_commit_sha' do
+ let(:finder) { described_class.new(project: project, from: 'a', to: 'b') }
+
+ it 'returns the SHA of a reverted commit' do
+ commit = double(
+ :commit,
+ description: 'This reverts commit 152c03af1b09f50fa4b567501032b106a3a81ff3.'
+ )
+
+ expect(finder.send(:revert_commit_sha, commit))
+ .to eq('152c03af1b09f50fa4b567501032b106a3a81ff3')
+ end
+
+ it 'returns nil when the commit is not a revert commit' do
+ commit = double(:commit, description: 'foo')
+
+ expect(finder.send(:revert_commit_sha, commit)).to be_nil
+ end
+
+ it 'returns nil when the commit has no description' do
+ commit = double(:commit, description: nil)
+
+ expect(finder.send(:revert_commit_sha, commit)).to be_nil
+ end
+ end
+end
diff --git a/spec/finders/repositories/commits_with_trailer_finder_spec.rb b/spec/finders/repositories/commits_with_trailer_finder_spec.rb
deleted file mode 100644
index 0c457aae340..00000000000
--- a/spec/finders/repositories/commits_with_trailer_finder_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Repositories::CommitsWithTrailerFinder do
- let(:project) { create(:project, :repository) }
-
- describe '#each_page' do
- it 'only yields commits with the given trailer' do
- finder = described_class.new(
- project: project,
- from: '570e7b2abdd848b95f2f578043fc23bd6f6fd24d',
- to: 'c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd'
- )
-
- commits = finder.each_page('Signed-off-by').to_a.flatten
-
- expect(commits.length).to eq(1)
- expect(commits.first.id).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
- expect(commits.first.trailers).to eq(
- 'Signed-off-by' => 'Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>'
- )
- end
-
- it 'supports paginating of commits' do
- finder = described_class.new(
- project: project,
- from: 'c1acaa58bbcbc3eafe538cb8274ba387047b69f8',
- to: '5937ac0a7beb003549fc5fd26fc247adbce4a52e',
- per_page: 1
- )
-
- commits = finder.each_page('Signed-off-by')
-
- expect(commits.count).to eq(4)
- end
- end
-end
diff --git a/spec/finders/repositories/previous_tag_finder_spec.rb b/spec/finders/repositories/previous_tag_finder_spec.rb
index 7cc33d11baf..b332dd158d1 100644
--- a/spec/finders/repositories/previous_tag_finder_spec.rb
+++ b/spec/finders/repositories/previous_tag_finder_spec.rb
@@ -12,16 +12,20 @@ RSpec.describe Repositories::PreviousTagFinder do
tag1 = double(:tag1, name: 'v1.0.0')
tag2 = double(:tag2, name: 'v1.1.0')
tag3 = double(:tag3, name: 'v2.0.0')
- tag4 = double(:tag4, name: '1.0.0')
+ tag4 = double(:tag4, name: '0.9.0')
+ tag5 = double(:tag5, name: 'v0.8.0-pre1')
+ tag6 = double(:tag6, name: 'v0.7.0')
allow(project.repository)
.to receive(:tags)
- .and_return([tag1, tag3, tag2, tag4])
+ .and_return([tag1, tag3, tag2, tag4, tag5, tag6])
expect(finder.execute('2.1.0')).to eq(tag3)
expect(finder.execute('2.0.0')).to eq(tag2)
expect(finder.execute('1.5.0')).to eq(tag2)
expect(finder.execute('1.0.1')).to eq(tag1)
+ expect(finder.execute('1.0.0')).to eq(tag4)
+ expect(finder.execute('0.9.0')).to eq(tag6)
end
end
diff --git a/spec/finders/security/license_compliance_jobs_finder_spec.rb b/spec/finders/security/license_compliance_jobs_finder_spec.rb
index 3066912df12..de4a7eb2c12 100644
--- a/spec/finders/security/license_compliance_jobs_finder_spec.rb
+++ b/spec/finders/security/license_compliance_jobs_finder_spec.rb
@@ -15,10 +15,9 @@ RSpec.describe Security::LicenseComplianceJobsFinder do
let!(:container_scanning_build) { create(:ci_build, :container_scanning, pipeline: pipeline) }
let!(:dast_build) { create(:ci_build, :dast, pipeline: pipeline) }
let!(:license_scanning_build) { create(:ci_build, :license_scanning, pipeline: pipeline) }
- let!(:license_management_build) { create(:ci_build, :license_management, pipeline: pipeline) }
- it 'returns only the license_scanning jobs' do
- is_expected.to contain_exactly(license_scanning_build, license_management_build)
+ it 'returns only the license_scanning job' do
+ is_expected.to contain_exactly(license_scanning_build)
end
end
end
diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb
index d9cc71106d5..b0f8b803141 100644
--- a/spec/finders/users_finder_spec.rb
+++ b/spec/finders/users_finder_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe UsersFinder do
it 'returns all users' do
users = described_class.new(user).execute
- expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, external_user, omniauth_user, internal_user, admin_user)
end
it 'filters by username' do
@@ -48,12 +48,18 @@ RSpec.describe UsersFinder do
it 'filters by active users' do
users = described_class.new(user, active: true).execute
- expect(users).to contain_exactly(user, normal_user, omniauth_user, admin_user)
+ expect(users).to contain_exactly(user, normal_user, external_user, omniauth_user, admin_user)
end
- it 'returns no external users' do
+ it 'filters by external users' do
users = described_class.new(user, external: true).execute
+ expect(users).to contain_exactly(external_user)
+ end
+
+ it 'filters by non external users' do
+ users = described_class.new(user, non_external: true).execute
+
expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user)
end
@@ -71,7 +77,7 @@ RSpec.describe UsersFinder do
it 'filters by non internal users' do
users = described_class.new(user, non_internal: true).execute
- expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, admin_user)
+ expect(users).to contain_exactly(user, normal_user, external_user, blocked_user, omniauth_user, admin_user)
end
it 'does not filter by custom attributes' do
@@ -80,18 +86,18 @@ RSpec.describe UsersFinder do
custom_attributes: { foo: 'bar' }
).execute
- expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user, admin_user)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, external_user, omniauth_user, internal_user, admin_user)
end
it 'orders returned results' do
users = described_class.new(user, sort: 'id_asc').execute
- expect(users).to eq([normal_user, admin_user, blocked_user, omniauth_user, internal_user, user])
+ expect(users).to eq([normal_user, admin_user, blocked_user, external_user, omniauth_user, internal_user, user])
end
it 'does not filter by admins' do
users = described_class.new(user, admins: true).execute
- expect(users).to contain_exactly(user, normal_user, admin_user, blocked_user, omniauth_user, internal_user)
+ expect(users).to contain_exactly(user, normal_user, external_user, admin_user, blocked_user, omniauth_user, internal_user)
end
end