summaryrefslogtreecommitdiff
path: root/spec/finders
diff options
context:
space:
mode:
Diffstat (limited to 'spec/finders')
-rw-r--r--spec/finders/alert_management/alerts_finder_spec.rb78
-rw-r--r--spec/finders/branches_finder_spec.rb263
-rw-r--r--spec/finders/ci/pipelines_finder_spec.rb4
-rw-r--r--spec/finders/ci/pipelines_for_merge_request_finder_spec.rb90
-rw-r--r--spec/finders/ci/runner_jobs_finder_spec.rb4
-rw-r--r--spec/finders/ci/variables_finder_spec.rb44
-rw-r--r--spec/finders/events_finder_spec.rb22
-rw-r--r--spec/finders/group_projects_finder_spec.rb44
-rw-r--r--spec/finders/merge_requests_finder_spec.rb39
-rw-r--r--spec/finders/notes_finder_spec.rb6
-rw-r--r--spec/finders/packages/conan/package_file_finder_spec.rb64
-rw-r--r--spec/finders/packages/conan/package_finder_spec.rb22
-rw-r--r--spec/finders/packages/go/module_finder_spec.rb71
-rw-r--r--spec/finders/packages/go/version_finder_spec.rb160
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb156
-rw-r--r--spec/finders/packages/maven/package_finder_spec.rb57
-rw-r--r--spec/finders/packages/npm/package_finder_spec.rb34
-rw-r--r--spec/finders/packages/nuget/package_finder_spec.rb75
-rw-r--r--spec/finders/packages/package_file_finder_spec.rb44
-rw-r--r--spec/finders/packages/package_finder_spec.rb25
-rw-r--r--spec/finders/packages/packages_finder_spec.rb90
-rw-r--r--spec/finders/packages/tags_finder_spec.rb68
-rw-r--r--spec/finders/personal_access_tokens_finder_spec.rb18
-rw-r--r--spec/finders/projects_finder_spec.rb11
-rw-r--r--spec/finders/resource_milestone_event_finder_spec.rb16
-rw-r--r--spec/finders/resource_state_event_finder_spec.rb76
-rw-r--r--spec/finders/snippets_finder_spec.rb22
-rw-r--r--spec/finders/todos_finder_spec.rb53
-rw-r--r--spec/finders/user_recent_events_finder_spec.rb16
29 files changed, 1498 insertions, 174 deletions
diff --git a/spec/finders/alert_management/alerts_finder_spec.rb b/spec/finders/alert_management/alerts_finder_spec.rb
index 5920d579ba6..7bf9047704b 100644
--- a/spec/finders/alert_management/alerts_finder_spec.rb
+++ b/spec/finders/alert_management/alerts_finder_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do
let(:params) { {} }
describe '#execute' do
- subject { described_class.new(current_user, project, params).execute }
+ subject(:execute) { described_class.new(current_user, project, params).execute }
context 'user is not a developer or above' do
it { is_expected.to be_empty }
@@ -144,81 +144,55 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do
end
context 'when sorting by severity' do
- let_it_be(:alert_critical) { create(:alert_management_alert, project: project, severity: :critical) }
- let_it_be(:alert_high) { create(:alert_management_alert, project: project, severity: :high) }
- let_it_be(:alert_medium) { create(:alert_management_alert, project: project, severity: :medium) }
- let_it_be(:alert_low) { create(:alert_management_alert, project: project, severity: :low) }
- let_it_be(:alert_info) { create(:alert_management_alert, project: project, severity: :info) }
- let_it_be(:alert_unknown) { create(:alert_management_alert, project: project, severity: :unknown) }
-
- context 'sorts alerts ascending' do
+ let_it_be(:alert_critical) { create(:alert_management_alert, :critical, project: project) }
+ let_it_be(:alert_high) { create(:alert_management_alert, :high, project: project) }
+ let_it_be(:alert_medium) { create(:alert_management_alert, :medium, project: project) }
+ let_it_be(:alert_low) { create(:alert_management_alert, :low, project: project) }
+ let_it_be(:alert_info) { create(:alert_management_alert, :info, project: project) }
+ let_it_be(:alert_unknown) { create(:alert_management_alert, :unknown, project: project) }
+
+ context 'with ascending sort order' do
let(:params) { { sort: 'severity_asc' } }
- it do
- is_expected.to eq [
- alert_2,
- alert_critical,
- alert_1,
- alert_high,
- alert_medium,
- alert_low,
- alert_info,
- alert_unknown
- ]
+ it 'sorts alerts by severity from less critical to more critical' do
+ expect(execute.pluck(:severity).uniq).to eq(%w(unknown info low medium high critical))
end
end
- context 'sorts alerts descending' do
+ context 'with descending sort order' do
let(:params) { { sort: 'severity_desc' } }
- it do
- is_expected.to eq [
- alert_unknown,
- alert_info,
- alert_low,
- alert_medium,
- alert_1,
- alert_high,
- alert_critical,
- alert_2
- ]
+ it 'sorts alerts by severity from more critical to less critical' do
+ expect(execute.pluck(:severity).uniq).to eq(%w(critical high medium low info unknown))
end
end
end
context 'when sorting by status' do
+ let(:statuses) { AlertManagement::Alert::STATUSES }
+ let(:triggered) { statuses[:triggered] }
+ let(:acknowledged) { statuses[:acknowledged] }
+ let(:resolved) { statuses[:resolved] }
+ let(:ignored) { statuses[:ignored] }
+
let_it_be(:alert_triggered) { create(:alert_management_alert, project: project) }
let_it_be(:alert_acknowledged) { create(:alert_management_alert, :acknowledged, project: project) }
let_it_be(:alert_resolved) { create(:alert_management_alert, :resolved, project: project) }
let_it_be(:alert_ignored) { create(:alert_management_alert, :ignored, project: project) }
- context 'sorts alerts ascending' do
+ context 'with ascending sort order' do
let(:params) { { sort: 'status_asc' } }
- it do
- is_expected.to eq [
- alert_triggered,
- alert_acknowledged,
- alert_1,
- alert_resolved,
- alert_2,
- alert_ignored
- ]
+ it 'sorts by status: Ignored > Resolved > Acknowledged > Triggered' do
+ expect(execute.map(&:status).uniq).to eq([ignored, resolved, acknowledged, triggered])
end
end
- context 'sorts alerts descending' do
+ context 'with descending sort order' do
let(:params) { { sort: 'status_desc' } }
- it do
- is_expected.to eq [
- alert_2,
- alert_ignored,
- alert_1,
- alert_resolved,
- alert_acknowledged,
- alert_triggered
- ]
+ it 'sorts by status: Triggered > Acknowledged > Resolved > Ignored' do
+ expect(execute.map(&:status).uniq).to eq([triggered, acknowledged, resolved, ignored])
end
end
end
diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb
index 2e52093342d..a62dd3842db 100644
--- a/spec/finders/branches_finder_spec.rb
+++ b/spec/finders/branches_finder_spec.rb
@@ -7,142 +7,255 @@ RSpec.describe BranchesFinder do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
+ let(:branch_finder) { described_class.new(repository, params) }
+ let(:params) { {} }
+
describe '#execute' do
+ subject { branch_finder.execute }
+
context 'sort only' do
- it 'sorts by name' do
- branches_finder = described_class.new(repository, {})
+ context 'by name' do
+ let(:params) { {} }
- result = branches_finder.execute
+ it 'sorts' do
+ result = subject
- expect(result.first.name).to eq("'test'")
+ expect(result.first.name).to eq("'test'")
+ end
end
- it 'sorts by recently_updated' do
- branches_finder = described_class.new(repository, { sort: 'updated_desc' })
+ context 'by recently_updated' do
+ let(:params) { { sort: 'updated_desc' } }
- result = branches_finder.execute
+ it 'sorts' do
+ result = subject
- recently_updated_branch = repository.branches.max do |a, b|
- repository.commit(a.dereferenced_target).committed_date <=> repository.commit(b.dereferenced_target).committed_date
- end
+ recently_updated_branch = repository.branches.max do |a, b|
+ repository.commit(a.dereferenced_target).committed_date <=> repository.commit(b.dereferenced_target).committed_date
+ end
- expect(result.first.name).to eq(recently_updated_branch.name)
+ expect(result.first.name).to eq(recently_updated_branch.name)
+ end
end
- it 'sorts by last_updated' do
- branches_finder = described_class.new(repository, { sort: 'updated_asc' })
+ context 'by last_updated' do
+ let(:params) { { sort: 'updated_asc' } }
- result = branches_finder.execute
+ it 'sorts' do
+ result = subject
- expect(result.first.name).to eq('feature')
+ expect(result.first.name).to eq('feature')
+ end
end
end
context 'filter only' do
- it 'filters branches by name' do
- branches_finder = described_class.new(repository, { search: 'fix' })
+ context 'by name' do
+ let(:params) { { search: 'fix' } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.first.name).to eq('fix')
- expect(result.count).to eq(1)
+ expect(result.first.name).to eq('fix')
+ expect(result.count).to eq(1)
+ end
end
- it 'filters branches by name ignoring letter case' do
- branches_finder = described_class.new(repository, { search: 'FiX' })
+ context 'by name ignoring letter case' do
+ let(:params) { { search: 'FiX' } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.first.name).to eq('fix')
- expect(result.count).to eq(1)
+ expect(result.first.name).to eq('fix')
+ expect(result.count).to eq(1)
+ end
end
- it 'does not find any branch with that name' do
- branches_finder = described_class.new(repository, { search: 'random' })
+ context 'with an unknown name' do
+ let(:params) { { search: 'random' } }
- result = branches_finder.execute
+ it 'does not find any branch' do
+ result = subject
- expect(result.count).to eq(0)
+ expect(result.count).to eq(0)
+ end
end
- it 'filters branches by provided names' do
- branches_finder = described_class.new(repository, { names: %w[fix csv lfs does-not-exist] })
+ context 'by provided names' do
+ let(:params) { { names: %w[fix csv lfs does-not-exist] } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.count).to eq(3)
- expect(result.map(&:name)).to eq(%w{csv fix lfs})
+ expect(result.count).to eq(3)
+ expect(result.map(&:name)).to eq(%w{csv fix lfs})
+ end
end
- it 'filters branches by name that begins with' do
- params = { search: '^feature_' }
- branches_finder = described_class.new(repository, params)
+ context 'by name that begins with' do
+ let(:params) { { search: '^feature_' } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.first.name).to eq('feature_conflict')
- expect(result.count).to eq(1)
+ expect(result.first.name).to eq('feature_conflict')
+ expect(result.count).to eq(1)
+ end
end
- it 'filters branches by name that ends with' do
- params = { search: 'feature$' }
- branches_finder = described_class.new(repository, params)
+ context 'by name that ends with' do
+ let(:params) { { search: 'feature$' } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.first.name).to eq('feature')
- expect(result.count).to eq(1)
+ expect(result.first.name).to eq('feature')
+ expect(result.count).to eq(1)
+ end
end
- it 'filters branches by nonexistent name that begins with' do
- params = { search: '^nope' }
- branches_finder = described_class.new(repository, params)
+ context 'by nonexistent name that begins with' do
+ let(:params) { { search: '^nope' } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.count).to eq(0)
+ expect(result.count).to eq(0)
+ end
end
- it 'filters branches by nonexistent name that ends with' do
- params = { search: 'nope$' }
- branches_finder = described_class.new(repository, params)
+ context 'by nonexistent name that ends with' do
+ let(:params) { { search: 'nope$' } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.count).to eq(0)
+ expect(result.count).to eq(0)
+ end
end
end
context 'filter and sort' do
- it 'filters branches by name and sorts by recently_updated' do
- params = { sort: 'updated_desc', search: 'feat' }
- branches_finder = described_class.new(repository, params)
+ context 'by name and sorts by recently_updated' do
+ let(:params) { { sort: 'updated_desc', search: 'feat' } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.first.name).to eq('feature_conflict')
+ expect(result.count).to eq(2)
+ end
+ end
+
+ context 'by name and sorts by recently_updated, with exact matches first' do
+ let(:params) { { sort: 'updated_desc', search: 'feature' } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.first.name).to eq('feature')
+ expect(result.second.name).to eq('feature_conflict')
+ expect(result.count).to eq(2)
+ end
+ end
+
+ context 'by name and sorts by last_updated' do
+ let(:params) { { sort: 'updated_asc', search: 'feature' } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.first.name).to eq('feature')
+ expect(result.count).to eq(2)
+ end
+ end
+ end
- result = branches_finder.execute
+ context 'with gitaly pagination' do
+ subject { branch_finder.execute(gitaly_pagination: true) }
- expect(result.first.name).to eq('feature_conflict')
- expect(result.count).to eq(2)
+ context 'by page_token and per_page' do
+ let(:params) { { page_token: 'feature', per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(feature_conflict fix))
+ end
end
- it 'filters branches by name and sorts by recently_updated, with exact matches first' do
- params = { sort: 'updated_desc', search: 'feature' }
- branches_finder = described_class.new(repository, params)
+ context 'by next page_token and per_page' do
+ let(:params) { { page_token: 'fix', per_page: 2 } }
- result = branches_finder.execute
+ it 'filters branches' do
+ result = subject
- expect(result.first.name).to eq('feature')
- expect(result.second.name).to eq('feature_conflict')
- expect(result.count).to eq(2)
+ expect(result.map(&:name)).to eq(%w(flatten-dir gitattributes))
+ end
end
- it 'filters branches by name and sorts by last_updated' do
- params = { sort: 'updated_asc', search: 'feature' }
- branches_finder = described_class.new(repository, params)
+ context 'by per_page only' do
+ let(:params) { { per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(["'test'", '2-mb-file'])
+ end
+ end
- result = branches_finder.execute
+ context 'by page_token only' do
+ let(:params) { { page_token: 'feature' } }
- expect(result.first.name).to eq('feature')
- expect(result.count).to eq(2)
+ it 'returns nothing' do
+ result = subject
+
+ expect(result.count).to eq(0)
+ end
+ end
+
+ context 'pagination and sort' do
+ context 'by per_page' do
+ let(:params) { { sort: 'updated_asc', per_page: 5 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(feature improve/awesome merge-test markdown feature_conflict))
+ end
+ end
+
+ context 'by page_token and per_page' do
+ let(:params) { { sort: 'updated_asc', page_token: 'improve/awesome', per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(merge-test markdown))
+ end
+ end
+ end
+
+ context 'pagination and names' do
+ let(:params) { { page_token: 'fix', per_page: 2, names: %w[fix csv lfs does-not-exist] } }
+
+ it 'falls back to default execute and ignore paginations' do
+ result = subject
+
+ expect(result.count).to eq(3)
+ expect(result.map(&:name)).to eq(%w{csv fix lfs})
+ end
+ end
+
+ context 'pagination and search' do
+ let(:params) { { page_token: 'feature', per_page: 2, search: '^f' } }
+
+ it 'falls back to default execute and ignore paginations' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(feature feature_conflict fix flatten-dir))
+ end
end
end
end
diff --git a/spec/finders/ci/pipelines_finder_spec.rb b/spec/finders/ci/pipelines_finder_spec.rb
index 680955ff9f9..a2a714689ba 100644
--- a/spec/finders/ci/pipelines_finder_spec.rb
+++ b/spec/finders/ci/pipelines_finder_spec.rb
@@ -77,13 +77,13 @@ RSpec.describe Ci::PipelinesFinder do
end
end
- HasStatus::AVAILABLE_STATUSES.each do |target|
+ Ci::HasStatus::AVAILABLE_STATUSES.each do |target|
context "when status is #{target}" do
let(:params) { { status: target } }
let!(:pipeline) { create(:ci_pipeline, project: project, status: target) }
before do
- exception_status = HasStatus::AVAILABLE_STATUSES - [target]
+ exception_status = Ci::HasStatus::AVAILABLE_STATUSES - [target]
create(:ci_pipeline, project: project, status: exception_status.first)
end
diff --git a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
index 543c289d366..ca6e0793d55 100644
--- a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
+++ b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
@@ -3,11 +3,97 @@
require 'spec_helper'
RSpec.describe Ci::PipelinesForMergeRequestFinder do
+ describe '#execute' do
+ include ProjectForksHelper
+
+ subject { finder.execute }
+
+ let_it_be(:developer_in_parent) { create(:user) }
+ let_it_be(:developer_in_fork) { create(:user) }
+ let_it_be(:developer_in_both) { create(:user) }
+ let_it_be(:reporter_in_parent_and_developer_in_fork) { create(:user) }
+ let_it_be(:external_user) { create(:user) }
+ let_it_be(:parent_project) { create(:project, :repository, :private) }
+ let_it_be(:forked_project) { fork_project(parent_project, nil, repository: true, target_project: create(:project, :private, :repository)) }
+
+ let(:merge_request) do
+ create(:merge_request, source_project: forked_project, source_branch: 'feature',
+ target_project: parent_project, target_branch: 'master')
+ end
+
+ let!(:pipeline_in_parent) do
+ create(:ci_pipeline, :merged_result_pipeline, merge_request: merge_request, project: parent_project)
+ end
+
+ let!(:pipeline_in_fork) do
+ create(:ci_pipeline, :merged_result_pipeline, merge_request: merge_request, project: forked_project)
+ end
+
+ let(:finder) { described_class.new(merge_request, actor) }
+
+ before_all do
+ parent_project.add_developer(developer_in_parent)
+ parent_project.add_developer(developer_in_both)
+ parent_project.add_reporter(reporter_in_parent_and_developer_in_fork)
+ forked_project.add_developer(developer_in_fork)
+ forked_project.add_developer(developer_in_both)
+ forked_project.add_developer(reporter_in_parent_and_developer_in_fork)
+ end
+
+ context 'when actor has permission to read pipelines in both parent and forked projects' do
+ let(:actor) { developer_in_both }
+
+ it 'returns all pipelines' do
+ is_expected.to eq([pipeline_in_fork, pipeline_in_parent])
+ end
+ end
+
+ context 'when actor has permission to read pipelines in both parent and forked projects' do
+ let(:actor) { reporter_in_parent_and_developer_in_fork }
+
+ it 'returns all pipelines' do
+ is_expected.to eq([pipeline_in_fork, pipeline_in_parent])
+ end
+ end
+
+ context 'when actor has permission to read pipelines in the parent project only' do
+ let(:actor) { developer_in_parent }
+
+ it 'returns pipelines in parent' do
+ is_expected.to eq([pipeline_in_parent])
+ end
+ end
+
+ context 'when actor has permission to read pipelines in the forked project only' do
+ let(:actor) { developer_in_fork }
+
+ it 'returns pipelines in fork' do
+ is_expected.to eq([pipeline_in_fork])
+ end
+ end
+
+ context 'when actor does not have permission to read pipelines' do
+ let(:actor) { external_user }
+
+ it 'returns nothing' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when actor is nil' do
+ let(:actor) { nil }
+
+ it 'returns nothing' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
describe '#all' do
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.source_project }
- subject { described_class.new(merge_request) }
+ subject { described_class.new(merge_request, nil) }
shared_examples 'returning pipelines with proper ordering' do
let!(:all_pipelines) do
@@ -134,7 +220,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
branch_pipeline_2,
branch_pipeline])
- expect(described_class.new(merge_request_2).all)
+ expect(described_class.new(merge_request_2, nil).all)
.to eq([detached_merge_request_pipeline_2,
branch_pipeline_2,
branch_pipeline])
diff --git a/spec/finders/ci/runner_jobs_finder_spec.rb b/spec/finders/ci/runner_jobs_finder_spec.rb
index 7c9f762c000..3569582d70f 100644
--- a/spec/finders/ci/runner_jobs_finder_spec.rb
+++ b/spec/finders/ci/runner_jobs_finder_spec.rb
@@ -21,13 +21,13 @@ RSpec.describe Ci::RunnerJobsFinder do
end
context 'when params contains status' do
- HasStatus::AVAILABLE_STATUSES.each do |target_status|
+ Ci::HasStatus::AVAILABLE_STATUSES.each do |target_status|
context "when status is #{target_status}" do
let(:params) { { status: target_status } }
let!(:job) { create(:ci_build, runner: runner, project: project, status: target_status) }
before do
- exception_status = HasStatus::AVAILABLE_STATUSES - [target_status]
+ exception_status = Ci::HasStatus::AVAILABLE_STATUSES - [target_status]
create(:ci_build, runner: runner, project: project, status: exception_status.first)
end
diff --git a/spec/finders/ci/variables_finder_spec.rb b/spec/finders/ci/variables_finder_spec.rb
new file mode 100644
index 00000000000..cd5f950ca8e
--- /dev/null
+++ b/spec/finders/ci/variables_finder_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::VariablesFinder do
+ let!(:project) { create(:project) }
+ let!(:params) { {} }
+
+ let!(:var1) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'staging') }
+ let!(:var2) { create(:ci_variable, project: project, key: 'key2', environment_scope: 'staging') }
+ let!(:var3) { create(:ci_variable, project: project, key: 'key2', environment_scope: 'production') }
+
+ describe '#initialize' do
+ subject { described_class.new(project, params) }
+
+ context 'without key filter' do
+ let!(:params) { {} }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ArgumentError, 'Please provide params[:key]')
+ end
+ end
+ end
+
+ describe '#execute' do
+ subject { described_class.new(project.reload, params).execute }
+
+ context 'with key filter' do
+ let!(:params) { { key: 'key1' } }
+
+ it 'returns var1' do
+ expect(subject).to contain_exactly(var1)
+ end
+ end
+
+ context 'with key and environment_scope filter' do
+ let!(:params) { { key: 'key2', filter: { environment_scope: 'staging' } } }
+
+ it 'returns var2' do
+ expect(subject).to contain_exactly(var2)
+ end
+ end
+ end
+end
diff --git a/spec/finders/events_finder_spec.rb b/spec/finders/events_finder_spec.rb
index b13ef7e94e7..fe2e449f03d 100644
--- a/spec/finders/events_finder_spec.rb
+++ b/spec/finders/events_finder_spec.rb
@@ -66,29 +66,13 @@ RSpec.describe EventsFinder do
end
end
- describe 'wiki events feature flag' do
+ describe 'wiki events' do
let_it_be(:events) { create_list(:wiki_page_event, 3, project: public_project) }
subject(:finder) { described_class.new(source: public_project, target_type: 'wiki', current_user: user) }
- context 'the wiki_events feature flag is disabled' do
- before do
- stub_feature_flags(wiki_events: false)
- end
-
- it 'omits the wiki page events' do
- expect(finder.execute).to be_empty
- end
- end
-
- context 'the wiki_events feature flag is enabled' do
- before do
- stub_feature_flags(wiki_events: true)
- end
-
- it 'can find the wiki events' do
- expect(finder.execute).to match_array(events)
- end
+ it 'can find the wiki events' do
+ expect(finder.execute).to match_array(events)
end
end
diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb
index 7499461ad8f..14f2bb017c6 100644
--- a/spec/finders/group_projects_finder_spec.rb
+++ b/spec/finders/group_projects_finder_spec.rb
@@ -46,6 +46,18 @@ RSpec.describe GroupProjectsFinder do
context 'without subgroups projects' do
it { is_expected.to match_array([shared_project_3, shared_project_2, shared_project_1, private_project, public_project]) }
end
+
+ context "with min access level" do
+ let!(:shared_project_4) { create(:project, :internal, path: '8') }
+
+ before do
+ shared_project_4.project_group_links.create(group_access: Gitlab::Access::REPORTER, group: group)
+ end
+
+ let(:params) { { min_access_level: Gitlab::Access::MAINTAINER } }
+
+ it { is_expected.to match_array([shared_project_3, shared_project_2, shared_project_1, private_project, public_project]) }
+ end
end
end
@@ -171,6 +183,38 @@ RSpec.describe GroupProjectsFinder do
end
end
+ describe 'feature availability' do
+ let!(:project_with_issues_disabled) { create(:project, :issues_disabled, :internal, path: '9') }
+ let!(:project_with_merge_request_disabled) { create(:project, :merge_requests_disabled, :internal, path: '10') }
+
+ before do
+ project_with_issues_disabled.project_group_links.create!(group_access: Gitlab::Access::REPORTER, group: group)
+ project_with_merge_request_disabled.project_group_links.create!(group_access: Gitlab::Access::REPORTER, group: group)
+ end
+
+ context 'without issues and merge request enabled' do
+ it { is_expected.to match_array([public_project, shared_project_1, shared_project_3, project_with_issues_disabled, project_with_merge_request_disabled]) }
+ end
+
+ context 'with issues enabled' do
+ let(:params) { { with_issues_enabled: true } }
+
+ it { is_expected.to match_array([public_project, shared_project_1, shared_project_3, project_with_merge_request_disabled]) }
+ end
+
+ context 'with merge request enabled' do
+ let(:params) { { with_merge_requests_enabled: true } }
+
+ it { is_expected.to match_array([public_project, shared_project_1, shared_project_3, project_with_issues_disabled]) }
+ end
+
+ context 'with issues and merge request enabled' do
+ let(:params) { { with_merge_requests_enabled: true, with_issues_enabled: true } }
+
+ it { is_expected.to match_array([public_project, shared_project_1, shared_project_3]) }
+ end
+ end
+
describe 'limiting' do
context 'without limiting' do
it 'returns all projects' do
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index f76110e3d85..e3643698012 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -53,6 +53,21 @@ RSpec.describe MergeRequestsFinder do
expect(merge_requests).to be_empty
end
+ 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
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request4, merge_request5)
+ end
+ end
+
it 'filters by projects' do
params = { projects: [project2.id, project3.id] }
@@ -258,6 +273,11 @@ RSpec.describe MergeRequestsFinder do
let(:expected_issuables) { [merge_request1, merge_request2] }
end
+ it_behaves_like 'assignee NOT ID filter' do
+ let(:params) { { not: { assignee_id: user.id } } }
+ let(:expected_issuables) { [merge_request3, merge_request4, merge_request5] }
+ end
+
it_behaves_like 'assignee username filter' do
before do
project2.add_developer(user3)
@@ -269,6 +289,15 @@ RSpec.describe MergeRequestsFinder do
let(:expected_issuables) { [merge_request3] }
end
+ it_behaves_like 'assignee NOT username filter' do
+ before do
+ merge_request2.assignees = [user2]
+ end
+
+ let(:params) { { not: { assignee_username: [user.username, user2.username] } } }
+ let(:expected_issuables) { [merge_request4, merge_request5] }
+ end
+
it_behaves_like 'no assignee filter' do
let_it_be(:user3) { create(:user) }
let(:expected_issuables) { [merge_request4, merge_request5] }
@@ -294,6 +323,16 @@ RSpec.describe MergeRequestsFinder do
expect(merge_requests).to contain_exactly(merge_request2, merge_request3)
end
+
+ context 'using NOT' do
+ let(:params) { { not: { milestone_title: group_milestone.title } } }
+
+ it 'returns MRs not assigned to that group milestone' do
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request4, merge_request5)
+ end
+ end
end
end
diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb
index 5610f5889e6..868b126dc28 100644
--- a/spec/finders/notes_finder_spec.rb
+++ b/spec/finders/notes_finder_spec.rb
@@ -123,7 +123,7 @@ RSpec.describe NotesFinder do
let!(:note1) { create :note_on_commit, project: project }
let!(:note2) { create :note_on_commit, project: project }
let(:commit) { note1.noteable }
- let(:params) { { project: project, target_id: commit.id, target_type: 'commit', last_fetched_at: 1.hour.ago.to_i } }
+ let(:params) { { project: project, target_id: commit.id, target_type: 'commit', last_fetched_at: 1.hour.ago } }
it 'finds all notes' do
notes = described_class.new(user, params).execute
@@ -172,7 +172,7 @@ RSpec.describe NotesFinder do
let(:confidential_issue) { create(:issue, :confidential, project: project, author: user) }
let!(:confidential_note) { create(:note, noteable: confidential_issue, project: confidential_issue.project) }
- let(:params) { { project: confidential_issue.project, target_id: confidential_issue.id, target_type: 'issue', last_fetched_at: 1.hour.ago.to_i } }
+ let(:params) { { project: confidential_issue.project, target_id: confidential_issue.id, target_type: 'issue', last_fetched_at: 1.hour.ago } }
it 'returns notes if user can see the issue' do
expect(described_class.new(user, params).execute).to eq([confidential_note])
@@ -204,7 +204,7 @@ RSpec.describe NotesFinder do
end
it 'returns the expected notes when last_fetched_at is given' do
- params = { project: project, target: commit, last_fetched_at: 1.hour.ago.to_i }
+ params = { project: project, target: commit, last_fetched_at: 1.hour.ago }
expect(described_class.new(user, params).execute).to eq([note2])
end
diff --git a/spec/finders/packages/conan/package_file_finder_spec.rb b/spec/finders/packages/conan/package_file_finder_spec.rb
new file mode 100644
index 00000000000..d0c9efa1418
--- /dev/null
+++ b/spec/finders/packages/conan/package_file_finder_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe ::Packages::Conan::PackageFileFinder do
+ let_it_be(:package) { create(:conan_package) }
+ let_it_be(:package_file) { package.package_files.first }
+ let(:package_file_name) { package_file.file_name }
+ let(:params) { {} }
+
+ RSpec.shared_examples 'package file finder examples' do
+ it { is_expected.to eq(package_file) }
+
+ context 'with conan_file_type' do
+ # conan packages contain a conanmanifest.txt file for both conan_file_types
+ let(:package_file_name) { 'conanmanifest.txt' }
+ let(:params) { { conan_file_type: :recipe_file } }
+
+ it { expect(subject.conan_file_type).to eq('recipe_file') }
+ end
+
+ context 'with conan_package_reference' do
+ let_it_be(:other_package) { create(:conan_package) }
+ let_it_be(:package_file_name) { 'conan_package.tgz' }
+ let_it_be(:package_file) { package.package_files.find_by(file_name: package_file_name) }
+
+ let(:params) do
+ { conan_package_reference: package_file.conan_file_metadatum.conan_package_reference }
+ end
+
+ it { expect(subject).to eq(package_file) }
+ end
+
+ context 'with file_name_like' do
+ let(:package_file_name) { package_file.file_name.upcase }
+ let(:params) { { with_file_name_like: true } }
+
+ it { is_expected.to eq(package_file) }
+ end
+ end
+
+ describe '#execute' do
+ subject { described_class.new(package, package_file_name, params).execute }
+
+ it_behaves_like 'package file finder examples'
+
+ context 'with unknown file_name' do
+ let(:package_file_name) { 'unknown.jpg' }
+
+ it { expect(subject).to be_nil }
+ end
+ end
+
+ describe '#execute!' do
+ subject { described_class.new(package, package_file_name, params).execute! }
+
+ it_behaves_like 'package file finder examples'
+
+ context 'with unknown file_name' do
+ let(:package_file_name) { 'unknown.jpg' }
+
+ it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
+ end
+ end
+end
diff --git a/spec/finders/packages/conan/package_finder_spec.rb b/spec/finders/packages/conan/package_finder_spec.rb
new file mode 100644
index 00000000000..936a0e5ff4b
--- /dev/null
+++ b/spec/finders/packages/conan/package_finder_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe ::Packages::Conan::PackageFinder do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+
+ describe '#execute' do
+ let!(:conan_package) { create(:conan_package, project: project) }
+ let!(:conan_package2) { create(:conan_package, project: project) }
+
+ subject { described_class.new(user, query: query).execute }
+
+ context 'packages that are not visible to user' do
+ let!(:non_visible_project) { create(:project, :private) }
+ let!(:non_visible_conan_package) { create(:conan_package, project: non_visible_project) }
+ let(:query) { "#{conan_package.name.split('/').first[0, 3]}%" }
+
+ it { is_expected.to eq [conan_package, conan_package2] }
+ end
+ end
+end
diff --git a/spec/finders/packages/go/module_finder_spec.rb b/spec/finders/packages/go/module_finder_spec.rb
new file mode 100644
index 00000000000..e5c8827fc8d
--- /dev/null
+++ b/spec/finders/packages/go/module_finder_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Go::ModuleFinder do
+ let_it_be(:project) { create :project }
+ let_it_be(:other_project) { create :project }
+ let(:finder) { described_class.new project, module_name }
+
+ shared_examples 'an invalid path' do
+ describe '#module_name' do
+ it 'returns the expected name' do
+ expect(finder.module_name).to eq(expected_name)
+ end
+ end
+
+ describe '#execute' do
+ it 'returns nil' do
+ expect(finder.execute).to be_nil
+ end
+ end
+ end
+
+ describe '#execute' do
+ context 'with module name equal to project name' do
+ let(:module_name) { base_url(project) }
+
+ it 'returns a module with empty path' do
+ mod = finder.execute
+ expect(mod).not_to be_nil
+ expect(mod.path).to eq('')
+ end
+ end
+
+ context 'with module name starting with project name and slash' do
+ let(:module_name) { base_url(project) + '/mod' }
+
+ it 'returns a module with non-empty path' do
+ mod = finder.execute
+ expect(mod).not_to be_nil
+ expect(mod.path).to eq('mod')
+ end
+ end
+
+ context 'with a module name not equal to and not starting with project name' do
+ let(:module_name) { base_url(other_project) }
+
+ it 'returns nil' do
+ expect(finder.execute).to be_nil
+ end
+ end
+ end
+
+ context 'with relative path component' do
+ it_behaves_like 'an invalid path' do
+ let(:module_name) { base_url(project) + '/../xyz' }
+ let(:expected_name) { base_url(project.namespace) + '/xyz' }
+ end
+ end
+
+ context 'with many relative path components' do
+ it_behaves_like 'an invalid path' do
+ let(:module_name) { base_url(project) + ('/..' * 10) + '/xyz' }
+ let(:expected_name) { ('../' * 7) + 'xyz' }
+ end
+ end
+
+ def base_url(project)
+ "#{Settings.build_gitlab_go_url}/#{project.full_path}"
+ end
+end
diff --git a/spec/finders/packages/go/version_finder_spec.rb b/spec/finders/packages/go/version_finder_spec.rb
new file mode 100644
index 00000000000..b67842d1e05
--- /dev/null
+++ b/spec/finders/packages/go/version_finder_spec.rb
@@ -0,0 +1,160 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Go::VersionFinder do
+ let_it_be(:user) { create :user }
+ let_it_be(:project) { create :project_empty_repo, creator: user, path: 'my-go-lib' }
+
+ let(:finder) { described_class.new mod }
+
+ before :all do
+ create :go_module_commit, :files, project: project, tag: 'v1.0.0', files: { 'README.md' => 'Hi' }
+ create :go_module_commit, :module, project: project, tag: 'v1.0.1'
+ create :go_module_commit, :package, project: project, tag: 'v1.0.2', path: 'pkg'
+ create :go_module_commit, :module, project: project, tag: 'v1.0.3', name: 'mod'
+ create :go_module_commit, :module, project: project, tag: 'v1.0.4', name: 'bad-mod', url: 'example.com/go-lib'
+ create :go_module_commit, :files, project: project, tag: 'c1', files: { 'y.go' => "package a\n" }
+ create :go_module_commit, :module, project: project, tag: 'c2', name: 'v2'
+ create :go_module_commit, :files, project: project, tag: 'v2.0.0', files: { 'v2/x.go' => "package a\n" }
+ end
+
+ before do
+ stub_feature_flags(go_proxy_disable_gomod_validation: false)
+ end
+
+ shared_examples '#execute' do |*expected|
+ it "returns #{expected.empty? ? 'nothing' : expected.join(', ')}" do
+ actual = finder.execute.map { |x| x.name }
+ expect(actual.to_set).to eq(expected.to_set)
+ end
+ end
+
+ shared_examples '#find with an invalid argument' do |message|
+ it "raises an argument exception: #{message}" do
+ expect { finder.find(target) }.to raise_error(ArgumentError, message)
+ end
+ end
+
+ describe '#execute' do
+ context 'for the root module' do
+ let(:mod) { create :go_module, project: project }
+
+ it_behaves_like '#execute', 'v1.0.1', 'v1.0.2', 'v1.0.3', 'v1.0.4'
+ end
+
+ context 'for the package' do
+ let(:mod) { create :go_module, project: project, path: 'pkg' }
+
+ it_behaves_like '#execute'
+ end
+
+ context 'for the submodule' do
+ let(:mod) { create :go_module, project: project, path: 'mod' }
+
+ it_behaves_like '#execute', 'v1.0.3', 'v1.0.4'
+ end
+
+ context 'for the root module v2' do
+ let(:mod) { create :go_module, project: project, path: 'v2' }
+
+ it_behaves_like '#execute', 'v2.0.0'
+ end
+
+ context 'for the bad module' do
+ let(:mod) { create :go_module, project: project, path: 'bad-mod' }
+
+ context 'with gomod checking enabled' do
+ it_behaves_like '#execute'
+ end
+
+ context 'with gomod checking disabled' do
+ before do
+ stub_feature_flags(go_proxy_disable_gomod_validation: true)
+ end
+
+ it_behaves_like '#execute', 'v1.0.4'
+ end
+ end
+ end
+
+ describe '#find' do
+ let(:mod) { create :go_module, project: project }
+
+ context 'with a ref' do
+ it 'returns a ref version' do
+ ref = project.repository.find_branch 'master'
+ v = finder.find(ref)
+ expect(v.type).to eq(:ref)
+ expect(v.ref).to eq(ref)
+ end
+ end
+
+ context 'with a semver tag' do
+ it 'returns a version with a semver' do
+ v = finder.find(project.repository.find_tag('v1.0.0'))
+ expect(v.major).to eq(1)
+ expect(v.minor).to eq(0)
+ expect(v.patch).to eq(0)
+ expect(v.prerelease).to be_nil
+ expect(v.build).to be_nil
+ end
+ end
+
+ context 'with a semver tag string' do
+ it 'returns a version with a semver' do
+ v = finder.find('v1.0.1')
+ expect(v.major).to eq(1)
+ expect(v.minor).to eq(0)
+ expect(v.patch).to eq(1)
+ expect(v.prerelease).to be_nil
+ expect(v.build).to be_nil
+ end
+ end
+
+ context 'with a commit' do
+ it 'retruns a commit version' do
+ v = finder.find(project.repository.head_commit)
+ expect(v.type).to eq(:commit)
+ end
+ end
+
+ context 'with a pseudo-version' do
+ it 'returns a pseudo version' do
+ commit = project.repository.head_commit
+ pseudo = "v0.0.0-#{commit.committed_date.strftime('%Y%m%d%H%M%S')}-#{commit.sha[0..11]}"
+ v = finder.find(pseudo)
+ expect(v.type).to eq(:pseudo)
+ expect(v.commit).to eq(commit)
+ expect(v.name).to eq(pseudo)
+ end
+ end
+
+ context 'with a string that is not a semantic version' do
+ it 'returns nil' do
+ expect(finder.find('not-a-semver')).to be_nil
+ end
+ end
+
+ context 'with a pseudo-version that does not reference a commit' do
+ it_behaves_like '#find with an invalid argument', 'invalid pseudo-version: unknown commit' do
+ let(:commit) { project.repository.head_commit }
+ let(:target) { "v0.0.0-#{commit.committed_date.strftime('%Y%m%d%H%M%S')}-#{'0' * 12}" }
+ end
+ end
+
+ context 'with a pseudo-version with a short sha' do
+ it_behaves_like '#find with an invalid argument', 'invalid pseudo-version: revision is shorter than canonical' do
+ let(:commit) { project.repository.head_commit }
+ let(:target) { "v0.0.0-#{commit.committed_date.strftime('%Y%m%d%H%M%S')}-#{commit.sha[0..10]}" }
+ end
+ end
+
+ context 'with a pseudo-version with an invalid timestamp' do
+ it_behaves_like '#find with an invalid argument', 'invalid pseudo-version: does not match version-control timestamp' do
+ let(:commit) { project.repository.head_commit }
+ let(:target) { "v0.0.0-#{'0' * 14}-#{commit.sha[0..11]}" }
+ end
+ end
+ end
+end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
new file mode 100644
index 00000000000..163c920f621
--- /dev/null
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -0,0 +1,156 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::GroupPackagesFinder do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
+ let(:another_group) { create(:group) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ describe '#execute' do
+ let(:params) { { exclude_subgroups: false } }
+
+ subject { described_class.new(user, group, params).execute }
+
+ shared_examples 'with package type' do |package_type|
+ let(:params) { { exclude_subgroups: false, package_type: package_type } }
+
+ it { is_expected.to match_array([send("package_#{package_type}")]) }
+ end
+
+ def self.package_types
+ @package_types ||= Packages::Package.package_types.keys
+ end
+
+ context 'group has packages' do
+ let!(:package1) { create(:maven_package, project: project) }
+ let!(:package2) { create(:maven_package, project: project) }
+ let!(:package3) { create(:maven_package) }
+
+ it { is_expected.to match_array([package1, package2]) }
+
+ context 'subgroup has packages' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:subproject) { create(:project, namespace: subgroup) }
+ let!(:package4) { create(:npm_package, project: subproject) }
+
+ it { is_expected.to match_array([package1, package2, package4]) }
+
+ context 'excluding subgroups' do
+ let(:params) { { exclude_subgroups: true } }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+ end
+
+ context 'when there are processing packages' do
+ let!(:package4) { create(:nuget_package, project: project, name: Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+
+ context 'does not include packages without version number' do
+ let!(:package_without_version) { create(:maven_package, project: project, version: nil) }
+
+ it { is_expected.not_to include(package_without_version) }
+ end
+
+ context 'with package_name' do
+ let_it_be(:named_package) { create(:maven_package, project: project, name: 'maven') }
+ let(:params) { { package_name: package_name } }
+
+ context 'as complete name' do
+ let(:package_name) { 'maven' }
+
+ it { is_expected.to eq([named_package]) }
+ end
+
+ %w[aven mav ave].each do |filter|
+ context "for fuzzy filter #{filter}" do
+ let(:package_name) { filter }
+
+ it { is_expected.to eq([named_package]) }
+ end
+ end
+ end
+ end
+
+ context 'group has package of all types' do
+ package_types.each { |pt| let!("package_#{pt}") { create("#{pt}_package", project: project) } }
+
+ package_types.each do |package_type|
+ it_behaves_like 'with package type', package_type
+ end
+ end
+
+ context 'group has no packages' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'group is nil' do
+ subject { described_class.new(user, nil).execute }
+
+ it { is_expected.to be_empty}
+ end
+
+ context 'package type is nil' do
+ let!(:package1) { create(:maven_package, project: project) }
+
+ subject { described_class.new(user, group, package_type: nil).execute }
+
+ it { is_expected.to match_array([package1])}
+ end
+
+ context 'with invalid package_type' do
+ let(:params) { { package_type: 'invalid_type' } }
+
+ it { expect { subject }.to raise_exception(described_class::InvalidPackageTypeError) }
+ end
+
+ context 'when project is public' do
+ let_it_be(:other_user) { create(:user) }
+ let(:finder) { described_class.new(other_user, group) }
+
+ before do
+ project.update!(visibility_level: ProjectFeature::ENABLED)
+ end
+
+ context 'when packages are public' do
+ before do
+ project.project_feature.update!(
+ builds_access_level: ProjectFeature::PRIVATE,
+ merge_requests_access_level: ProjectFeature::PRIVATE,
+ repository_access_level: ProjectFeature::ENABLED)
+ end
+
+ it 'returns group packages' do
+ package1 = create(:maven_package, project: project)
+ package2 = create(:maven_package, project: project)
+ create(:maven_package)
+
+ expect(finder.execute).to match_array([package1, package2])
+ end
+ end
+
+ context 'packages are members only' do
+ before do
+ project.project_feature.update!(
+ builds_access_level: ProjectFeature::PRIVATE,
+ merge_requests_access_level: ProjectFeature::PRIVATE,
+ repository_access_level: ProjectFeature::PRIVATE)
+
+ create(:maven_package, project: project)
+ create(:maven_package)
+ end
+
+ it 'filters out the project if the user doesn\'t have permission' do
+ expect(finder.execute).to be_empty
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/packages/maven/package_finder_spec.rb b/spec/finders/packages/maven/package_finder_spec.rb
new file mode 100644
index 00000000000..239e8c10f52
--- /dev/null
+++ b/spec/finders/packages/maven/package_finder_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe ::Packages::Maven::PackageFinder do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, namespace: group) }
+ let(:package) { create(:maven_package, project: project) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ describe '#execute!' do
+ context 'within the project' do
+ it 'returns a package' do
+ finder = described_class.new(package.maven_metadatum.path, user, project: project)
+
+ expect(finder.execute!).to eq(package)
+ end
+
+ it 'raises an error' do
+ finder = described_class.new('com/example/my-app/1.0-SNAPSHOT', user, project: project)
+
+ expect { finder.execute! }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'across all projects' do
+ it 'returns a package' do
+ finder = described_class.new(package.maven_metadatum.path, user)
+
+ expect(finder.execute!).to eq(package)
+ end
+
+ it 'raises an error' do
+ finder = described_class.new('com/example/my-app/1.0-SNAPSHOT', user)
+
+ expect { finder.execute! }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'within a group' do
+ it 'returns a package' do
+ finder = described_class.new(package.maven_metadatum.path, user, group: group)
+
+ expect(finder.execute!).to eq(package)
+ end
+
+ it 'raises an error' do
+ finder = described_class.new('com/example/my-app/1.0-SNAPSHOT', user, group: group)
+
+ expect { finder.execute! }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+end
diff --git a/spec/finders/packages/npm/package_finder_spec.rb b/spec/finders/packages/npm/package_finder_spec.rb
new file mode 100644
index 00000000000..be54b1f8b18
--- /dev/null
+++ b/spec/finders/packages/npm/package_finder_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe ::Packages::Npm::PackageFinder do
+ let(:package) { create(:npm_package) }
+ let(:project) { package.project }
+ let(:package_name) { package.name }
+
+ describe '#execute!' do
+ subject { described_class.new(project, package_name).execute }
+
+ it { is_expected.to eq([package]) }
+
+ context 'with unknown package name' do
+ let(:package_name) { 'baz' }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ describe '#find_by_version' do
+ let(:version) { package.version }
+
+ subject { described_class.new(project, package.name).find_by_version(version) }
+
+ it { is_expected.to eq(package) }
+
+ context 'with unknown version' do
+ let(:version) { 'foobar' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+end
diff --git a/spec/finders/packages/nuget/package_finder_spec.rb b/spec/finders/packages/nuget/package_finder_spec.rb
new file mode 100644
index 00000000000..9295d0c7a2f
--- /dev/null
+++ b/spec/finders/packages/nuget/package_finder_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::Nuget::PackageFinder do
+ let_it_be(:package1) { create(:nuget_package) }
+ let_it_be(:project) { package1.project }
+ let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0', project: project) }
+ let_it_be(:package3) { create(:nuget_package, name: 'Another.Dummy.Package', project: project) }
+ let(:package_name) { package1.name }
+ let(:package_version) { nil }
+ let(:limit) { 50 }
+
+ describe '#execute!' do
+ subject { described_class.new(project, package_name: package_name, package_version: package_version, limit: limit).execute }
+
+ it { is_expected.to match_array([package1, package2]) }
+
+ context 'with lower case package name' do
+ let(:package_name) { package1.name.downcase }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+
+ context 'with unknown package name' do
+ let(:package_name) { 'foobar' }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'with valid version' do
+ let(:package_version) { '2.0.0' }
+
+ it { is_expected.to match_array([package2]) }
+ end
+
+ context 'with unknown version' do
+ let(:package_version) { 'foobar' }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'with limit hit' do
+ let_it_be(:package4) { create(:nuget_package, name: package1.name, project: project) }
+ let_it_be(:package5) { create(:nuget_package, name: package1.name, project: project) }
+ let_it_be(:package6) { create(:nuget_package, name: package1.name, project: project) }
+ let(:limit) { 2 }
+
+ it { is_expected.to match_array([package5, package6]) }
+ end
+
+ context 'with downcase package name' do
+ let(:package_name) { package1.name.downcase }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+
+ context 'with prefix wildcard' do
+ let(:package_name) { "%#{package1.name[3..-1]}" }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+
+ context 'with suffix wildcard' do
+ let(:package_name) { "#{package1.name[0..-3]}%" }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+
+ context 'with surrounding wildcards' do
+ let(:package_name) { "%#{package1.name[3..-3]}%" }
+
+ it { is_expected.to match_array([package1, package2]) }
+ end
+ end
+end
diff --git a/spec/finders/packages/package_file_finder_spec.rb b/spec/finders/packages/package_file_finder_spec.rb
new file mode 100644
index 00000000000..ab58f75fcae
--- /dev/null
+++ b/spec/finders/packages/package_file_finder_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::PackageFileFinder do
+ let_it_be(:package) { create(:maven_package) }
+ let_it_be(:package_file) { package.package_files.first }
+ let(:package_file_name) { package_file.file_name }
+ let(:params) { {} }
+
+ RSpec.shared_examples 'package file finder examples' do
+ it { is_expected.to eq(package_file) }
+
+ context 'with file_name_like' do
+ let(:package_file_name) { package_file.file_name.upcase }
+ let(:params) { { with_file_name_like: true } }
+
+ it { is_expected.to eq(package_file) }
+ end
+ end
+
+ describe '#execute' do
+ subject { described_class.new(package, package_file_name, params).execute }
+
+ it_behaves_like 'package file finder examples'
+
+ context 'with unknown file_name' do
+ let(:package_file_name) { 'unknown.jpg' }
+
+ it { expect(subject).to be_nil }
+ end
+ end
+
+ describe '#execute!' do
+ subject { described_class.new(package, package_file_name, params).execute! }
+
+ it_behaves_like 'package file finder examples'
+
+ context 'with unknown file_name' do
+ let(:package_file_name) { 'unknown.jpg' }
+
+ it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
+ end
+ end
+end
diff --git a/spec/finders/packages/package_finder_spec.rb b/spec/finders/packages/package_finder_spec.rb
new file mode 100644
index 00000000000..ef07e7575d1
--- /dev/null
+++ b/spec/finders/packages/package_finder_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Packages::PackageFinder do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:maven_package) { create(:maven_package, project: project) }
+
+ describe '#execute' do
+ let(:package_id) { maven_package.id }
+
+ subject { described_class.new(project, package_id).execute }
+
+ 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(:package_id) { nuget_package.id }
+
+ it 'are not returned' do
+ expect { subject }.to raise_exception(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+end
diff --git a/spec/finders/packages/packages_finder_spec.rb b/spec/finders/packages/packages_finder_spec.rb
new file mode 100644
index 00000000000..925b003bb8e
--- /dev/null
+++ b/spec/finders/packages/packages_finder_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Packages::PackagesFinder do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:maven_package) { create(:maven_package, project: project, created_at: 2.days.ago, name: 'maven', version: '2.0.0') }
+ let_it_be(:conan_package) { create(:conan_package, project: project, created_at: 1.day.ago, name: 'conan', version: '1.0.0') }
+
+ describe '#execute' do
+ let(:params) { {} }
+
+ subject { described_class.new(project, params).execute }
+
+ context 'with package_type' do
+ let_it_be(:npm_package1) { create(:npm_package, project: project) }
+ let_it_be(:npm_package2) { create(:npm_package, project: project) }
+
+ context 'conan packages' do
+ let(:params) { { package_type: 'conan' } }
+
+ it { is_expected.to eq([conan_package]) }
+ end
+
+ context 'npm packages' do
+ let(:params) { { package_type: 'npm' } }
+
+ it { is_expected.to match_array([npm_package1, npm_package2]) }
+ end
+ end
+
+ context 'with order_by' do
+ context 'by default is created_at' do
+ it { is_expected.to eq([maven_package, conan_package]) }
+ end
+
+ context 'order by name' do
+ let(:params) { { order_by: 'name' } }
+
+ it { is_expected.to eq([conan_package, maven_package]) }
+ end
+
+ context 'order by version' do
+ let(:params) { { order_by: 'version' } }
+
+ it { is_expected.to eq([conan_package, maven_package]) }
+ end
+
+ context 'order by type' do
+ let(:params) { { order_by: 'type' } }
+
+ it { is_expected.to eq([maven_package, conan_package]) }
+ end
+ end
+
+ context 'with sort' do
+ context 'by default is ascending' do
+ it { is_expected.to eq([maven_package, conan_package]) }
+ end
+
+ context 'can sort descended' do
+ let(:params) { { sort: 'desc' } }
+
+ it { is_expected.to eq([conan_package, maven_package]) }
+ end
+ end
+
+ context 'with package_name' do
+ let(:params) { { package_name: 'maven' } }
+
+ it { is_expected.to eq([maven_package]) }
+ end
+
+ context 'with nil params' do
+ it { is_expected.to match_array([conan_package, maven_package]) }
+ end
+
+ context 'with processing packages' do
+ let_it_be(:nuget_package) { create(:nuget_package, project: project, name: Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) }
+
+ it { is_expected.to match_array([conan_package, maven_package]) }
+ end
+
+ context 'does not include packages without version number' do
+ let_it_be(:package_without_version) { create(:maven_package, project: project, version: nil) }
+
+ it { is_expected.not_to include(package_without_version) }
+ end
+ end
+end
diff --git a/spec/finders/packages/tags_finder_spec.rb b/spec/finders/packages/tags_finder_spec.rb
new file mode 100644
index 00000000000..47e1d25debf
--- /dev/null
+++ b/spec/finders/packages/tags_finder_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Packages::TagsFinder do
+ let(:package) { create(:npm_package) }
+ let(:project) { package.project }
+ let!(:tag1) { create(:packages_tag, package: package) }
+ let!(:tag2) { create(:packages_tag, package: package) }
+ let(:package_name) { package.name }
+ let(:params) { {} }
+
+ describe '#execute' do
+ subject { described_class.new(project, package_name, params).execute }
+
+ it { is_expected.to match_array([tag1, tag2]) }
+
+ context 'with package type' do
+ let(:package_maven) { create(:maven_package, project: project) }
+ let!(:tag_maven) { create(:packages_tag, package: package_maven) }
+ let(:package_name) { package_maven.name }
+ let(:params) { { package_type: package_maven.package_type } }
+
+ it { is_expected.to match_array([tag_maven]) }
+ end
+
+ context 'with blank package type' do
+ let(:params) { { package_type: ' ' } }
+
+ it { is_expected.to match_array([tag1, tag2]) }
+ end
+
+ context 'with nil package type' do
+ let(:params) { { package_type: nil } }
+
+ it { is_expected.to match_array([tag1, tag2]) }
+ end
+
+ context 'with unknown package name' do
+ let(:package_name) { 'foobar' }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ describe '#find_by_name' do
+ let(:tag_name) { tag1.name }
+
+ subject { described_class.new(project, package_name, params).execute.find_by_name(tag_name) }
+
+ it { is_expected.to eq(tag1) }
+
+ context 'with package type' do
+ let(:package_maven) { create(:maven_package, project: project) }
+ let!(:tag_maven) { create(:packages_tag, package: package_maven) }
+ let(:package_name) { package_maven.name }
+ let(:params) { { package_type: package_maven.package_type } }
+ let(:tag_name) { tag_maven.name }
+
+ it { is_expected.to eq(tag_maven) }
+ end
+
+ context 'with unknown tag_name' do
+ let(:tag_name) { 'foobar' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+end
diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb
index dde4f010e41..94954f4153b 100644
--- a/spec/finders/personal_access_tokens_finder_spec.rb
+++ b/spec/finders/personal_access_tokens_finder_spec.rb
@@ -218,6 +218,24 @@ RSpec.describe PersonalAccessTokensFinder do
end
end
+ describe 'with active or expired state' do
+ before do
+ params[:state] = 'active_or_expired'
+ end
+
+ it 'includes active tokens' do
+ is_expected.to include(active_personal_access_token, active_impersonation_token)
+ end
+
+ it 'includes expired tokens' do
+ is_expected.to include(expired_personal_access_token, expired_impersonation_token)
+ end
+
+ it 'does not include revoked tokens' do
+ is_expected.not_to include(revoked_personal_access_token, revoked_impersonation_token)
+ end
+ end
+
describe 'with id' do
subject { finder(params).find_by_id(active_personal_access_token.id) }
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 929927ec1c4..bd71a8186ad 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -262,6 +262,17 @@ RSpec.describe ProjectsFinder, :do_not_mock_admin_mode do
it { is_expected.to match_array([public_project]) }
end
+ describe 'filter by repository_storage' do
+ let(:params) { { repository_storage: 'nfs-05' } }
+ let!(:project) { create(:project, :public) }
+
+ before do
+ project.update_columns(repository_storage: 'nfs-05')
+ end
+
+ it { is_expected.to match_array([project]) }
+ end
+
describe 'sorting' do
let(:params) { { sort: 'name_asc' } }
diff --git a/spec/finders/resource_milestone_event_finder_spec.rb b/spec/finders/resource_milestone_event_finder_spec.rb
index ff4508996e2..27e124afe2e 100644
--- a/spec/finders/resource_milestone_event_finder_spec.rb
+++ b/spec/finders/resource_milestone_event_finder_spec.rb
@@ -42,18 +42,6 @@ RSpec.describe ResourceMilestoneEventFinder do
expect(subject).to be_empty
end
- it 'paginates results' do
- milestone = create(:milestone, project: issue_project)
- create_event(milestone)
- create_event(milestone)
- issue_project.add_guest(user)
-
- paginated = described_class.new(user, issue, per_page: 1).execute
-
- expect(subject.count).to eq 2
- expect(paginated.count).to eq 1
- end
-
context 'when multiple events share the same milestone' do
it 'avoids N+1 queries' do
issue_project.add_developer(user)
@@ -71,8 +59,8 @@ RSpec.describe ResourceMilestoneEventFinder do
create_event(milestone2, :add)
create_event(milestone2, :remove)
- # 1 events + 1 milestones + 1 project + 1 user + 4 ability
- expect { described_class.new(user, issue).execute }.not_to exceed_query_limit(control_count + 7)
+ # 1 milestones + 1 project + 1 user + 4 ability
+ expect { described_class.new(user, issue).execute }.not_to exceed_query_limit(control_count + 6)
end
end
diff --git a/spec/finders/resource_state_event_finder_spec.rb b/spec/finders/resource_state_event_finder_spec.rb
new file mode 100644
index 00000000000..139ef549834
--- /dev/null
+++ b/spec/finders/resource_state_event_finder_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ResourceStateEventFinder do
+ let_it_be(:user) { create(:user) }
+
+ describe '#execute' do
+ subject { described_class.new(user, issue).execute }
+
+ let(:project) { create(:project) }
+ let(:issue) { create(:issue, project: project) }
+
+ let!(:event) { create(:resource_state_event, issue: issue) }
+
+ it 'returns events accessible by user' do
+ project.add_guest(user)
+
+ expect(subject).to eq [event]
+ end
+
+ context 'when issues are private' do
+ let(:project) { create(:project, :public, :issues_private) }
+
+ it 'does not return any events' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'when issue is not accesible to the user' do
+ let(:project) { create(:project, :private) }
+
+ it 'does not return any events' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+
+ describe '#can_read_eventable?' do
+ let(:project) { create(:project, :private) }
+
+ subject { described_class.new(user, eventable).can_read_eventable? }
+
+ context 'when eventable is an Issue' do
+ let(:eventable) { create(:issue, project: project) }
+
+ context 'when issue is readable' do
+ before do
+ project.add_developer(user)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when issue is not readable' do
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when eventable is a MergeRequest' do
+ let(:eventable) { create(:merge_request, source_project: project) }
+
+ context 'when merge request is readable' do
+ before do
+ project.add_developer(user)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when merge request is not readable' do
+ it { is_expected.to be_falsey }
+ end
+ end
+ end
+end
diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb
index 0affc832b30..6fc1cbcee0a 100644
--- a/spec/finders/snippets_finder_spec.rb
+++ b/spec/finders/snippets_finder_spec.rb
@@ -283,6 +283,12 @@ RSpec.describe SnippetsFinder do
it 'returns only personal snippets when the user cannot read cross project' do
expect(described_class.new(user).execute).to contain_exactly(private_personal_snippet, internal_personal_snippet, public_personal_snippet)
end
+
+ context 'when only project snippets are required' do
+ it 'returns no records' do
+ expect(described_class.new(user, only_project: true).execute).to be_empty
+ end
+ end
end
context 'when project snippets are disabled' do
@@ -295,6 +301,22 @@ RSpec.describe SnippetsFinder do
expect(finder.execute).to be_empty
end
end
+
+ context 'no sort param is provided' do
+ it 'returns snippets sorted by id' do
+ snippets = described_class.new(admin).execute
+
+ expect(snippets.ids).to eq(Snippet.order_id_desc.ids)
+ end
+ end
+
+ context 'sort param is provided' do
+ it 'returns snippets sorted by sort param' do
+ snippets = described_class.new(admin, sort: 'updated_desc').execute
+
+ expect(snippets.ids).to eq(Snippet.order_updated_desc.ids)
+ end
+ end
end
it_behaves_like 'snippet visibility'
diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb
index 4123783d828..f6796398782 100644
--- a/spec/finders/todos_finder_spec.rb
+++ b/spec/finders/todos_finder_spec.rb
@@ -37,16 +37,63 @@ RSpec.describe TodosFinder do
end
context 'when filtering by type' do
- it 'returns correct todos when filtered by a type' do
+ it 'returns todos by type when filtered by a single type' do
todos = finder.new(user, { type: 'Issue' }).execute
expect(todos).to match_array([todo1])
end
- it 'returns the correct todos when filtering for multiple types' do
+ it 'returns todos by type when filtered by multiple types' do
+ design_todo = create(:todo, user: user, group: group, target: create(:design))
+
todos = finder.new(user, { type: %w[Issue MergeRequest] }).execute
- expect(todos).to match_array([todo1, todo2])
+ expect(todos).to contain_exactly(todo1, todo2)
+ expect(todos).not_to include(design_todo)
+ end
+
+ it 'returns all todos when type is nil' do
+ todos = finder.new(user, { type: nil }).execute
+
+ expect(todos).to contain_exactly(todo1, todo2)
+ end
+
+ it 'returns all todos when type is an empty collection' do
+ todos = finder.new(user, { type: [] }).execute
+
+ expect(todos).to contain_exactly(todo1, todo2)
+ end
+
+ it 'returns all todos when type is blank' do
+ todos = finder.new(user, { type: '' }).execute
+
+ expect(todos).to contain_exactly(todo1, todo2)
+ end
+
+ it 'returns todos by type when blank type is in type collection' do
+ todos = finder.new(user, { type: ['', 'MergeRequest'] }).execute
+
+ expect(todos).to contain_exactly(todo2)
+ end
+
+ it 'returns todos of all types when only blanks are in a collection' do
+ todos = finder.new(user, { type: ['', ''] }).execute
+
+ expect(todos).to contain_exactly(todo1, todo2)
+ end
+
+ it 'returns all todos when no type param' do
+ todos = finder.new(user).execute
+
+ expect(todos).to contain_exactly(todo1, todo2)
+ end
+
+ it 'raises an argument error when invalid type is passed' do
+ create(:todo, user: user, group: group, target: create(:design))
+
+ todos_finder = finder.new(user, { type: %w[Issue MergeRequest NotAValidType] })
+
+ expect { todos_finder.execute }.to raise_error(ArgumentError)
end
end
diff --git a/spec/finders/user_recent_events_finder_spec.rb b/spec/finders/user_recent_events_finder_spec.rb
index 04ba05c68e4..559d1004b4b 100644
--- a/spec/finders/user_recent_events_finder_spec.rb
+++ b/spec/finders/user_recent_events_finder_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe UserRecentEventsFinder do
- let(:current_user) { create(:user) }
- let(:project_owner) { create(:user) }
+ let_it_be(:project_owner, reload: true) { create(:user) }
+ let_it_be(:current_user, reload: true) { create(:user) }
let(:private_project) { create(:project, :private, creator: project_owner) }
let(:internal_project) { create(:project, :internal, creator: project_owner) }
let(:public_project) { create(:project, :public, creator: project_owner) }
@@ -36,5 +36,17 @@ RSpec.describe UserRecentEventsFinder do
expect(finder.execute).to be_empty
end
+
+ describe 'design activity events' do
+ let_it_be(:event_a) { create(:design_event, author: project_owner) }
+ let_it_be(:event_b) { create(:design_event, author: project_owner) }
+
+ it 'only includes design events', :aggregate_failures do
+ events = finder.execute
+
+ expect(events).to include(event_a)
+ expect(events).to include(event_b)
+ end
+ end
end
end