diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-20 17:22:11 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-12-20 17:22:11 +0300 |
commit | 0c872e02b2c822e3397515ec324051ff540f0cd5 (patch) | |
tree | ce2fb6ce7030e4dad0f4118d21ab6453e5938cdd /spec/finders | |
parent | f7e05a6853b12f02911494c4b3fe53d9540d74fc (diff) |
Add latest changes from gitlab-org/gitlab@15-7-stable-eev15.7.0-rc42
Diffstat (limited to 'spec/finders')
-rw-r--r-- | spec/finders/autocomplete/routes_finder_spec.rb | 40 | ||||
-rw-r--r-- | spec/finders/branches_finder_spec.rb | 63 | ||||
-rw-r--r-- | spec/finders/ci/auth_job_finder_spec.rb | 4 | ||||
-rw-r--r-- | spec/finders/ci/freeze_periods_finder_spec.rb (renamed from spec/finders/freeze_periods_finder_spec.rb) | 2 | ||||
-rw-r--r-- | spec/finders/ci/jobs_finder_spec.rb | 88 | ||||
-rw-r--r-- | spec/finders/ci/pipelines_finder_spec.rb | 41 | ||||
-rw-r--r-- | spec/finders/ci/runners_finder_spec.rb | 447 | ||||
-rw-r--r-- | spec/finders/clusters/agent_tokens_finder_spec.rb | 53 | ||||
-rw-r--r-- | spec/finders/environments/environments_finder_spec.rb | 24 | ||||
-rw-r--r-- | spec/finders/issues_finder_spec.rb | 2 | ||||
-rw-r--r-- | spec/finders/notes_finder_spec.rb | 10 | ||||
-rw-r--r-- | spec/finders/personal_access_tokens_finder_spec.rb | 475 | ||||
-rw-r--r-- | spec/finders/projects_finder_spec.rb | 17 | ||||
-rw-r--r-- | spec/finders/tags_finder_spec.rb | 13 | ||||
-rw-r--r-- | spec/finders/todos_finder_spec.rb | 4 | ||||
-rw-r--r-- | spec/finders/users_finder_spec.rb | 52 | ||||
-rw-r--r-- | spec/finders/work_items/work_items_finder_spec.rb | 2 |
17 files changed, 857 insertions, 480 deletions
diff --git a/spec/finders/autocomplete/routes_finder_spec.rb b/spec/finders/autocomplete/routes_finder_spec.rb index c5b040a5640..f37e8e8de7b 100644 --- a/spec/finders/autocomplete/routes_finder_spec.rb +++ b/spec/finders/autocomplete/routes_finder_spec.rb @@ -32,8 +32,24 @@ RSpec.describe Autocomplete::RoutesFinder do context 'when user is admin' do let(:current_user) { admin } - it 'finds all namespaces matching the search excluding project namespaces' do - is_expected.to match_array([group.route, group2.route, user_route]) + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it 'finds all namespaces matching the search excluding project namespaces' do + is_expected.to match_array([group.route, group2.route, user_route]) + end + end + + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it 'finds all namespaces matching the search excluding project namespaces' do + is_expected.to match_array([group.route, group2.route, user_route]) + end + end + + context 'when not in admin mode' do + it 'does not find all namespaces' do + is_expected.to match_array([]) + end + end end end end @@ -48,8 +64,24 @@ RSpec.describe Autocomplete::RoutesFinder do context 'when user is admin' do let(:current_user) { admin } - it 'finds all projects matching the search' do - is_expected.to match_array([project.route, project2.route]) + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it 'finds all projects matching the search' do + is_expected.to match_array([project.route, project2.route]) + end + end + + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it 'finds all projects matching the search' do + is_expected.to match_array([project.route, project2.route]) + end + end + + context 'when not in admin mode' do + it 'does not find all projects' do + is_expected.to match_array([]) + end + end end end end diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb index f14c60c4b8f..18f8d1adecc 100644 --- a/spec/finders/branches_finder_spec.rb +++ b/spec/finders/branches_finder_spec.rb @@ -72,16 +72,6 @@ RSpec.describe BranchesFinder do end end - context 'with an unknown name' do - let(:params) { { search: 'random' } } - - it 'does not find any branch' do - result = subject - - expect(result.count).to eq(0) - end - end - context 'by provided names' do let(:params) { { names: %w[fix csv lfs does-not-exist] } } @@ -115,6 +105,49 @@ RSpec.describe BranchesFinder do end end + context 'by name with wildcard' do + let(:params) { { search: 'f*e' } } + + it 'filters branches' do + result = subject + + expect(result.first.name).to eq('2-mb-file') + expect(result.count).to eq(30) + end + end + + context 'by mixed regex operators' do + let(:params) { { search: '^f*e$' } } + + it 'filters branches' do + result = subject + + expect(result.first.name).to eq('feature') + expect(result.count).to eq(1) + end + end + + context 'by name with multiple wildcards' do + let(:params) { { search: 'f*a*e' } } + + it 'filters branches' do + result = subject + + expect(result.first.name).to eq('after-create-delete-modify-move') + expect(result.count).to eq(11) + end + end + + context 'with an unknown name' do + let(:params) { { search: 'random' } } + + it 'does not find any branch' do + result = subject + + expect(result.count).to eq(0) + end + end + context 'by nonexistent name that begins with' do let(:params) { { search: '^nope' } } @@ -134,6 +167,16 @@ RSpec.describe BranchesFinder do expect(result.count).to eq(0) end end + + context 'by nonexistent name with wildcard' do + let(:params) { { search: 'zz*asdf' } } + + it 'filters branches' do + result = subject + + expect(result.count).to eq(0) + end + end end context 'filter and sort' do diff --git a/spec/finders/ci/auth_job_finder_spec.rb b/spec/finders/ci/auth_job_finder_spec.rb index 0a326699875..73a65d0c5af 100644 --- a/spec/finders/ci/auth_job_finder_spec.rb +++ b/spec/finders/ci/auth_job_finder_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Ci::AuthJobFinder do +RSpec.describe Ci::AuthJobFinder, feature_category: :continuous_integration do let_it_be(:user, reload: true) { create(:user) } let_it_be(:job, reload: true) { create(:ci_build, status: :running, user: user) } @@ -68,7 +68,7 @@ RSpec.describe Ci::AuthJobFinder do it 'sets ci_job_token_scope on the job user', :aggregate_failures do expect(subject).to eq(job) expect(subject.user).to be_from_ci_job_token - expect(subject.user.ci_job_token_scope.source_project).to eq(job.project) + expect(subject.user.ci_job_token_scope.current_project).to eq(job.project) end end end diff --git a/spec/finders/freeze_periods_finder_spec.rb b/spec/finders/ci/freeze_periods_finder_spec.rb index 53cc07d91b0..6c58028a221 100644 --- a/spec/finders/freeze_periods_finder_spec.rb +++ b/spec/finders/ci/freeze_periods_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe FreezePeriodsFinder do +RSpec.describe Ci::FreezePeriodsFinder, feature_category: :release_orchestration do subject(:finder) { described_class.new(project, user).execute } let(:project) { create(:project, :private) } diff --git a/spec/finders/ci/jobs_finder_spec.rb b/spec/finders/ci/jobs_finder_spec.rb index dd3ba9721e4..0b3777a2fe8 100644 --- a/spec/finders/ci/jobs_finder_spec.rb +++ b/spec/finders/ci/jobs_finder_spec.rb @@ -14,52 +14,55 @@ RSpec.describe Ci::JobsFinder, '#execute' do let(:params) { {} } context 'no project' do - subject { described_class.new(current_user: admin, params: params).execute } + subject { described_class.new(current_user: current_user, params: params).execute } - it 'returns all jobs' do - expect(subject).to match_array([pending_job, running_job, successful_job]) - end + context 'with admin' do + let(:current_user) { admin } - context 'non admin user' do - let(:admin) { user } + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it { is_expected.to match_array([pending_job, running_job, successful_job]) } + end - it 'returns no jobs' do - expect(subject).to be_empty + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it { is_expected.to match_array([pending_job, running_job, successful_job]) } + end + + context 'when not in admin mode' do + it { is_expected.to be_empty } + end end end + context 'with normal user' do + let(:current_user) { user } + + it { is_expected.to be_empty } + end + context 'without user' do - let(:admin) { nil } + let(:current_user) { nil } - it 'returns no jobs' do - expect(subject).to be_empty - end + it { is_expected.to be_empty } end - context 'scope is present' do + context 'with scope', :enable_admin_mode do + let(:current_user) { admin } let(:jobs) { [pending_job, running_job, successful_job] } - where(:scope, :index) do - [ - ['pending', 0], - ['running', 1], - ['finished', 2] - ] + using RSpec::Parameterized::TableSyntax + + where(:scope, :expected_jobs) do + 'pending' | lazy { [pending_job] } + 'running' | lazy { [running_job] } + 'finished' | lazy { [successful_job] } + %w[running success] | lazy { [running_job, successful_job] } end with_them do let(:params) { { scope: scope } } - it { expect(subject).to match_array([jobs[index]]) } - end - end - - context 'scope is an array' do - let(:jobs) { [pending_job, running_job, successful_job, canceled_job] } - let(:params) { { scope: %w'running success' } } - - it 'filters by the job statuses in the scope' do - expect(subject).to contain_exactly(running_job, successful_job) + it { is_expected.to match_array(expected_jobs) } end end end @@ -96,6 +99,33 @@ RSpec.describe Ci::JobsFinder, '#execute' do end end + context 'when artifacts are present for some jobs' do + let_it_be(:job_with_artifacts) { create(:ci_build, :success, pipeline: pipeline, name: 'test') } + let_it_be(:artifact) { create(:ci_job_artifact, job: job_with_artifacts) } + + subject { described_class.new(current_user: user, project: project, params: params).execute } + + before do + project.add_maintainer(user) + end + + context 'when with_artifacts is true' do + let(:params) { { with_artifacts: true } } + + it 'returns only jobs with artifacts' do + expect(subject).to match_array([job_with_artifacts]) + end + end + + context 'when with_artifacts is false' do + let(:params) { { with_artifacts: false } } + + it 'returns all jobs' do + expect(subject).to match_array([successful_job, job_with_artifacts]) + end + end + end + context 'when pipeline is present' do before_all do project.add_maintainer(user) diff --git a/spec/finders/ci/pipelines_finder_spec.rb b/spec/finders/ci/pipelines_finder_spec.rb index 908210e0296..a2e8fe8df5a 100644 --- a/spec/finders/ci/pipelines_finder_spec.rb +++ b/spec/finders/ci/pipelines_finder_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Ci::PipelinesFinder do - let(:project) { create(:project, :public, :repository) } + let_it_be(:project) { create(:project, :public, :repository) } let(:current_user) { nil } let(:params) { {} } @@ -242,6 +242,45 @@ RSpec.describe Ci::PipelinesFinder do end end + context 'when name is specified' do + let_it_be(:pipeline) { create(:ci_pipeline, project: project, name: 'Build pipeline') } + let_it_be(:pipeline_other) { create(:ci_pipeline, project: project, name: 'Some other pipeline') } + + let(:params) { { name: 'build Pipeline' } } + + it 'performs case insensitive compare' do + is_expected.to contain_exactly(pipeline) + end + + context 'when name does not exist' do + let(:params) { { name: 'absent-name' } } + + it 'returns empty' do + is_expected.to be_empty + end + end + + context 'when pipeline_name feature flag is off' do + before do + stub_feature_flags(pipeline_name: false) + end + + it 'ignores name parameter' do + is_expected.to contain_exactly(pipeline, pipeline_other) + end + end + + context 'when pipeline_name_search feature flag is off' do + before do + stub_feature_flags(pipeline_name_search: false) + end + + it 'ignores name parameter' do + is_expected.to contain_exactly(pipeline, pipeline_other) + end + end + end + describe 'ordering' do using RSpec::Parameterized::TableSyntax diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb index 18eecd0f073..a8ef99eeaec 100644 --- a/spec/finders/ci/runners_finder_spec.rb +++ b/spec/finders/ci/runners_finder_spec.rb @@ -7,219 +7,221 @@ RSpec.describe Ci::RunnersFinder do let_it_be(:admin) { create(:user, :admin) } describe '#execute' do - context 'with 2 runners' do - let_it_be(:runner1) { create(:ci_runner, active: true) } - let_it_be(:runner2) { create(:ci_runner, active: false) } - - context 'with empty params' do - it 'returns all runners' do - expect(Ci::Runner).to receive(:with_tags).and_call_original - expect(described_class.new(current_user: admin, params: {}).execute).to match_array [runner1, runner2] + shared_examples 'executes as admin' do + context 'with 2 runners' do + let_it_be(:runner1) { create(:ci_runner, active: true) } + let_it_be(:runner2) { create(:ci_runner, active: false) } + + context 'with empty params' do + it 'returns all runners' do + expect(Ci::Runner).to receive(:with_tags).and_call_original + expect(described_class.new(current_user: admin, params: {}).execute).to match_array [runner1, runner2] + end end - end - context 'with nil group' do - it 'returns all runners' do - expect(Ci::Runner).to receive(:with_tags).and_call_original - expect(described_class.new(current_user: admin, params: { group: nil }).execute).to match_array [runner1, runner2] + context 'with nil group' do + it 'returns all runners' do + expect(Ci::Runner).to receive(:with_tags).and_call_original + expect(described_class.new(current_user: admin, params: { group: nil }).execute).to match_array [runner1, runner2] + end end - end - context 'with preload param set to :tag_name true' do - it 'requests tags' do - expect(Ci::Runner).to receive(:with_tags).and_call_original - expect(described_class.new(current_user: admin, params: { preload: { tag_name: true } }).execute).to match_array [runner1, runner2] + context 'with preload param set to :tag_name true' do + it 'requests tags' do + expect(Ci::Runner).to receive(:with_tags).and_call_original + expect(described_class.new(current_user: admin, params: { preload: { tag_name: true } }).execute).to match_array [runner1, runner2] + end end - end - context 'with preload param set to :tag_name false' do - it 'does not request tags' do - expect(Ci::Runner).not_to receive(:with_tags) - expect(described_class.new(current_user: admin, params: { preload: { tag_name: false } }).execute).to match_array [runner1, runner2] + context 'with preload param set to :tag_name false' do + it 'does not request tags' do + expect(Ci::Runner).not_to receive(:with_tags) + expect(described_class.new(current_user: admin, params: { preload: { tag_name: false } }).execute).to match_array [runner1, runner2] + end end end - end - context 'filtering' do - context 'by search term' do - it 'calls Ci::Runner.search' do - expect(Ci::Runner).to receive(:search).with('term').and_call_original + context 'filtering' do + context 'by search term' do + it 'calls Ci::Runner.search' do + expect(Ci::Runner).to receive(:search).with('term').and_call_original - described_class.new(current_user: admin, params: { search: 'term' }).execute + described_class.new(current_user: admin, params: { search: 'term' }).execute + end end - end - context 'by upgrade status' do - let(:upgrade_status) {} + context 'by upgrade status' do + let(:upgrade_status) {} - let_it_be(:runner1) { create(:ci_runner, version: 'a') } - let_it_be(:runner2) { create(:ci_runner, version: 'b') } - let_it_be(:runner3) { create(:ci_runner, version: 'c') } - let_it_be(:runner_version_recommended) do - create(:ci_runner_version, version: 'a', status: :recommended) - end + let_it_be(:runner1) { create(:ci_runner, version: 'a') } + let_it_be(:runner2) { create(:ci_runner, version: 'b') } + let_it_be(:runner3) { create(:ci_runner, version: 'c') } + let_it_be(:runner_version_recommended) do + create(:ci_runner_version, version: 'a', status: :recommended) + end - let_it_be(:runner_version_not_available) do - create(:ci_runner_version, version: 'b', status: :not_available) - end + let_it_be(:runner_version_not_available) do + create(:ci_runner_version, version: 'b', status: :not_available) + end - let_it_be(:runner_version_available) do - create(:ci_runner_version, version: 'c', status: :available) - end + let_it_be(:runner_version_available) do + create(:ci_runner_version, version: 'c', status: :available) + end - def execute - described_class.new(current_user: admin, params: { upgrade_status: upgrade_status }).execute - end + def execute + described_class.new(current_user: admin, params: { upgrade_status: upgrade_status }).execute + end - Ci::RunnerVersion.statuses.keys.map(&:to_sym).each do |status| - context "set to :#{status}" do - let(:upgrade_status) { status } + Ci::RunnerVersion.statuses.keys.map(&:to_sym).each do |status| + context "set to :#{status}" do + let(:upgrade_status) { status } - it "calls with_upgrade_status scope with corresponding :#{status} status" do - if [:available, :not_available, :recommended].include?(status) - expected_result = Ci::Runner.with_upgrade_status(status) - end + it "calls with_upgrade_status scope with corresponding :#{status} status" do + if [:available, :not_available, :recommended].include?(status) + expected_result = Ci::Runner.with_upgrade_status(status) + end - expect(Ci::Runner).to receive(:with_upgrade_status).with(status).and_call_original + expect(Ci::Runner).to receive(:with_upgrade_status).with(status).and_call_original - result = execute + result = execute - expect(result).to match_array(expected_result) if expected_result + expect(result).to match_array(expected_result) if expected_result + end end end - end - context 'set to an invalid value' do - let(:upgrade_status) { :some_invalid_status } + context 'set to an invalid value' do + let(:upgrade_status) { :some_invalid_status } - it 'raises ArgumentError' do - expect { execute }.to raise_error(ArgumentError) + it 'raises ArgumentError' do + expect { execute }.to raise_error(ArgumentError) + end end - end - context 'set to nil' do - let(:upgrade_status) { nil } + context 'set to nil' do + let(:upgrade_status) { nil } - it 'does not call with_upgrade_status' do - expect(Ci::Runner).not_to receive(:with_upgrade_status) + it 'does not call with_upgrade_status' do + expect(Ci::Runner).not_to receive(:with_upgrade_status) - expect(execute).to match_array(Ci::Runner.all) + expect(execute).to match_array(Ci::Runner.all) + end end end - end - context 'by status' do - Ci::Runner::AVAILABLE_STATUSES.each do |status| - it "calls the corresponding :#{status} scope on Ci::Runner" do - expect(Ci::Runner).to receive(status.to_sym).and_call_original + context 'by status' do + Ci::Runner::AVAILABLE_STATUSES.each do |status| + it "calls the corresponding :#{status} scope on Ci::Runner" do + expect(Ci::Runner).to receive(status.to_sym).and_call_original - described_class.new(current_user: admin, params: { status_status: status }).execute + described_class.new(current_user: admin, params: { status_status: status }).execute + end end end - end - context 'by active status' do - it 'with active set as false calls the corresponding scope on Ci::Runner with false' do - expect(Ci::Runner).to receive(:active).with(false).and_call_original + context 'by active status' do + it 'with active set as false calls the corresponding scope on Ci::Runner with false' do + expect(Ci::Runner).to receive(:active).with(false).and_call_original - described_class.new(current_user: admin, params: { active: false }).execute - end + described_class.new(current_user: admin, params: { active: false }).execute + end - it 'with active set as true calls the corresponding scope on Ci::Runner with true' do - expect(Ci::Runner).to receive(:active).with(true).and_call_original + it 'with active set as true calls the corresponding scope on Ci::Runner with true' do + expect(Ci::Runner).to receive(:active).with(true).and_call_original - described_class.new(current_user: admin, params: { active: true }).execute + described_class.new(current_user: admin, params: { active: true }).execute + end end - end - context 'by runner type' do - it 'calls the corresponding scope on Ci::Runner' do - expect(Ci::Runner).to receive(:project_type).and_call_original + context 'by runner type' do + it 'calls the corresponding scope on Ci::Runner' do + expect(Ci::Runner).to receive(:project_type).and_call_original - described_class.new(current_user: admin, params: { type_type: 'project_type' }).execute + described_class.new(current_user: admin, params: { type_type: 'project_type' }).execute + end end - end - context 'by tag_name' do - it 'calls the corresponding scope on Ci::Runner' do - expect(Ci::Runner).to receive(:tagged_with).with(%w[tag1 tag2]).and_call_original + context 'by tag_name' do + it 'calls the corresponding scope on Ci::Runner' do + expect(Ci::Runner).to receive(:tagged_with).with(%w[tag1 tag2]).and_call_original - described_class.new(current_user: admin, params: { tag_name: %w[tag1 tag2] }).execute + described_class.new(current_user: admin, params: { tag_name: %w[tag1 tag2] }).execute + end end end - end - context 'sorting' do - let_it_be(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago, token_expires_at: '2022-02-15 07:00' } - let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago, token_expires_at: '2022-02-15 06:00' } - let_it_be(:runner3) { create :ci_runner, created_at: '2018-07-12 09:00', contacted_at: 2.minutes.ago } + context 'sorting' do + let_it_be(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago, token_expires_at: '2022-02-15 07:00' } + let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago, token_expires_at: '2022-02-15 06:00' } + let_it_be(:runner3) { create :ci_runner, created_at: '2018-07-12 09:00', contacted_at: 2.minutes.ago } - subject do - described_class.new(current_user: admin, params: params).execute - end + subject do + described_class.new(current_user: admin, params: params).execute + end - shared_examples 'sorts by created_at descending' do - it 'sorts by created_at descending' do - is_expected.to eq [runner3, runner2, runner1] + shared_examples 'sorts by created_at descending' do + it 'sorts by created_at descending' do + is_expected.to eq [runner3, runner2, runner1] + end end - end - context 'without sort param' do - let(:params) { {} } + context 'without sort param' do + let(:params) { {} } - it_behaves_like 'sorts by created_at descending' - end + it_behaves_like 'sorts by created_at descending' + end - %w(created_date created_at_desc).each do |sort| - context "with sort param equal to #{sort}" do - let(:params) { { sort: sort } } + %w(created_date created_at_desc).each do |sort| + context "with sort param equal to #{sort}" do + let(:params) { { sort: sort } } - it_behaves_like 'sorts by created_at descending' + it_behaves_like 'sorts by created_at descending' + end end - end - context 'with sort param equal to created_at_asc' do - let(:params) { { sort: 'created_at_asc' } } + context 'with sort param equal to created_at_asc' do + let(:params) { { sort: 'created_at_asc' } } - it 'sorts by created_at ascending' do - is_expected.to eq [runner1, runner2, runner3] + it 'sorts by created_at ascending' do + is_expected.to eq [runner1, runner2, runner3] + end end - end - context 'with sort param equal to contacted_asc' do - let(:params) { { sort: 'contacted_asc' } } + context 'with sort param equal to contacted_asc' do + let(:params) { { sort: 'contacted_asc' } } - it 'sorts by contacted_at ascending' do - is_expected.to eq [runner2, runner3, runner1] + it 'sorts by contacted_at ascending' do + is_expected.to eq [runner2, runner3, runner1] + end end - end - context 'with sort param equal to contacted_desc' do - let(:params) { { sort: 'contacted_desc' } } + context 'with sort param equal to contacted_desc' do + let(:params) { { sort: 'contacted_desc' } } - it 'sorts by contacted_at descending' do - is_expected.to eq [runner1, runner3, runner2] + it 'sorts by contacted_at descending' do + is_expected.to eq [runner1, runner3, runner2] + end end - end - context 'with sort param equal to token_expires_at_asc' do - let(:params) { { sort: 'token_expires_at_asc' } } + context 'with sort param equal to token_expires_at_asc' do + let(:params) { { sort: 'token_expires_at_asc' } } - it 'sorts by contacted_at ascending' do - is_expected.to eq [runner2, runner1, runner3] + it 'sorts by contacted_at ascending' do + is_expected.to eq [runner2, runner1, runner3] + end end - end - context 'with sort param equal to token_expires_at_desc' do - let(:params) { { sort: 'token_expires_at_desc' } } + context 'with sort param equal to token_expires_at_desc' do + let(:params) { { sort: 'token_expires_at_desc' } } - it 'sorts by contacted_at descending' do - is_expected.to eq [runner3, runner1, runner2] + it 'sorts by contacted_at descending' do + is_expected.to eq [runner3, runner1, runner2] + end end end end - context 'by non admin user' do + shared_examples 'executes as normal user' do it 'returns no runners' do user = create :user create :ci_runner, active: true @@ -229,6 +231,24 @@ RSpec.describe Ci::RunnersFinder do end end + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it_behaves_like 'executes as admin' + end + + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it_behaves_like 'executes as admin' + end + + context 'when not in admin mode' do + it_behaves_like 'executes as normal user' + end + end + + context 'by non admin user' do + it_behaves_like 'executes as normal user' + end + context 'when user is nil' do it 'returns no runners' do user = nil @@ -473,4 +493,153 @@ RSpec.describe Ci::RunnersFinder do end end end + + context 'project' do + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } + let_it_be(:other_project) { create(:project) } + + let(:extra_params) { {} } + let(:params) { { project: project }.merge(extra_params).reject { |_, v| v.nil? } } + + describe '#execute' do + subject { described_class.new(current_user: user, params: params).execute } + + context 'with user as project admin' do + before do + project.add_maintainer(user) + end + + context 'with project runners' do + let_it_be(:runner_project) { create(:ci_runner, :project, contacted_at: 7.minutes.ago, projects: [project]) } + + it 'returns runners available to project' do + expect(subject).to match_array([runner_project]) + end + end + + context 'with ancestor group runners' do + let_it_be(:runner_instance) { create(:ci_runner, contacted_at: 13.minutes.ago) } + let_it_be(:runner_group) { create(:ci_runner, :group, contacted_at: 12.minutes.ago, groups: [group]) } + + it 'returns runners available to project' do + expect(subject).to match_array([runner_instance, runner_group]) + end + end + + context 'with allowed shared runners' do + let_it_be(:runner_instance) { create(:ci_runner, :instance, contacted_at: 13.minutes.ago) } + + it 'returns runners available to project' do + expect(subject).to match_array([runner_instance]) + end + end + + context 'with project, ancestor group, and allowed shared runners' do + let_it_be(:runner_project) { create(:ci_runner, :project, contacted_at: 7.minutes.ago, projects: [project]) } + let_it_be(:runner_group) { create(:ci_runner, :group, contacted_at: 12.minutes.ago, groups: [group]) } + let_it_be(:runner_instance) { create(:ci_runner, :instance, contacted_at: 13.minutes.ago) } + + it 'returns runners available to project' do + expect(subject).to match_array([runner_project, runner_group, runner_instance]) + end + end + + context 'filtering' do + let_it_be(:runner_instance_inactive) { create(:ci_runner, :instance, active: false, contacted_at: 13.minutes.ago) } + let_it_be(:runner_instance_active) { create(:ci_runner, :instance, active: true, contacted_at: 13.minutes.ago) } + let_it_be(:runner_project_active) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, active: true, projects: [project]) } + let_it_be(:runner_project_inactive) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, active: false, projects: [project]) } + let_it_be(:runner_other_project_inactive) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, active: false, projects: [other_project]) } + + context 'by search term' do + let_it_be(:runner_project_1) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, description: 'runner_project_search', projects: [project]) } + let_it_be(:runner_project_2) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, description: 'runner_project', projects: [project]) } + let_it_be(:runner_another_project) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, description: 'runner_project_search', projects: [other_project]) } + + let(:extra_params) { { search: 'runner_project_search' } } + + it 'returns the correct runner' do + expect(subject).to match_array([runner_project_1]) + end + end + + context 'by active status' do + let(:extra_params) { { active: false } } + + it 'returns the correct runners' do + expect(subject).to match_array([runner_instance_inactive, runner_project_inactive]) + end + end + + context 'by status' do + let(:extra_params) { { status_status: 'paused' } } + + it 'returns correct runner' do + expect(subject).to match_array([runner_instance_inactive, runner_project_inactive]) + end + end + + context 'by tag_name' do + let_it_be(:runner_project_1) { create(:ci_runner, :project, contacted_at: 3.minutes.ago, tag_list: %w[runner_tag], projects: [project]) } + let_it_be(:runner_project_2) { create(:ci_runner, :project, contacted_at: 3.minutes.ago, tag_list: %w[other_tag], projects: [project]) } + let_it_be(:runner_other_project) { create(:ci_runner, :project, contacted_at: 3.minutes.ago, tag_list: %w[runner_tag], projects: [other_project]) } + + let(:extra_params) { { tag_name: %w[runner_tag] } } + + it 'returns correct runner' do + expect(subject).to match_array([runner_project_1]) + end + end + + context 'by runner type' do + let(:extra_params) { { type_type: 'project_type' } } + + it 'returns correct runners' do + expect(subject).to match_array([runner_project_active, runner_project_inactive]) + end + end + end + end + + context 'with user as project developer' do + let(:user) { create(:user) } + + before do + project.add_developer(user) + end + + it 'returns no runners' do + expect(subject).to be_empty + end + end + + context 'when user is nil' do + let_it_be(:user) { nil } + + it 'returns no runners' do + expect(subject).to be_empty + end + end + + context 'with nil project_full_path' do + let(:project_full_path) { nil } + + it 'returns no runners' do + expect(subject).to be_empty + end + end + + context 'when on_demand_scans_runner_tags feature flag is disabled' do + before do + stub_feature_flags(on_demand_scans_runner_tags: false) + end + + it 'returns no runners' do + expect(subject).to be_empty + end + end + end + end end diff --git a/spec/finders/clusters/agent_tokens_finder_spec.rb b/spec/finders/clusters/agent_tokens_finder_spec.rb index 619aca891c1..024e567a16e 100644 --- a/spec/finders/clusters/agent_tokens_finder_spec.rb +++ b/spec/finders/clusters/agent_tokens_finder_spec.rb @@ -5,24 +5,43 @@ require 'spec_helper' RSpec.describe Clusters::AgentTokensFinder do describe '#execute' do let_it_be(:project) { create(:project) } + let_it_be(:agent) { create(:cluster_agent, project: project) } let(:user) { create(:user, maintainer_projects: [project]) } - let(:agent) { create(:cluster_agent, project: project) } - let(:agent_id) { agent.id } - let!(:matching_agent_tokens) do + let_it_be(:active_agent_tokens) do [ create(:cluster_agent_token, agent: agent), - create(:cluster_agent_token, :revoked, agent: agent) + create(:cluster_agent_token, agent: agent) ] end - subject(:execute) { described_class.new(project, user, agent_id).execute } + let_it_be(:revoked_agent_tokens) do + [ + create(:cluster_agent_token, :revoked, agent: agent), + create(:cluster_agent_token, :revoked, agent: agent) + ] + end - it 'returns the tokens of the specified agent' do - # creating a token in a different agent to make sure it will not be included in the result + before_all do + # set up a token under a different agent as a way to verify + # that only tokens of a given agent are included in the result create(:cluster_agent_token, agent: create(:cluster_agent)) + end + + subject(:execute) { described_class.new(agent, user).execute } + + it { is_expected.to match_array(active_agent_tokens + revoked_agent_tokens) } - expect(execute).to match_array(matching_agent_tokens) + context 'when filtering by status=active' do + subject(:execute) { described_class.new(agent, user, status: 'active').execute } + + it { is_expected.to match_array(active_agent_tokens) } + end + + context 'when filtering by status=revoked' do + subject(:execute) { described_class.new(agent, user, status: 'revoked').execute } + + it { is_expected.to match_array(revoked_agent_tokens) } end context 'when user does not have permission' do @@ -32,16 +51,20 @@ RSpec.describe Clusters::AgentTokensFinder do project.add_reporter(user) end - it 'raises an error' do - expect { execute }.to raise_error(ActiveRecord::RecordNotFound) - end + it { is_expected.to eq ::Clusters::AgentToken.none } end - context 'when agent does not exist' do - let(:agent_id) { non_existing_record_id } + context 'when current_user is nil' do + it 'returns an empty list' do + result = described_class.new(agent, nil).execute + expect(result).to eq ::Clusters::AgentToken.none + end + end - it 'raises an error' do - expect { execute }.to raise_error(ActiveRecord::RecordNotFound) + context 'when agent is nil' do + it 'returns an empty list' do + result = described_class.new(nil, user).execute + expect(result).to eq ::Clusters::AgentToken.none end end end diff --git a/spec/finders/environments/environments_finder_spec.rb b/spec/finders/environments/environments_finder_spec.rb index 04fbd4067b4..df66bbdc235 100644 --- a/spec/finders/environments/environments_finder_spec.rb +++ b/spec/finders/environments/environments_finder_spec.rb @@ -51,15 +51,35 @@ RSpec.describe Environments::EnvironmentsFinder do end context 'with search and states' do + let_it_be(:environment_available_b) { create(:environment, :available, name: 'test/foldered-env', project: project) } + it 'searches environments by name and state' do result = described_class.new(project, user, search: 'test', states: :available).execute - expect(result).to contain_exactly(environment_available) + expect(result).to contain_exactly(environment_available, environment_available_b) + end + + it 'searches environments by name inside folder and state' do + result = described_class.new(project, user, search: 'folder', states: :available).execute + + expect(result).to contain_exactly(environment_available_b) + end + + context 'when enable_environments_search_within_folder FF is disabled' do + before do + stub_feature_flags(enable_environments_search_within_folder: false) + end + + it 'ignores name inside folder' do + result = described_class.new(project, user, search: 'folder', states: :available).execute + + expect(result).to be_empty + end end end context 'with id' do - it 'searches environments by name and state' do + it 'searches environments by name and id' do result = described_class.new(project, user, search: 'test', environment_ids: [environment_available.id]).execute expect(result).to contain_exactly(environment_available) diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index 704171a737b..43d66d285fa 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe IssuesFinder do +RSpec.describe IssuesFinder, feature_category: :team_planning do include_context 'IssuesFinder context' it_behaves_like 'issues or work items finder', :issue, 'IssuesFinder#execute context' diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb index 11de19cfdbc..61be90b267a 100644 --- a/spec/finders/notes_finder_spec.rb +++ b/spec/finders/notes_finder_spec.rb @@ -328,6 +328,16 @@ RSpec.describe NotesFinder do it 'returns the commit' do expect(subject.target).to eq(commit) end + + context 'user does not have permission to read_code' do + before do + allow(Ability).to receive(:allowed?).with(user, :read_code, project).and_return false + end + + it 'returns nil' do + expect(subject.target).to be_nil + end + end end context 'target_iid' do diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb index 21380cb6632..bcd5aef84f9 100644 --- a/spec/finders/personal_access_tokens_finder_spec.rb +++ b/spec/finders/personal_access_tokens_finder_spec.rb @@ -2,359 +2,320 @@ require 'spec_helper' -RSpec.describe PersonalAccessTokensFinder do - def finder(options = {}, current_user = nil) - described_class.new(options, current_user) - end - - describe '# searches PATs' do - using RSpec::Parameterized::TableSyntax +RSpec.describe PersonalAccessTokensFinder, :enable_admin_mode do + using RSpec::Parameterized::TableSyntax - let_it_be(:time_token) do - create(:personal_access_token, created_at: DateTime.new(2022, 01, 02), - last_used_at: DateTime.new(2022, 01, 02)) + describe '#execute' do + let(:admin) { create(:admin) } + let(:user) { create(:user) } + let(:other_user) { create(:user) } + let(:project_bot) { create(:user, :project_bot) } + + let!(:tokens) do + { + active: create(:personal_access_token, user: user, name: 'my_pat_1'), + active_other: create(:personal_access_token, user: other_user, name: 'my_pat_2'), + expired: create(:personal_access_token, :expired, user: user), + revoked: create(:personal_access_token, :revoked, user: user), + active_impersonation: create(:personal_access_token, :impersonation, user: user), + expired_impersonation: create(:personal_access_token, :expired, :impersonation, user: user), + revoked_impersonation: create(:personal_access_token, :revoked, :impersonation, user: user), + bot: create(:personal_access_token, user: project_bot) + } end - let_it_be(:name_token) { create(:personal_access_token, name: 'test_1') } - - let_it_be(:impersonated_token) do - create(:personal_access_token, :impersonation, - created_at: DateTime.new(2022, 01, 02), - last_used_at: DateTime.new(2022, 01, 02), - name: 'imp_token' - ) - end + let(:params) { {} } + let(:current_user) { admin } - shared_examples 'finding tokens by user and options' do - subject { finder(option, user).execute } + subject { described_class.new(params, current_user).execute } - it 'finds exactly' do - subject + describe 'by current user' do + context 'with no user' do + let(:current_user) { nil } - is_expected.to contain_exactly(*result) + it 'returns all tokens' do + is_expected.to match_array(tokens.values) + end end - end - context 'by' do - where(:option, :user, :result) do - { created_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] } - { created_after: DateTime.new(2022, 01, 01) } | create(:admin) | lazy { [time_token, name_token, impersonated_token] } - { last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] } - { last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] } - { impersonation: true } | create(:admin) | lazy { [impersonated_token] } - { search: 'test' } | create(:admin) | lazy { [name_token] } - end + context 'with admin' do + let(:current_user) { admin } - with_them do - it_behaves_like 'finding tokens by user and options' - end - end - end - - describe '#execute' do - let(:user) { create(:user) } - let(:params) { {} } - let(:current_user) { nil } - let!(:active_personal_access_token) { create(:personal_access_token, user: user) } - let!(:expired_personal_access_token) { create(:personal_access_token, :expired, user: user) } - let!(:revoked_personal_access_token) { create(:personal_access_token, :revoked, user: user) } - let!(:active_impersonation_token) { create(:personal_access_token, :impersonation, user: user) } - let!(:expired_impersonation_token) { create(:personal_access_token, :expired, :impersonation, user: user) } - let!(:revoked_impersonation_token) { create(:personal_access_token, :revoked, :impersonation, user: user) } - let!(:project_bot) { create(:user, :project_bot) } - let!(:project_member) { create(:project_member, user: project_bot) } - let!(:project_access_token) { create(:personal_access_token, user: project_bot) } - - subject { finder(params, current_user).execute } - - context 'when current_user is defined' do - let(:current_user) { create(:admin) } - let(:params) { { user: user } } - - context 'current_user is allowed to read PATs' do - it do - is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token, - revoked_personal_access_token, expired_personal_access_token, - revoked_impersonation_token, expired_impersonation_token) + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it 'returns all tokens' do + is_expected.to match_array(tokens.values) + end end - end - context 'current_user is not allowed to read PATs' do - let(:current_user) { create(:user) } + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it 'returns all tokens' do + is_expected.to match_array(tokens.values) + end + end + + context 'when not in admin mode' do + before do + allow_next_instance_of(Gitlab::Auth::CurrentUserMode) do |current_user_mode| + allow(current_user_mode).to receive(:admin_mode?).and_return(false) + end + end - it { is_expected.to be_empty } + it 'returns no tokens' do + is_expected.to be_empty + end + end + end end - context 'when user param is not set' do - let(:params) { {} } + context 'when user can read user personal access tokens' do + let(:params) { { user: user } } + let(:current_user) { user } - it do - is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token, - revoked_personal_access_token, expired_personal_access_token, - revoked_impersonation_token, expired_impersonation_token, project_access_token) + it 'returns tokens of user' do + is_expected.to contain_exactly(*user.personal_access_tokens) end + end - context 'when current_user is not an administrator' do - let(:current_user) { create(:user) } + context 'when user can not read user personal access tokens' do + let(:params) { { user: other_user } } + let(:current_user) { user } - it { is_expected.to be_empty } + it 'returns no tokens' do + is_expected.to be_empty end end end - describe 'without user' do - it do - is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token, - revoked_personal_access_token, expired_personal_access_token, - revoked_impersonation_token, expired_impersonation_token, project_access_token) + describe 'by user' do + where(:by_user, :expected_tokens) do + nil | tokens.keys + ref(:user) | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation] + ref(:other_user) | [:active_other] + ref(:admin) | [] end - describe 'with users' do - let(:user2) { create(:user) } - - before do - create(:personal_access_token, user: user2) - create(:personal_access_token, :expired, user: user2) - create(:personal_access_token, :revoked, user: user2) - create(:personal_access_token, :impersonation, user: user2) - create(:personal_access_token, :expired, :impersonation, user: user2) - create(:personal_access_token, :revoked, :impersonation, user: user2) + with_them do + let(:params) { { user: by_user } } - params[:users] = [user] + it 'returns tokens by user' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end - - it { - is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token, - revoked_personal_access_token, expired_personal_access_token, - revoked_impersonation_token, expired_impersonation_token) - } end + end - describe 'with sort order' do - before do - params[:sort] = 'id_asc' - end - - it 'sorts records as per the specified sort order' do - expect(subject).to match_array(PersonalAccessToken.all.order(id: :asc)) - end + describe 'by users' do + where(:by_users, :expected_tokens) do + nil | tokens.keys + lazy { [user] } | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation] + lazy { [other_user] } | [:active_other] + lazy { [user, other_user] } | [:active, :active_other, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation] + [] | [] # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands end - describe 'without impersonation' do - before do - params[:impersonation] = false - end - - it { is_expected.to contain_exactly(active_personal_access_token, revoked_personal_access_token, expired_personal_access_token, project_access_token) } - - describe 'with active state' do - before do - params[:state] = 'active' - end - - it { is_expected.to contain_exactly(active_personal_access_token, project_access_token) } - end - - describe 'with inactive state' do - before do - params[:state] = 'inactive' - end + with_them do + let(:params) { { users: by_users } } - it { is_expected.to contain_exactly(revoked_personal_access_token, expired_personal_access_token) } + it 'returns tokens by users' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end end + end - describe 'with impersonation' do - before do - params[:impersonation] = true - end - - it { is_expected.to contain_exactly(active_impersonation_token, revoked_impersonation_token, expired_impersonation_token) } - - describe 'with active state' do - before do - params[:state] = 'active' - end - - it { is_expected.to contain_exactly(active_impersonation_token) } - end + describe 'by impersonation' do + where(:by_impersonation, :expected_tokens) do + nil | tokens.keys + true | [:active_impersonation, :expired_impersonation, :revoked_impersonation] + false | [:active, :active_other, :expired, :revoked, :bot] + 'other' | tokens.keys + end - describe 'with inactive state' do - before do - params[:state] = 'inactive' - end + with_them do + let(:params) { { impersonation: by_impersonation } } - it { is_expected.to contain_exactly(revoked_impersonation_token, expired_impersonation_token) } + it 'returns tokens by impersonation' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end end + end - describe 'with active state' do - before do - params[:state] = 'active' - end - - it { is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token, project_access_token) } + describe 'by state' do + where(:by_state, :expected_tokens) do + nil | tokens.keys + 'active' | [:active, :active_other, :active_impersonation, :bot] + 'inactive' | [:expired, :revoked, :expired_impersonation, :revoked_impersonation] + 'other' | tokens.keys end - describe 'with inactive state' do - before do - params[:state] = 'inactive' - end + with_them do + let(:params) { { state: by_state } } - it do - is_expected.to contain_exactly(expired_personal_access_token, revoked_personal_access_token, - expired_impersonation_token, revoked_impersonation_token) + it 'returns tokens by state' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end end + end - describe 'with id' do - subject { finder(params).find_by_id(active_personal_access_token.id) } - - it { is_expected.to eq(active_personal_access_token) } + describe 'by owner type' do + where(:by_owner_type, :expected_tokens) do + nil | tokens.keys + 'human' | [:active, :active_other, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation] + 'other' | tokens.keys + end - describe 'with impersonation' do - before do - params[:impersonation] = true - end + with_them do + let(:params) { { owner_type: by_owner_type } } - it { is_expected.to be_nil } + it 'returns tokens by owner type' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end end + end - describe 'with token' do - subject { finder(params).find_by_token(active_personal_access_token.token) } - - it { is_expected.to eq(active_personal_access_token) } + describe 'by revoked state' do + where(:by_revoked_state, :expected_tokens) do + nil | [:active, :active_other, :expired, :active_impersonation, :expired_impersonation, :bot] + true | [:revoked, :revoked_impersonation] + false | [:active, :active_other, :expired, :active_impersonation, :expired_impersonation, :bot] + end - describe 'with impersonation' do - before do - params[:impersonation] = true - end + with_them do + let(:params) { { revoked: by_revoked_state } } - it { is_expected.to be_nil } + it 'returns tokens by revoked state' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end end end - describe 'with user' do - let(:user2) { create(:user) } - let!(:other_user_active_personal_access_token) { create(:personal_access_token, user: user2) } - let!(:other_user_expired_personal_access_token) { create(:personal_access_token, :expired, user: user2) } - let!(:other_user_revoked_personal_access_token) { create(:personal_access_token, :revoked, user: user2) } - let!(:other_user_active_impersonation_token) { create(:personal_access_token, :impersonation, user: user2) } - let!(:other_user_expired_impersonation_token) { create(:personal_access_token, :expired, :impersonation, user: user2) } - let!(:other_user_revoked_impersonation_token) { create(:personal_access_token, :revoked, :impersonation, user: user2) } - + describe 'by created date' do before do - params[:user] = user - end - - it do - is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token, - revoked_personal_access_token, expired_personal_access_token, - revoked_impersonation_token, expired_impersonation_token) + tokens[:active_other].update!(created_at: 5.days.ago) end - describe 'filtering human tokens' do - before do - params[:owner_type] = 'human' + describe 'by created before' do + where(:by_created_before, :expected_tokens) do + 6.days.ago | [] + 2.days.ago | [:active_other] + 2.days.from_now | tokens.keys end - it { is_expected.not_to include(project_access_token) } + with_them do + let(:params) { { created_before: by_created_before } } + + it 'returns tokens by created before' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) + end + end end - describe 'without impersonation' do - before do - params[:impersonation] = false + describe 'by created after' do + where(:by_created_after, :expected_tokens) do + 6.days.ago | tokens.keys + 2.days.ago | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation, :bot] + 2.days.from_now | [] end - it { is_expected.to contain_exactly(active_personal_access_token, revoked_personal_access_token, expired_personal_access_token) } + with_them do + let(:params) { { created_after: by_created_after } } - describe 'with active state' do - before do - params[:state] = 'active' + it 'returns tokens by created before' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end - - it { is_expected.to contain_exactly(active_personal_access_token) } end + end + end - describe 'with inactive state' do - before do - params[:state] = 'inactive' - end - - it { is_expected.to contain_exactly(revoked_personal_access_token, expired_personal_access_token) } - end + describe 'by last used date' do + before do + PersonalAccessToken.update_all(last_used_at: Time.now) + tokens[:active_other].update!(last_used_at: 5.days.ago) end - describe 'with impersonation' do - before do - params[:impersonation] = true + describe 'by last used before' do + where(:by_last_used_before, :expected_tokens) do + 6.days.ago | [] + 2.days.ago | [:active_other] + 2.days.from_now | tokens.keys end - it { is_expected.to contain_exactly(active_impersonation_token, revoked_impersonation_token, expired_impersonation_token) } + with_them do + let(:params) { { last_used_before: by_last_used_before } } - describe 'with active state' do - before do - params[:state] = 'active' + it 'returns tokens by last used before' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end + end + end - it { is_expected.to contain_exactly(active_impersonation_token) } + describe 'by last used after' do + where(:by_last_used_after, :expected_tokens) do + 6.days.ago | tokens.keys + 2.days.ago | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation, :bot] + 2.days.from_now | [] end - describe 'with inactive state' do - before do - params[:state] = 'inactive' - end + with_them do + let(:params) { { last_used_after: by_last_used_after } } - it { is_expected.to contain_exactly(revoked_impersonation_token, expired_impersonation_token) } + it 'returns tokens by last used after' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) + end end end + end - describe 'with active state' do - before do - params[:state] = 'active' - end - - it { is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token) } + describe 'by search' do + where(:by_search, :expected_tokens) do + nil | tokens.keys + 'my_pat' | [:active, :active_other] + 'other' | [] end - describe 'with inactive state' do - before do - params[:state] = 'inactive' - end + with_them do + let(:params) { { search: by_search } } - it do - is_expected.to contain_exactly(expired_personal_access_token, revoked_personal_access_token, - expired_impersonation_token, revoked_impersonation_token) + it 'returns tokens by search' do + is_expected.to match_array(tokens.values_at(*expected_tokens)) end end + end - describe 'with id' do - subject { finder(params).find_by_id(active_personal_access_token.id) } - - it { is_expected.to eq(active_personal_access_token) } + describe 'sort' do + where(:sort, :expected_tokens) do + nil | tokens.keys + 'id_asc' | [:active, :active_other, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation, :bot] + 'id_desc' | [:bot, :revoked_impersonation, :expired_impersonation, :active_impersonation, :revoked, :expired, :active_other, :active] + 'other' | tokens.keys + end - describe 'with impersonation' do - before do - params[:impersonation] = true - end + with_them do + let(:params) { { sort: sort } } - it { is_expected.to be_nil } + it 'returns ordered tokens' do + expect(subject.map(&:id)).to eq(tokens.values_at(*expected_tokens).map(&:id)) end end + end - describe 'with token' do - subject { finder(params).find_by_token(active_personal_access_token.token) } + describe 'delegates' do + subject { described_class.new(params, current_user) } - it { is_expected.to eq(active_personal_access_token) } + describe '#find_by_id' do + it 'returns token by id' do + expect(subject.find_by_id(tokens[:active].id)).to eq(tokens[:active]) + end + end - describe 'with impersonation' do - before do - params[:impersonation] = true - end + describe '#find_by_token' do + it 'returns token by token' do + expect(subject.find_by_token(tokens[:active].token)).to eq(tokens[:active]) + end + end - it { is_expected.to be_nil } + describe '#find' do + it 'returns token by id' do + expect(subject.find(tokens[:active].id)).to eq(tokens[:active]) end end end diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb index 02153715eac..9fecbfb71fc 100644 --- a/spec/finders/projects_finder_spec.rb +++ b/spec/finders/projects_finder_spec.rb @@ -392,6 +392,23 @@ RSpec.describe ProjectsFinder do it { is_expected.to match_array([project]) } end + describe 'filter by language' do + let_it_be(:ruby) { create(:programming_language, name: 'Ruby') } + let_it_be(:repository_language) { create(:repository_language, project: internal_project, programming_language: ruby) } + + let(:params) { { language: ruby.id } } + + it { is_expected.to match_array([internal_project]) } + + context 'when project_language_search feature flag disabled' do + before do + stub_feature_flags(project_language_search: false) + end + + it { is_expected.to match_array([internal_project, public_project]) } + end + end + describe 'sorting' do let_it_be(:more_projects) do [ diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb index 0bf9b228c8a..2af23c466fb 100644 --- a/spec/finders/tags_finder_spec.rb +++ b/spec/finders/tags_finder_spec.rb @@ -68,6 +68,14 @@ RSpec.describe TagsFinder do expect(result.count).to eq(1) end + it 'filters tags by name with wildcard' do + result = load_tags({ search: 'v1.*.0' }) + + expect(result.first.name).to eq('v1.0.0') + expect(result.second.name).to eq('v1.1.0') + expect(result.count).to eq(2) + end + it 'filters tags by nonexistent name that begins with' do result = load_tags({ search: '^nope' }) @@ -79,6 +87,11 @@ RSpec.describe TagsFinder do expect(result.count).to eq(0) end + it 'filters tags by nonexistent name with wildcard' do + result = load_tags({ search: 'n*e' }) + expect(result.count).to eq(0) + end + context 'when search is not a string' do it 'returns no matches' do result = load_tags({ search: { 'a' => 'b' } }) diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb index 5611a67e977..bcead6b0170 100644 --- a/spec/finders/todos_finder_spec.rb +++ b/spec/finders/todos_finder_spec.rb @@ -327,9 +327,9 @@ RSpec.describe TodosFinder do it 'returns the expected types' do expected_result = if Gitlab.ee? - %w[Epic Issue MergeRequest DesignManagement::Design AlertManagement::Alert] + %w[Epic Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert] else - %w[Issue MergeRequest DesignManagement::Design AlertManagement::Alert] + %w[Issue WorkItem MergeRequest DesignManagement::Design AlertManagement::Alert] end expect(described_class.todo_types).to contain_exactly(*expected_result) diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb index 271dce44db7..5cf845a87b2 100644 --- a/spec/finders/users_finder_spec.rb +++ b/spec/finders/users_finder_spec.rb @@ -8,9 +8,7 @@ RSpec.describe UsersFinder do let_it_be(:project_bot) { create(:user, :project_bot) } - context 'with a normal user' do - let_it_be(:user) { create(:user) } - + shared_examples 'executes users finder as normal user' do it 'returns searchable users' do users = described_class.new(user).execute @@ -97,37 +95,35 @@ RSpec.describe UsersFinder do end end - context 'with an admin user', :enable_admin_mode do - let_it_be(:admin) { create(:admin) } - + shared_examples 'executes users finder as admin' do it 'filters by external users' do - users = described_class.new(admin, external: true).execute + users = described_class.new(user, external: true).execute expect(users).to contain_exactly(external_user) end it 'returns all users' do - users = described_class.new(admin).execute + users = described_class.new(user).execute - expect(users).to contain_exactly(admin, normal_user, blocked_user, unconfirmed_user, banned_user, external_user, omniauth_user, internal_user, admin_user, project_bot) + expect(users).to contain_exactly(user, normal_user, blocked_user, unconfirmed_user, banned_user, external_user, omniauth_user, internal_user, admin_user, project_bot) end it 'filters by blocked users' do - users = described_class.new(admin, blocked: true).execute + users = described_class.new(user, blocked: true).execute expect(users).to contain_exactly(blocked_user) end it 'filters by active users' do - users = described_class.new(admin, active: true).execute + users = described_class.new(user, active: true).execute - expect(users).to contain_exactly(admin, normal_user, unconfirmed_user, external_user, omniauth_user, admin_user, project_bot) + expect(users).to contain_exactly(user, normal_user, unconfirmed_user, external_user, omniauth_user, admin_user, project_bot) end it 'returns only admins' do - users = described_class.new(admin, admins: true).execute + users = described_class.new(user, admins: true).execute - expect(users).to contain_exactly(admin, admin_user) + expect(users).to contain_exactly(user, admin_user) end it 'filters by custom attributes' do @@ -137,7 +133,7 @@ RSpec.describe UsersFinder do create :user_custom_attribute, user: internal_user, key: 'foo', value: 'foo' users = described_class.new( - admin, + user, custom_attributes: { foo: 'foo', bar: 'bar' } ).execute @@ -145,10 +141,34 @@ RSpec.describe UsersFinder do end it 'filters by private emails search' do - users = described_class.new(admin, search: normal_user.email).execute + users = described_class.new(user, search: normal_user.email).execute expect(users).to contain_exactly(normal_user) end end + + context 'with a normal user' do + let_it_be(:user) { create(:user) } + + it_behaves_like 'executes users finder as normal user' + end + + context 'with an admin user' do + let_it_be(:user) { create(:admin) } + + context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do + it_behaves_like 'executes users finder as admin' + end + + context 'when admin mode setting is enabled' do + context 'when in admin mode', :enable_admin_mode do + it_behaves_like 'executes users finder as admin' + end + + context 'when not in admin mode' do + it_behaves_like 'executes users finder as normal user' + end + end + end end end diff --git a/spec/finders/work_items/work_items_finder_spec.rb b/spec/finders/work_items/work_items_finder_spec.rb index fe400688a23..ab8a9ba9204 100644 --- a/spec/finders/work_items/work_items_finder_spec.rb +++ b/spec/finders/work_items/work_items_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe WorkItems::WorkItemsFinder do +RSpec.describe WorkItems::WorkItemsFinder, feature_category: :team_planning do using RSpec::Parameterized::TableSyntax include_context 'WorkItemsFinder context' |