diff options
Diffstat (limited to 'spec/finders')
21 files changed, 478 insertions, 128 deletions
diff --git a/spec/finders/admin/projects_finder_spec.rb b/spec/finders/admin/projects_finder_spec.rb index 03eb41ddfb6..8522170874f 100644 --- a/spec/finders/admin/projects_finder_spec.rb +++ b/spec/finders/admin/projects_finder_spec.rb @@ -88,7 +88,7 @@ RSpec.describe Admin::ProjectsFinder do context 'filter by abandoned' do before do - private_project.update(last_activity_at: Time.zone.now - 6.months - 1.minute) + private_project.update!(last_activity_at: Time.zone.now - 6.months - 1.minute) end let(:params) { { abandoned: true } } @@ -98,7 +98,7 @@ RSpec.describe Admin::ProjectsFinder do context 'filter by last_repository_check_failed' do before do - private_project.update(last_repository_check_failed: true) + private_project.update!(last_repository_check_failed: true) end let(:params) { { last_repository_check_failed: true } } diff --git a/spec/finders/alert_management/alerts_finder_spec.rb b/spec/finders/alert_management/alerts_finder_spec.rb index 7bf9047704b..926446b31d5 100644 --- a/spec/finders/alert_management/alerts_finder_spec.rb +++ b/spec/finders/alert_management/alerts_finder_spec.rb @@ -5,9 +5,9 @@ require 'spec_helper' RSpec.describe AlertManagement::AlertsFinder, '#execute' do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project) } - let_it_be(:alert_1) { create(:alert_management_alert, :all_fields, :resolved, project: project, ended_at: 1.year.ago, events: 2, severity: :high) } - let_it_be(:alert_2) { create(:alert_management_alert, :all_fields, :ignored, project: project, events: 1, severity: :critical) } - let_it_be(:alert_3) { create(:alert_management_alert, :all_fields) } + let_it_be(:resolved_alert) { create(:alert_management_alert, :all_fields, :resolved, project: project, ended_at: 1.year.ago, events: 2, severity: :high) } + let_it_be(:ignored_alert) { create(:alert_management_alert, :all_fields, :ignored, project: project, events: 1, severity: :critical) } + let_it_be(:triggered_alert) { create(:alert_management_alert, :all_fields) } let(:params) { {} } describe '#execute' do @@ -23,13 +23,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do end context 'empty params' do - it { is_expected.to contain_exactly(alert_1, alert_2) } + it { is_expected.to contain_exactly(resolved_alert, ignored_alert) } end context 'iid given' do - let(:params) { { iid: alert_1.iid } } + let(:params) { { iid: resolved_alert.iid } } - it { is_expected.to match_array(alert_1) } + it { is_expected.to match_array(resolved_alert) } context 'unknown iid' do let(:params) { { iid: 'unknown' } } @@ -41,13 +41,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do context 'status given' do let(:params) { { status: AlertManagement::Alert::STATUSES[:resolved] } } - it { is_expected.to match_array(alert_1) } + it { is_expected.to match_array(resolved_alert) } context 'with an array of statuses' do - let(:alert_3) { create(:alert_management_alert) } + let(:triggered_alert) { create(:alert_management_alert) } let(:params) { { status: [AlertManagement::Alert::STATUSES[:resolved]] } } - it { is_expected.to match_array(alert_1) } + it { is_expected.to match_array(resolved_alert) } end context 'with no alerts of status' do @@ -59,13 +59,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do context 'with an empty status array' do let(:params) { { status: [] } } - it { is_expected.to match_array([alert_1, alert_2]) } + it { is_expected.to match_array([resolved_alert, ignored_alert]) } end context 'with an nil status' do let(:params) { { status: nil } } - it { is_expected.to match_array([alert_1, alert_2]) } + it { is_expected.to match_array([resolved_alert, ignored_alert]) } end end @@ -74,13 +74,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do context 'sorts alerts ascending' do let(:params) { { sort: 'created_asc' } } - it { is_expected.to eq [alert_1, alert_2] } + it { is_expected.to eq [resolved_alert, ignored_alert] } end context 'sorts alerts descending' do let(:params) { { sort: 'created_desc' } } - it { is_expected.to eq [alert_2, alert_1] } + it { is_expected.to eq [ignored_alert, resolved_alert] } end end @@ -88,13 +88,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do context 'sorts alerts ascending' do let(:params) { { sort: 'updated_asc' } } - it { is_expected.to eq [alert_1, alert_2] } + it { is_expected.to eq [resolved_alert, ignored_alert] } end context 'sorts alerts descending' do let(:params) { { sort: 'updated_desc' } } - it { is_expected.to eq [alert_2, alert_1] } + it { is_expected.to eq [ignored_alert, resolved_alert] } end end @@ -102,13 +102,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do context 'sorts alerts ascending' do let(:params) { { sort: 'started_at_asc' } } - it { is_expected.to eq [alert_1, alert_2] } + it { is_expected.to eq [resolved_alert, ignored_alert] } end context 'sorts alerts descending' do let(:params) { { sort: 'started_at_desc' } } - it { is_expected.to eq [alert_2, alert_1] } + it { is_expected.to eq [ignored_alert, resolved_alert] } end end @@ -116,13 +116,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do context 'sorts alerts ascending' do let(:params) { { sort: 'ended_at_asc' } } - it { is_expected.to eq [alert_1, alert_2] } + it { is_expected.to eq [resolved_alert, ignored_alert] } end context 'sorts alerts descending' do let(:params) { { sort: 'ended_at_desc' } } - it { is_expected.to eq [alert_2, alert_1] } + it { is_expected.to eq [ignored_alert, resolved_alert] } end end @@ -133,13 +133,13 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do context 'sorts alerts ascending' do let(:params) { { sort: 'event_count_asc' } } - it { is_expected.to eq [alert_2, alert_1, alert_count_3, alert_count_6] } + it { is_expected.to eq [ignored_alert, resolved_alert, alert_count_3, alert_count_6] } end context 'sorts alerts descending' do let(:params) { { sort: 'event_count_desc' } } - it { is_expected.to eq [alert_count_6, alert_count_3, alert_1, alert_2] } + it { is_expected.to eq [alert_count_6, alert_count_3, resolved_alert, ignored_alert] } end end diff --git a/spec/finders/autocomplete/move_to_project_finder_spec.rb b/spec/finders/autocomplete/move_to_project_finder_spec.rb index 61328a5335a..fb2de908777 100644 --- a/spec/finders/autocomplete/move_to_project_finder_spec.rb +++ b/spec/finders/autocomplete/move_to_project_finder_spec.rb @@ -22,14 +22,14 @@ RSpec.describe Autocomplete::MoveToProjectFinder do expect(finder.execute).to be_empty end - it 'returns projects equal or above Gitlab::Access::REPORTER ordered by name' do + it 'returns projects equal or above Gitlab::Access::REPORTER' do reporter_project.add_reporter(user) developer_project.add_developer(user) maintainer_project.add_maintainer(user) finder = described_class.new(user, project_id: project.id) - expect(finder.execute.to_a).to eq([reporter_project, developer_project, maintainer_project]) + expect(finder.execute.to_a).to contain_exactly(reporter_project, developer_project, maintainer_project) end it 'does not include the source project' do @@ -53,7 +53,7 @@ RSpec.describe Autocomplete::MoveToProjectFinder do it 'does not return projects for which issues are disabled' do reporter_project.add_reporter(user) - reporter_project.update(issues_enabled: false) + reporter_project.update!(issues_enabled: false) other_reporter_project = create(:project) other_reporter_project.add_reporter(user) @@ -88,10 +88,10 @@ RSpec.describe Autocomplete::MoveToProjectFinder do wadus_project.add_maintainer(user) expect(described_class.new(user, project_id: project.id).execute.to_a) - .to eq([foo_project, wadus_project]) + .to contain_exactly(foo_project, wadus_project) expect(described_class.new(user, project_id: project.id, search: 'wadus').execute.to_a) - .to eq([wadus_project]) + .to contain_exactly(wadus_project) end it 'allows searching by parent namespace' do diff --git a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb index bdb0bc9b561..c0434b5f371 100644 --- a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb +++ b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb @@ -59,6 +59,8 @@ RSpec.describe Ci::DailyBuildGroupReportResultsFinder do end end + private + def create_daily_coverage(group_name, coverage, date) create( :ci_daily_build_group_report_result, 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 ca6e0793d55..196fde5efe0 100644 --- a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb +++ b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb @@ -115,7 +115,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do context 'with multiple irrelevant merge_request_diffs' do before do - merge_request.update(target_branch: 'v1.0.0') + merge_request.update!(target_branch: 'v1.0.0') end it_behaves_like 'returning pipelines with proper ordering' diff --git a/spec/finders/design_management/designs_finder_spec.rb b/spec/finders/design_management/designs_finder_spec.rb index 696327cc49c..0133095827d 100644 --- a/spec/finders/design_management/designs_finder_spec.rb +++ b/spec/finders/design_management/designs_finder_spec.rb @@ -8,9 +8,9 @@ RSpec.describe DesignManagement::DesignsFinder do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :private) } let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:design1) { create(:design, :with_file, issue: issue, versions_count: 1) } - let_it_be(:design2) { create(:design, :with_file, issue: issue, versions_count: 1) } - let_it_be(:design3) { create(:design, :with_file, issue: issue, versions_count: 1) } + let_it_be(:design1) { create(:design, :with_file, issue: issue, versions_count: 1, relative_position: 3) } + let_it_be(:design2) { create(:design, :with_file, issue: issue, versions_count: 1, relative_position: 2) } + let_it_be(:design3) { create(:design, :with_file, issue: issue, versions_count: 1, relative_position: 1) } let(:params) { {} } subject(:designs) { described_class.new(issue, user, params).execute } @@ -38,8 +38,28 @@ RSpec.describe DesignManagement::DesignsFinder do enable_design_management end - it 'returns the designs' do - is_expected.to contain_exactly(design1, design2, design3) + it 'returns the designs sorted by their relative position' do + is_expected.to eq([design3, design2, design1]) + end + + context 'when the :reorder_designs feature is enabled for the project' do + before do + stub_feature_flags(reorder_designs: project) + end + + it 'returns the designs sorted by their relative position' do + is_expected.to eq([design3, design2, design1]) + end + end + + context 'when the :reorder_designs feature is disabled' do + before do + stub_feature_flags(reorder_designs: false) + end + + it 'returns the designs sorted by ID' do + is_expected.to eq([design1, design2, design3]) + end end context 'when argument is the ids of designs' do diff --git a/spec/finders/fork_targets_finder_spec.rb b/spec/finders/fork_targets_finder_spec.rb index 3c66f4e5757..7208f46cfff 100644 --- a/spec/finders/fork_targets_finder_spec.rb +++ b/spec/finders/fork_targets_finder_spec.rb @@ -10,15 +10,19 @@ RSpec.describe ForkTargetsFinder do let!(:maintained_group) do create(:group).tap { |g| g.add_maintainer(user) } end + let!(:owned_group) do create(:group).tap { |g| g.add_owner(user) } end + let!(:developer_group) do create(:group).tap { |g| g.add_developer(user) } end + let!(:reporter_group) do create(:group).tap { |g| g.add_reporter(user) } end + let!(:guest_group) do create(:group).tap { |g| g.add_guest(user) } end diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb index 77ef546e083..2f9303606b1 100644 --- a/spec/finders/group_descendants_finder_spec.rb +++ b/spec/finders/group_descendants_finder_spec.rb @@ -122,7 +122,7 @@ RSpec.describe GroupDescendantsFinder do it 'does not include projects shared with the group' do project = create(:project, namespace: group) other_project = create(:project) - other_project.project_group_links.create(group: group, + other_project.project_group_links.create!(group: group, group_access: Gitlab::Access::MAINTAINER) expect(finder.execute).to contain_exactly(project) diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb index 14f2bb017c6..c66fdb19260 100644 --- a/spec/finders/group_projects_finder_spec.rb +++ b/spec/finders/group_projects_finder_spec.rb @@ -51,7 +51,7 @@ RSpec.describe GroupProjectsFinder 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) + shared_project_4.project_group_links.create!(group_access: Gitlab::Access::REPORTER, group: group) end let(:params) { { min_access_level: Gitlab::Access::MAINTAINER } } @@ -76,7 +76,7 @@ RSpec.describe GroupProjectsFinder do context "with external user" do before do - current_user.update(external: true) + current_user.update!(external: true) end it { is_expected.to match_array([shared_project_2, shared_project_1]) } @@ -107,7 +107,7 @@ RSpec.describe GroupProjectsFinder do context "with external user" do before do - current_user.update(external: true) + current_user.update!(external: true) end context 'with subgroups projects' do diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index 672318c292e..fb7d4e808fe 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -185,9 +185,9 @@ RSpec.describe IssuesFinder do let(:params) { { milestone_title: group_milestone.title } } before do - project2.update(namespace: group) - issue2.update(milestone: group_milestone) - issue3.update(milestone: group_milestone) + project2.update!(namespace: group) + issue2.update!(milestone: group_milestone) + issue3.update!(milestone: group_milestone) end it 'returns issues assigned to that group milestone' do @@ -668,6 +668,58 @@ RSpec.describe IssuesFinder do end end + context 'filtering by issue type' do + let_it_be(:incident_issue) { create(:incident, project: project1) } + + context 'no type given' do + let(:params) { { issue_types: [] } } + + it 'returns all issues' do + expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4) + end + end + + context 'incident type' do + let(:params) { { issue_types: ['incident'] } } + + it 'returns incident issues' do + expect(issues).to contain_exactly(incident_issue) + end + end + + context 'issue type' do + let(:params) { { issue_types: ['issue'] } } + + it 'returns all issues with type issue' do + expect(issues).to contain_exactly(issue1, issue2, issue3, issue4) + end + end + + context 'multiple params' do + let(:params) { { issue_types: %w(issue incident) } } + + it 'returns all issues' do + expect(issues).to contain_exactly(incident_issue, issue1, issue2, issue3, issue4) + end + end + + context 'without array' do + let(:params) { { issue_types: 'incident' } } + + it 'returns incident issues' do + expect(issues).to contain_exactly(incident_issue) + end + end + + context 'invalid params' do + let(:params) { { issue_types: ['nonsense'] } } + + it 'returns no issues' do + expect(issues).to eq(Issue.none) + end + end + end + context 'when the user is unauthorized' do let(:search_user) { nil } diff --git a/spec/finders/joined_groups_finder_spec.rb b/spec/finders/joined_groups_finder_spec.rb index 8f826ef67ec..058db735708 100644 --- a/spec/finders/joined_groups_finder_spec.rb +++ b/spec/finders/joined_groups_finder_spec.rb @@ -55,7 +55,7 @@ RSpec.describe JoinedGroupsFinder do context 'external users' do before do - profile_visitor.update(external: true) + profile_visitor.update!(external: true) end context 'if not a member' do diff --git a/spec/finders/members_finder_spec.rb b/spec/finders/members_finder_spec.rb index b14ad84a96e..3ef8d6a01aa 100644 --- a/spec/finders/members_finder_spec.rb +++ b/spec/finders/members_finder_spec.rb @@ -10,16 +10,39 @@ RSpec.describe MembersFinder, '#execute' do let_it_be(:user2) { create(:user) } let_it_be(:user3) { create(:user) } let_it_be(:user4) { create(:user) } + let_it_be(:blocked_user) { create(:user, :blocked) } it 'returns members for project and parent groups' do nested_group.request_access(user1) member1 = group.add_maintainer(user2) member2 = nested_group.add_maintainer(user3) member3 = project.add_maintainer(user4) + blocked_member = project.add_maintainer(blocked_user) result = described_class.new(project, user2).execute - expect(result).to contain_exactly(member1, member2, member3) + expect(result).to contain_exactly(member1, member2, member3, blocked_member) + end + + it 'returns owners and maintainers' do + member1 = group.add_owner(user1) + group.add_developer(user2) + member3 = project.add_maintainer(user3) + project.add_developer(user4) + + result = described_class.new(project, user2, params: { owners_and_maintainers: true }).execute + + expect(result).to contain_exactly(member1, member3) + end + + it 'returns active users and excludes invited users' do + member1 = project.add_maintainer(user2) + create(:project_member, :invited, project: project, invite_email: create(:user).email) + project.add_maintainer(blocked_user) + + result = described_class.new(project, user2, params: { active_without_invites_and_requests: true }).execute + + expect(result).to contain_exactly(member1) end it 'includes only non-invite members if user do not have amdin permissions on project' do diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb index e3643698012..5b86c891e47 100644 --- a/spec/finders/merge_requests_finder_spec.rb +++ b/spec/finders/merge_requests_finder_spec.rb @@ -85,6 +85,31 @@ RSpec.describe MergeRequestsFinder do expect(merge_requests).to contain_exactly(merge_request5) end + context 'filters by merged_at date' do + before do + merge_request1.metrics.update!(merged_at: 5.days.ago) + merge_request2.metrics.update!(merged_at: 10.days.ago) + end + + describe 'merged_after' do + subject { described_class.new(user, merged_after: 6.days.ago).execute } + + it { is_expected.to eq([merge_request1]) } + end + + describe 'merged_before' do + subject { described_class.new(user, merged_before: 6.days.ago).execute } + + it { is_expected.to eq([merge_request2]) } + end + + describe 'when both merged_after and merged_before is given' do + subject { described_class.new(user, merged_after: 15.days.ago, merged_before: 6.days.ago).execute } + + it { is_expected.to eq([merge_request2]) } + end + end + context 'filtering by group' do it 'includes all merge requests when user has access excluding merge requests from projects the user does not have access to' do private_project = allow_gitaly_n_plus_1 { create(:project, :private, group: group) } @@ -192,43 +217,59 @@ RSpec.describe MergeRequestsFinder do expect(merge_requests).to contain_exactly(merge_request3) end - describe 'WIP state' do + describe 'draft state' do let!(:wip_merge_request1) { create(:merge_request, :simple, author: user, source_project: project5, target_project: project5, title: 'WIP: thing') } let!(:wip_merge_request2) { create(:merge_request, :simple, author: user, source_project: project6, target_project: project6, title: 'wip thing') } let!(:wip_merge_request3) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project1, title: '[wip] thing') } let!(:wip_merge_request4) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2, title: 'wip: thing') } + let!(:draft_merge_request1) { create(:merge_request, :simple, author: user, source_branch: 'draft1', source_project: project5, target_project: project5, title: 'Draft: thing') } + let!(:draft_merge_request2) { create(:merge_request, :simple, author: user, source_branch: 'draft2', source_project: project6, target_project: project6, title: '[draft] thing') } + let!(:draft_merge_request3) { create(:merge_request, :simple, author: user, source_branch: 'draft3', source_project: project1, target_project: project1, title: '(draft) thing') } + let!(:draft_merge_request4) { create(:merge_request, :simple, author: user, source_branch: 'draft4', source_project: project1, target_project: project2, title: 'Draft - thing') } - it 'filters by wip' do - params = { wip: 'yes' } + [:wip, :draft].each do |draft_param_key| + it "filters by #{draft_param_key}" do + params = { draft_param_key => 'yes' } - merge_requests = described_class.new(user, params).execute + merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly(merge_request4, merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4) - end + expect(merge_requests).to contain_exactly( + merge_request4, merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4, + draft_merge_request1, draft_merge_request2, draft_merge_request3, draft_merge_request4 + ) + end - it 'filters by not wip' do - params = { wip: 'no' } + context 'when merge_request_draft_filter is disabled' do + it 'does not include draft merge requests' do + stub_feature_flags(merge_request_draft_filter: false) - merge_requests = described_class.new(user, params).execute + merge_requests = described_class.new(user, { draft_param_key => 'yes' }).execute - expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3) - end + expect(merge_requests).to contain_exactly( + merge_request4, merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4 + ) + end + end - it 'returns all items if no valid wip param exists' do - params = { wip: '' } + it "filters by not #{draft_param_key}" do + params = { draft_param_key => 'no' } - merge_requests = described_class.new(user, params).execute + merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly( - merge_request1, merge_request2, merge_request3, merge_request4, - merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, - wip_merge_request4) - end + expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3) + end - it 'adds wip to scalar params' do - scalar_params = described_class.scalar_params + it "returns all items if no valid #{draft_param_key} param exists" do + params = { draft_param_key => '' } + + merge_requests = described_class.new(user, params).execute - expect(scalar_params).to include(:wip, :assignee_id) + expect(merge_requests).to contain_exactly( + merge_request1, merge_request2, merge_request3, merge_request4, + merge_request5, wip_merge_request1, wip_merge_request2, wip_merge_request3, wip_merge_request4, + draft_merge_request1, draft_merge_request2, draft_merge_request3, draft_merge_request4 + ) + end end context 'filter by deployment' do @@ -265,6 +306,14 @@ RSpec.describe MergeRequestsFinder do end end + describe '.scalar_params' do + it 'contains scalar params related to merge requests' do + scalar_params = described_class.scalar_params + + expect(scalar_params).to include(:wip, :draft, :assignee_id) + end + end + context 'assignee filtering' do let(:issuables) { described_class.new(user, params).execute } @@ -311,9 +360,8 @@ RSpec.describe MergeRequestsFinder do let(:group_milestone) { create(:milestone, group: group) } before do - project2.update(namespace: group) - merge_request2.update(milestone: group_milestone) - merge_request3.update(milestone: group_milestone) + merge_request1.update!(milestone: group_milestone) + merge_request2.update!(milestone: group_milestone) end it 'returns merge requests assigned to that group milestone' do @@ -321,7 +369,7 @@ RSpec.describe MergeRequestsFinder do merge_requests = described_class.new(user, params).execute - expect(merge_requests).to contain_exactly(merge_request2, merge_request3) + expect(merge_requests).to contain_exactly(merge_request1, merge_request2) end context 'using NOT' do @@ -330,7 +378,7 @@ RSpec.describe MergeRequestsFinder do 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) + expect(merge_requests).to contain_exactly(merge_request3, merge_request4, merge_request5) end end end diff --git a/spec/finders/milestones_finder_spec.rb b/spec/finders/milestones_finder_spec.rb index 5920c185c64..6e486671132 100644 --- a/spec/finders/milestones_finder_spec.rb +++ b/spec/finders/milestones_finder_spec.rb @@ -56,6 +56,14 @@ RSpec.describe MilestonesFinder do milestone_3.close end + it 'filters by id' do + params[:ids] = [milestone_1.id, milestone_2.id] + + result = described_class.new(params).execute + + expect(result).to contain_exactly(milestone_1, milestone_2) + end + it 'filters by active state' do params[:state] = 'active' result = described_class.new(params).execute diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb index 94954f4153b..c8913329839 100644 --- a/spec/finders/personal_access_tokens_finder_spec.rb +++ b/spec/finders/personal_access_tokens_finder_spec.rb @@ -3,13 +3,14 @@ require 'spec_helper' RSpec.describe PersonalAccessTokensFinder do - def finder(options = {}) - described_class.new(options) + def finder(options = {}, current_user = nil) + described_class.new(options, current_user) 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) } @@ -17,7 +18,42 @@ RSpec.describe PersonalAccessTokensFinder do let!(:expired_impersonation_token) { create(:personal_access_token, :expired, :impersonation, user: user) } let!(:revoked_impersonation_token) { create(:personal_access_token, :revoked, :impersonation, user: user) } - subject { finder(params).execute } + 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) + end + end + + context 'current_user is not allowed to read PATs' do + let(:current_user) { create(:user) } + + it { is_expected.to be_empty } + end + + context 'when user param is not set' do + let(:params) { {} } + + 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) + end + + context 'when current_user is not an administrator' do + let(:current_user) { create(:user) } + + it { is_expected.to be_empty } + end + end + end describe 'without user' do it do diff --git a/spec/finders/personal_projects_finder_spec.rb b/spec/finders/personal_projects_finder_spec.rb index 62e9999fdd6..493ec0e569e 100644 --- a/spec/finders/personal_projects_finder_spec.rb +++ b/spec/finders/personal_projects_finder_spec.rb @@ -37,7 +37,7 @@ RSpec.describe PersonalProjectsFinder do context 'external' do before do - current_user.update(external: true) + current_user.update!(external: true) end it { is_expected.to eq([public_project, private_project]) } diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb index bd71a8186ad..29b6dc61386 100644 --- a/spec/finders/projects_finder_spec.rb +++ b/spec/finders/projects_finder_spec.rb @@ -244,8 +244,8 @@ RSpec.describe ProjectsFinder, :do_not_mock_admin_mode do let(:params) { { last_activity_after: 60.minutes.ago } } before do - internal_project.update(last_activity_at: Time.now) - public_project.update(last_activity_at: 61.minutes.ago) + internal_project.update!(last_activity_at: Time.now) + public_project.update!(last_activity_at: 61.minutes.ago) end it { is_expected.to match_array([internal_project]) } @@ -255,8 +255,8 @@ RSpec.describe ProjectsFinder, :do_not_mock_admin_mode do let(:params) { { last_activity_before: 60.minutes.ago } } before do - internal_project.update(last_activity_at: Time.now) - public_project.update(last_activity_at: 61.minutes.ago) + internal_project.update!(last_activity_at: Time.now) + public_project.update!(last_activity_at: 61.minutes.ago) end it { is_expected.to match_array([public_project]) } diff --git a/spec/finders/releases_finder_spec.rb b/spec/finders/releases_finder_spec.rb index 3dc01570d64..e8049a9eb81 100644 --- a/spec/finders/releases_finder_spec.rb +++ b/spec/finders/releases_finder_spec.rb @@ -3,29 +3,68 @@ require 'spec_helper' RSpec.describe ReleasesFinder do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } - let(:params) { {} } + let(:user) { create(:user) } + let(:group) { create :group } + let(:project) { create(:project, :repository, group: group) } + let(:params) { {} } + let(:args) { {} } let(:repository) { project.repository } let(:v1_0_0) { create(:release, project: project, tag: 'v1.0.0') } let(:v1_1_0) { create(:release, project: project, tag: 'v1.1.0') } - let(:finder) { described_class.new(project, user, params) } before do v1_0_0.update_attribute(:released_at, 2.days.ago) v1_1_0.update_attribute(:released_at, 1.day.ago) end - describe '#execute' do - subject { finder.execute(**args) } + shared_examples_for 'when the user is not part of the project' do + it 'returns no releases' do + is_expected.to be_empty + end + end + + # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27716 + shared_examples_for 'when tag is nil' do + before do + v1_0_0.update_column(:tag, nil) + end + + it 'ignores rows with a nil tag' do + expect(subject.size).to eq(1) + expect(subject).to eq([v1_1_0]) + end + end + + shared_examples_for 'when a tag parameter is passed' do + let(:params) { { tag: 'v1.0.0' } } + + it 'only returns the release with the matching tag' do + expect(subject).to eq([v1_0_0]) + end + end + + shared_examples_for 'preload' do + it 'preloads associations' do + expect(Release).to receive(:preloaded).once.and_call_original + + subject + end + + context 'when preload is false' do + let(:args) { { preload: false } } - let(:args) { {} } + it 'does not preload associations' do + expect(Release).not_to receive(:preloaded) - context 'when the user is not part of the project' do - it 'returns no releases' do - is_expected.to be_empty + subject end end + end + + describe 'when parent is a project' do + subject { described_class.new(project, user, params).execute(**args) } + + it_behaves_like 'when the user is not part of the project' context 'when the user is a project developer' do before do @@ -38,39 +77,137 @@ RSpec.describe ReleasesFinder do expect(subject).to eq([v1_1_0, v1_0_0]) end - it 'preloads associations' do - expect(Release).to receive(:preloaded).once.and_call_original + it_behaves_like 'preload' + it_behaves_like 'when tag is nil' + it_behaves_like 'when a tag parameter is passed' + end + end - subject - end + describe 'when parent is a group' do + context 'without subgroups' do + let(:project2) { create(:project, :repository, namespace: group) } + let!(:v6) { create(:release, project: project2, tag: 'v6') } - context 'when preload is false' do - let(:args) { { preload: false } } + subject { described_class.new(group, user, params).execute(**args) } - it 'does not preload associations' do - expect(Release).not_to receive(:preloaded) + it_behaves_like 'when the user is not part of the project' + + context 'when the user is a project developer on one sibling project' do + before do + project.add_developer(user) + v1_0_0.update_attribute(:released_at, 3.days.ago) + v1_1_0.update_attribute(:released_at, 1.day.ago) + end - subject + it 'sorts by release date' do + expect(subject.size).to eq(2) + expect(subject).to eq([v1_1_0, v1_0_0]) end end - # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27716 - context 'when tag is nil' do + context 'when the user is a project developer on all projects' do before do - v1_0_0.update_column(:tag, nil) + project.add_developer(user) + project2.add_developer(user) + v1_0_0.update_attribute(:released_at, 3.days.ago) + v6.update_attribute(:released_at, 2.days.ago) + v1_1_0.update_attribute(:released_at, 1.day.ago) end - it 'ignores rows with a nil tag' do - expect(subject.size).to eq(1) - expect(subject).to eq([v1_1_0]) + it 'sorts by release date' do + expect(subject.size).to eq(3) + expect(subject).to eq([v1_1_0, v6, v1_0_0]) + end + + it_behaves_like 'when a tag parameter is passed' + end + end + + describe 'with subgroups' do + let(:params) { { include_subgroups: true } } + + subject { described_class.new(group, user, params).execute(**args) } + + context 'with a single-level subgroup' do + let(:subgroup) { create :group, parent: group } + let(:project2) { create(:project, :repository, namespace: subgroup) } + let!(:v6) { create(:release, project: project2, tag: 'v6') } + + it_behaves_like 'when the user is not part of the project' + + context 'when the user a project developer in the subgroup project' do + before do + project2.add_developer(user) + end + + it 'returns only the subgroup releases' do + expect(subject).to match_array([v6]) + end + end + + context 'when the user a project developer in both projects' do + before do + project.add_developer(user) + project2.add_developer(user) + v6.update_attribute(:released_at, 2.days.ago) + end + + it 'returns all releases' do + expect(subject).to match_array([v1_1_0, v1_0_0, v6]) + end + + it_behaves_like 'when a tag parameter is passed' end end - context 'when a tag parameter is passed' do - let(:params) { { tag: 'v1.0.0' } } + context 'with a multi-level subgroup' do + let(:subgroup) { create :group, parent: group } + let(:subsubgroup) { create :group, parent: subgroup } + let(:project2) { create(:project, :repository, namespace: subgroup) } + let(:project3) { create(:project, :repository, namespace: subsubgroup) } + let!(:v6) { create(:release, project: project2, tag: 'v6') } + let!(:p3) { create(:release, project: project3, tag: 'p3') } + + before do + v6.update_attribute(:released_at, 2.days.ago) + p3.update_attribute(:released_at, 3.days.ago) + end + + it_behaves_like 'when the user is not part of the project' + + context 'when the user a project developer in the subgroup and subsubgroup project' do + before do + project2.add_developer(user) + project3.add_developer(user) + end + + it 'returns only the subgroup and subsubgroup releases' do + expect(subject).to match_array([v6, p3]) + end + end + + context 'when the user a project developer in the subsubgroup project' do + before do + project3.add_developer(user) + end + + it 'returns only the subsubgroup releases' do + expect(subject).to match_array([p3]) + end + end + + context 'when the user a project developer in all projects' do + before do + project.add_developer(user) + project2.add_developer(user) + project3.add_developer(user) + end + + it 'returns all releases' do + expect(subject).to match_array([v1_1_0, v6, v1_0_0, p3]) + end - it 'only returns the release with the matching tag' do - expect(subject).to eq([v1_0_0]) + it_behaves_like 'when a tag parameter is passed' end end end diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb index 34f81e249e2..0fdd6ab402d 100644 --- a/spec/finders/template_finder_spec.rb +++ b/spec/finders/template_finder_spec.rb @@ -12,7 +12,8 @@ RSpec.describe TemplateFinder do :dockerfiles | described_class :gitignores | described_class :gitlab_ci_ymls | described_class - :licenses | ::LicenseTemplateFinder + :licenses | ::LicenseTemplateFinder + :metrics_dashboard_ymls | described_class end with_them do @@ -28,6 +29,7 @@ RSpec.describe TemplateFinder do :dockerfiles | 'Binary' :gitignores | 'Actionscript' :gitlab_ci_ymls | 'Android' + :metrics_dashboard_ymls | 'Default' end with_them do diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb index f6796398782..577ad80ede1 100644 --- a/spec/finders/todos_finder_spec.rb +++ b/spec/finders/todos_finder_spec.rb @@ -4,14 +4,14 @@ require 'spec_helper' RSpec.describe TodosFinder do describe '#execute' do - let(:user) { create(:user) } - let(:group) { create(:group) } - let(:project) { create(:project, namespace: group) } - let(:issue) { create(:issue, project: project) } - let(:merge_request) { create(:merge_request, source_project: project) } + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :repository, namespace: group) } + let_it_be(:issue) { create(:issue, project: project) } + let_it_be(:merge_request) { create(:merge_request, source_project: project) } let(:finder) { described_class } - before do + before_all do group.add_developer(user) end @@ -89,8 +89,6 @@ RSpec.describe TodosFinder do 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) @@ -131,8 +129,8 @@ RSpec.describe TodosFinder do end context 'when filtering by author' do - let(:author1) { create(:user) } - let(:author2) { create(:user) } + let_it_be(:author1) { create(:user) } + let_it_be(:author2) { create(:user) } let!(:todo1) { create(:todo, user: user, author: author1) } let!(:todo2) { create(:todo, user: user, author: author2) } @@ -154,7 +152,7 @@ RSpec.describe TodosFinder do context 'by groups' do context 'with subgroups' do - let(:subgroup) { create(:group, parent: group) } + let_it_be(:subgroup) { create(:group, parent: group) } let!(:todo3) { create(:todo, user: user, group: subgroup, target: issue) } it 'returns todos from subgroups when filtered by a group' do @@ -167,17 +165,14 @@ RSpec.describe TodosFinder do context 'filtering for multiple groups' do let_it_be(:group2) { create(:group) } let_it_be(:group3) { create(:group) } + let_it_be(:subgroup1) { create(:group, parent: group) } + let_it_be(:subgroup2) { create(:group, parent: group2) } let!(:todo1) { create(:todo, user: user, project: project, target: issue) } let!(:todo2) { create(:todo, user: user, group: group, target: merge_request) } let!(:todo3) { create(:todo, user: user, group: group2, target: merge_request) } - - let(:subgroup1) { create(:group, parent: group) } let!(:todo4) { create(:todo, user: user, group: subgroup1, target: issue) } - - let(:subgroup2) { create(:group, parent: group2) } let!(:todo5) { create(:todo, user: user, group: subgroup2, target: issue) } - let!(:todo6) { create(:todo, user: user, group: group3, target: issue) } it 'returns the expected groups' do @@ -232,6 +227,29 @@ RSpec.describe TodosFinder do expect(todos).to match_array([todo2, todo1]) end end + + context 'when filtering by target id' do + it 'returns the expected todos for the target' do + todos = finder.new(user, { type: 'Issue', target_id: issue.id }).execute + + expect(todos).to match_array([todo1]) + end + + it 'returns the expected todos for multiple target ids' do + another_issue = create(:issue, project: project) + todo3 = create(:todo, user: user, project: project, target: another_issue) + + todos = finder.new(user, { type: 'Issue', target_id: [issue.id, another_issue.id] }).execute + + expect(todos).to match_array([todo1, todo3]) + end + + it 'returns the expected todos for empty target id collection' do + todos = finder.new(user, { target_id: [] }).execute + + expect(todos).to match_array([todo1, todo2]) + end + end end context 'external authorization' do @@ -307,9 +325,9 @@ RSpec.describe TodosFinder do it 'returns the expected types' do expected_result = if Gitlab.ee? - %w[Epic Issue MergeRequest DesignManagement::Design] + %w[Epic Issue MergeRequest DesignManagement::Design AlertManagement::Alert] else - %w[Issue MergeRequest DesignManagement::Design] + %w[Issue MergeRequest DesignManagement::Design AlertManagement::Alert] end expect(described_class.todo_types).to contain_exactly(*expected_result) diff --git a/spec/finders/uploader_finder_spec.rb b/spec/finders/uploader_finder_spec.rb index 814d4b88b57..e1488f18d8a 100644 --- a/spec/finders/uploader_finder_spec.rb +++ b/spec/finders/uploader_finder_spec.rb @@ -12,7 +12,7 @@ RSpec.describe UploaderFinder do subject { described_class.new(project, secret, file_name).execute } before do - upload.save + upload.save! end context 'when successful' do @@ -32,7 +32,7 @@ RSpec.describe UploaderFinder do context 'when path traversal in file name' do before do upload.path = '/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../etc/passwd)' - upload.save + upload.save! end it 'returns nil' do |