Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/finders')
-rw-r--r--spec/finders/ci/auth_job_finder_spec.rb11
-rw-r--r--spec/finders/ci/runners_finder_spec.rb28
-rw-r--r--spec/finders/environments/environments_by_deployments_finder_spec.rb14
-rw-r--r--spec/finders/group_descendants_finder_spec.rb345
-rw-r--r--spec/finders/groups_finder_spec.rb15
-rw-r--r--spec/finders/issuables/crm_contact_filter_spec.rb45
-rw-r--r--spec/finders/issuables/crm_organization_filter_spec.rb48
-rw-r--r--spec/finders/issues_finder_spec.rb39
-rw-r--r--spec/finders/merge_requests_finder_spec.rb24
-rw-r--r--spec/finders/packages/build_infos_finder_spec.rb64
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb22
-rw-r--r--spec/finders/packages/nuget/package_finder_spec.rb2
-rw-r--r--spec/finders/personal_projects_finder_spec.rb34
-rw-r--r--spec/finders/user_group_notification_settings_finder_spec.rb238
14 files changed, 611 insertions, 318 deletions
diff --git a/spec/finders/ci/auth_job_finder_spec.rb b/spec/finders/ci/auth_job_finder_spec.rb
index 78827c9ddee..0a326699875 100644
--- a/spec/finders/ci/auth_job_finder_spec.rb
+++ b/spec/finders/ci/auth_job_finder_spec.rb
@@ -70,17 +70,6 @@ RSpec.describe Ci::AuthJobFinder do
expect(subject.user).to be_from_ci_job_token
expect(subject.user.ci_job_token_scope.source_project).to eq(job.project)
end
-
- context 'when feature flag ci_scoped_job_token is disabled' do
- before do
- stub_feature_flags(ci_scoped_job_token: false)
- end
-
- it 'does not set ci_job_token_scope on the job user' do
- expect(subject).to eq(job)
- expect(subject.user).not_to be_from_ci_job_token
- end
- end
end
end
end
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index 10d3f641e02..7e3c1abd6d1 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -59,6 +59,20 @@ RSpec.describe Ci::RunnersFinder do
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
+
+ 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
+
+ described_class.new(current_user: admin, params: { active: true }).execute
+ 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
@@ -263,7 +277,15 @@ RSpec.describe Ci::RunnersFinder do
let(:extra_params) { { search: 'runner_project_search' } }
it 'returns correct runner' do
- expect(subject).to eq([runner_project_3])
+ expect(subject).to match_array([runner_project_3])
+ end
+ end
+
+ context 'by active status' do
+ let(:extra_params) { { active: false } }
+
+ it 'returns correct runner' do
+ expect(subject).to match_array([runner_sub_group_1])
end
end
@@ -271,7 +293,7 @@ RSpec.describe Ci::RunnersFinder do
let(:extra_params) { { status_status: 'paused' } }
it 'returns correct runner' do
- expect(subject).to eq([runner_sub_group_1])
+ expect(subject).to match_array([runner_sub_group_1])
end
end
@@ -279,7 +301,7 @@ RSpec.describe Ci::RunnersFinder do
let(:extra_params) { { tag_name: %w[runner_tag] } }
it 'returns correct runner' do
- expect(subject).to eq([runner_project_5])
+ expect(subject).to match_array([runner_project_5])
end
end
diff --git a/spec/finders/environments/environments_by_deployments_finder_spec.rb b/spec/finders/environments/environments_by_deployments_finder_spec.rb
index 7804ffa4ef1..1b86aced67d 100644
--- a/spec/finders/environments/environments_by_deployments_finder_spec.rb
+++ b/spec/finders/environments/environments_by_deployments_finder_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Environments::EnvironmentsByDeploymentsFinder do
project.add_maintainer(user)
end
- shared_examples 'execute' do
+ describe '#execute' do
context 'tagged deployment' do
let(:environment_two) { create(:environment, project: project) }
# Environments need to include commits, so rewind two commits to fit
@@ -124,16 +124,4 @@ RSpec.describe Environments::EnvironmentsByDeploymentsFinder do
end
end
end
-
- describe "#execute" do
- include_examples 'execute'
-
- context 'when environments_by_deployments_finder_exists_optimization is disabled' do
- before do
- stub_feature_flags(environments_by_deployments_finder_exists_optimization: false)
- end
-
- include_examples 'execute'
- end
- end
end
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index 01c6eb05907..f6b87f7eeab 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -4,7 +4,12 @@ require 'spec_helper'
RSpec.describe GroupDescendantsFinder do
let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
+
+ let_it_be_with_reload(:group) do
+ create(:group).tap do |g|
+ g.add_owner(user)
+ end
+ end
let(:params) { {} }
@@ -12,254 +17,262 @@ RSpec.describe GroupDescendantsFinder do
described_class.new(current_user: user, parent_group: group, params: params)
end
- before do
- group.add_owner(user)
- end
-
- describe '#has_children?' do
- it 'is true when there are projects' do
- create(:project, namespace: group)
-
- expect(finder.has_children?).to be_truthy
- end
-
- context 'when there are subgroups' do
+ shared_examples 'group descentants finder examples' do
+ describe '#has_children?' do
it 'is true when there are projects' do
- create(:group, parent: group)
+ create(:project, namespace: group)
expect(finder.has_children?).to be_truthy
end
- end
- end
- describe '#execute' do
- it 'includes projects' do
- project = create(:project, namespace: group)
+ context 'when there are subgroups' do
+ it 'is true when there are projects' do
+ create(:group, parent: group)
- expect(finder.execute).to contain_exactly(project)
+ expect(finder.has_children?).to be_truthy
+ end
+ end
end
- context 'when archived is `true`' do
- let(:params) { { archived: 'true' } }
-
- it 'includes archived projects' do
- archived_project = create(:project, namespace: group, archived: true)
+ describe '#execute' do
+ it 'includes projects' do
project = create(:project, namespace: group)
- expect(finder.execute).to contain_exactly(archived_project, project)
+ expect(finder.execute).to contain_exactly(project)
end
- end
- context 'when archived is `only`' do
- let(:params) { { archived: 'only' } }
+ context 'when archived is `true`' do
+ let(:params) { { archived: 'true' } }
- it 'includes only archived projects' do
- archived_project = create(:project, namespace: group, archived: true)
- _project = create(:project, namespace: group)
+ it 'includes archived projects' do
+ archived_project = create(:project, namespace: group, archived: true)
+ project = create(:project, namespace: group)
- expect(finder.execute).to contain_exactly(archived_project)
+ expect(finder.execute).to contain_exactly(archived_project, project)
+ end
end
- end
- it 'does not include archived projects' do
- _archived_project = create(:project, :archived, namespace: group)
+ context 'when archived is `only`' do
+ let(:params) { { archived: 'only' } }
- expect(finder.execute).to be_empty
- end
+ it 'includes only archived projects' do
+ archived_project = create(:project, namespace: group, archived: true)
+ _project = create(:project, namespace: group)
- context 'with a filter' do
- let(:params) { { filter: 'test' } }
+ expect(finder.execute).to contain_exactly(archived_project)
+ end
+ end
- it 'includes only projects matching the filter' do
- _other_project = create(:project, namespace: group)
- matching_project = create(:project, namespace: group, name: 'testproject')
+ it 'does not include archived projects' do
+ _archived_project = create(:project, :archived, namespace: group)
- expect(finder.execute).to contain_exactly(matching_project)
+ expect(finder.execute).to be_empty
end
- end
- it 'sorts elements by name as default' do
- project1 = create(:project, namespace: group, name: 'z')
- project2 = create(:project, namespace: group, name: 'a')
+ context 'with a filter' do
+ let(:params) { { filter: 'test' } }
- expect(subject.execute).to eq([project2, project1])
- end
+ it 'includes only projects matching the filter' do
+ _other_project = create(:project, namespace: group)
+ matching_project = create(:project, namespace: group, name: 'testproject')
- context 'sorting by name' do
- let!(:project1) { create(:project, namespace: group, name: 'a', path: 'project-a') }
- let!(:project2) { create(:project, namespace: group, name: 'z', path: 'project-z') }
- let(:params) do
- {
- sort: 'name_asc'
- }
+ expect(finder.execute).to contain_exactly(matching_project)
+ end
end
- it 'sorts elements by name' do
- expect(subject.execute).to eq(
- [
- project1,
- project2
- ]
- )
+ it 'sorts elements by name as default' do
+ project1 = create(:project, namespace: group, name: 'z')
+ project2 = create(:project, namespace: group, name: 'a')
+
+ expect(subject.execute).to match_array([project2, project1])
end
- context 'with nested groups' do
- let!(:subgroup1) { create(:group, parent: group, name: 'a', path: 'sub-a') }
- let!(:subgroup2) { create(:group, parent: group, name: 'z', path: 'sub-z') }
+ context 'sorting by name' do
+ let!(:project1) { create(:project, namespace: group, name: 'a', path: 'project-a') }
+ let!(:project2) { create(:project, namespace: group, name: 'z', path: 'project-z') }
+ let(:params) do
+ {
+ sort: 'name_asc'
+ }
+ end
it 'sorts elements by name' do
expect(subject.execute).to eq(
[
- subgroup1,
- subgroup2,
project1,
project2
]
)
end
- end
- end
-
- 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,
- group_access: Gitlab::Access::MAINTAINER)
- expect(finder.execute).to contain_exactly(project)
- end
- end
+ context 'with nested groups' do
+ let!(:subgroup1) { create(:group, parent: group, name: 'a', path: 'sub-a') }
+ let!(:subgroup2) { create(:group, parent: group, name: 'z', path: 'sub-z') }
+
+ it 'sorts elements by name' do
+ expect(subject.execute).to eq(
+ [
+ subgroup1,
+ subgroup2,
+ project1,
+ project2
+ ]
+ )
+ end
+ end
+ end
- context 'with shared groups' do
- let_it_be(:other_group) { create(:group) }
- let_it_be(:shared_group_link) do
- create(:group_group_link,
- shared_group: group,
- shared_with_group: other_group)
- end
+ 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,
+ group_access: Gitlab::Access::MAINTAINER)
- context 'without common ancestor' do
- it { expect(finder.execute).to be_empty }
+ expect(finder.execute).to contain_exactly(project)
+ end
end
- context 'with common ancestor' do
- let_it_be(:common_ancestor) { create(:group) }
- let_it_be(:other_group) { create(:group, parent: common_ancestor) }
- let_it_be(:group) { create(:group, parent: common_ancestor) }
+ context 'with shared groups' do
+ let_it_be(:other_group) { create(:group) }
+ let_it_be(:shared_group_link) do
+ create(:group_group_link,
+ shared_group: group,
+ shared_with_group: other_group)
+ end
- context 'querying under the common ancestor' do
+ context 'without common ancestor' do
it { expect(finder.execute).to be_empty }
end
- context 'querying the common ancestor' do
- subject(:finder) do
- described_class.new(current_user: user, parent_group: common_ancestor, params: params)
+ context 'with common ancestor' do
+ let_it_be(:common_ancestor) { create(:group) }
+ let_it_be(:other_group) { create(:group, parent: common_ancestor) }
+ let_it_be(:group) { create(:group, parent: common_ancestor) }
+
+ context 'querying under the common ancestor' do
+ it { expect(finder.execute).to be_empty }
end
- it 'contains shared subgroups' do
- expect(finder.execute).to contain_exactly(group, other_group)
+ context 'querying the common ancestor' do
+ subject(:finder) do
+ described_class.new(current_user: user, parent_group: common_ancestor, params: params)
+ end
+
+ it 'contains shared subgroups' do
+ expect(finder.execute).to contain_exactly(group, other_group)
+ end
end
end
end
- end
- context 'with nested groups' do
- let!(:project) { create(:project, namespace: group) }
- let!(:subgroup) { create(:group, :private, parent: group) }
+ context 'with nested groups' do
+ let!(:project) { create(:project, namespace: group) }
+ let!(:subgroup) { create(:group, :private, parent: group) }
- describe '#execute' do
- it 'contains projects and subgroups' do
- expect(finder.execute).to contain_exactly(subgroup, project)
- end
+ describe '#execute' do
+ it 'contains projects and subgroups' do
+ expect(finder.execute).to contain_exactly(subgroup, project)
+ end
- it 'does not include subgroups the user does not have access to' do
- subgroup.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ it 'does not include subgroups the user does not have access to' do
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- public_subgroup = create(:group, :public, parent: group, path: 'public-group')
- other_subgroup = create(:group, :private, parent: group, path: 'visible-private-group')
- other_user = create(:user)
- other_subgroup.add_developer(other_user)
+ public_subgroup = create(:group, :public, parent: group, path: 'public-group')
+ other_subgroup = create(:group, :private, parent: group, path: 'visible-private-group')
+ other_user = create(:user)
+ other_subgroup.add_developer(other_user)
- finder = described_class.new(current_user: other_user, parent_group: group)
+ finder = described_class.new(current_user: other_user, parent_group: group)
- expect(finder.execute).to contain_exactly(public_subgroup, other_subgroup)
- end
+ expect(finder.execute).to contain_exactly(public_subgroup, other_subgroup)
+ end
- it 'only includes public groups when no user is given' do
- public_subgroup = create(:group, :public, parent: group)
- _private_subgroup = create(:group, :private, parent: group)
+ it 'only includes public groups when no user is given' do
+ public_subgroup = create(:group, :public, parent: group)
+ _private_subgroup = create(:group, :private, parent: group)
- finder = described_class.new(current_user: nil, parent_group: group)
+ finder = described_class.new(current_user: nil, parent_group: group)
- expect(finder.execute).to contain_exactly(public_subgroup)
- end
+ expect(finder.execute).to contain_exactly(public_subgroup)
+ end
- context 'when archived is `true`' do
- let(:params) { { archived: 'true' } }
+ context 'when archived is `true`' do
+ let(:params) { { archived: 'true' } }
- it 'includes archived projects in the count of subgroups' do
- create(:project, namespace: subgroup, archived: true)
+ it 'includes archived projects in the count of subgroups' do
+ create(:project, namespace: subgroup, archived: true)
- expect(finder.execute.first.preloaded_project_count).to eq(1)
+ expect(finder.execute.first.preloaded_project_count).to eq(1)
+ end
end
- end
- context 'with a filter' do
- let(:params) { { filter: 'test' } }
+ context 'with a filter' do
+ let(:params) { { filter: 'test' } }
- it 'contains only matching projects and subgroups' do
- matching_project = create(:project, namespace: group, name: 'Testproject')
- matching_subgroup = create(:group, name: 'testgroup', parent: group)
+ it 'contains only matching projects and subgroups' do
+ matching_project = create(:project, namespace: group, name: 'Testproject')
+ matching_subgroup = create(:group, name: 'testgroup', parent: group)
- expect(finder.execute).to contain_exactly(matching_subgroup, matching_project)
- end
+ expect(finder.execute).to contain_exactly(matching_subgroup, matching_project)
+ end
- it 'does not include subgroups the user does not have access to' do
- _invisible_subgroup = create(:group, :private, parent: group, name: 'test1')
- other_subgroup = create(:group, :private, parent: group, name: 'test2')
- public_subgroup = create(:group, :public, parent: group, name: 'test3')
- other_subsubgroup = create(:group, :private, parent: other_subgroup, name: 'test4')
- other_user = create(:user)
- other_subgroup.add_developer(other_user)
+ it 'does not include subgroups the user does not have access to' do
+ _invisible_subgroup = create(:group, :private, parent: group, name: 'test1')
+ other_subgroup = create(:group, :private, parent: group, name: 'test2')
+ public_subgroup = create(:group, :public, parent: group, name: 'test3')
+ other_subsubgroup = create(:group, :private, parent: other_subgroup, name: 'test4')
+ other_user = create(:user)
+ other_subgroup.add_developer(other_user)
- finder = described_class.new(current_user: other_user,
- parent_group: group,
- params: params)
+ finder = described_class.new(current_user: other_user,
+ parent_group: group,
+ params: params)
- expect(finder.execute).to contain_exactly(other_subgroup, public_subgroup, other_subsubgroup)
- end
+ expect(finder.execute).to contain_exactly(other_subgroup, public_subgroup, other_subsubgroup)
+ end
- context 'with matching children' do
- it 'includes a group that has a subgroup matching the query and its parent' do
- matching_subgroup = create(:group, :private, name: 'testgroup', parent: subgroup)
+ context 'with matching children' do
+ it 'includes a group that has a subgroup matching the query and its parent' do
+ matching_subgroup = create(:group, :private, name: 'testgroup', parent: subgroup)
- expect(finder.execute).to contain_exactly(subgroup, matching_subgroup)
- end
+ expect(finder.execute).to contain_exactly(subgroup, matching_subgroup)
+ end
- it 'includes the parent of a matching project' do
- matching_project = create(:project, namespace: subgroup, name: 'Testproject')
+ it 'includes the parent of a matching project' do
+ matching_project = create(:project, namespace: subgroup, name: 'Testproject')
- expect(finder.execute).to contain_exactly(subgroup, matching_project)
- end
+ expect(finder.execute).to contain_exactly(subgroup, matching_project)
+ end
- context 'with a small page size' do
- let(:params) { { filter: 'test', per_page: 1 } }
+ context 'with a small page size' do
+ let(:params) { { filter: 'test', per_page: 1 } }
- it 'contains all the ancestors of a matching subgroup regardless the page size' do
- subgroup = create(:group, :private, parent: group)
- matching = create(:group, :private, name: 'testgroup', parent: subgroup)
+ it 'contains all the ancestors of a matching subgroup regardless the page size' do
+ subgroup = create(:group, :private, parent: group)
+ matching = create(:group, :private, name: 'testgroup', parent: subgroup)
- expect(finder.execute).to contain_exactly(subgroup, matching)
+ expect(finder.execute).to contain_exactly(subgroup, matching)
+ end
end
- end
- it 'does not include the parent itself' do
- group.update!(name: 'test')
+ it 'does not include the parent itself' do
+ group.update!(name: 'test')
- expect(finder.execute).not_to include(group)
+ expect(finder.execute).not_to include(group)
+ end
end
end
end
end
end
+
+ it_behaves_like 'group descentants finder examples'
+
+ context 'when feature flag :linear_group_descendants_finder is disabled' do
+ before do
+ stub_feature_flags(linear_group_descendants_finder: false)
+ end
+
+ it_behaves_like 'group descentants finder examples'
+ end
end
diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb
index 10a08d7326e..a4cbee6a124 100644
--- a/spec/finders/groups_finder_spec.rb
+++ b/spec/finders/groups_finder_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe GroupsFinder do
include AdminModeHelper
- describe '#execute' do
+ shared_examples '#execute' do
let(:user) { create(:user) }
describe 'root level groups' do
@@ -20,6 +20,7 @@ RSpec.describe GroupsFinder do
user_private_group)
:regular | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
:regular | {} | %i(public_group internal_group user_public_group user_internal_group user_private_group)
+ :regular | { min_access_level: Gitlab::Access::DEVELOPER } | %i(user_public_group user_internal_group user_private_group)
:external | { all_available: true } | %i(public_group user_public_group user_internal_group user_private_group)
:external | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
@@ -261,4 +262,16 @@ RSpec.describe GroupsFinder do
end
end
end
+
+ describe '#execute' do
+ include_examples '#execute'
+
+ context 'when use_traversal_ids_groups_finder feature flags is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids_groups_finder: false)
+ end
+
+ include_examples '#execute'
+ end
+ end
end
diff --git a/spec/finders/issuables/crm_contact_filter_spec.rb b/spec/finders/issuables/crm_contact_filter_spec.rb
new file mode 100644
index 00000000000..d6eccab39ad
--- /dev/null
+++ b/spec/finders/issuables/crm_contact_filter_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issuables::CrmContactFilter do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ let_it_be(:contact1) { create(:contact, group: group) }
+ let_it_be(:contact2) { create(:contact, group: group) }
+
+ let_it_be(:contact1_issue1) { create(:issue, project: project) }
+ let_it_be(:contact1_issue2) { create(:issue, project: project) }
+ let_it_be(:contact2_issue1) { create(:issue, project: project) }
+ let_it_be(:issues) { Issue.where(id: [contact1_issue1.id, contact1_issue2.id, contact2_issue1.id]) }
+
+ before_all do
+ create(:issue_customer_relations_contact, issue: contact1_issue1, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact1_issue2, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue1, contact: contact2)
+ end
+
+ describe 'when a contact has issues' do
+ it 'returns all contact1 issues' do
+ params = { crm_contact_id: contact1.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact1_issue1, contact1_issue2)
+ end
+
+ it 'returns all contact2 issues' do
+ params = { crm_contact_id: contact2.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact2_issue1)
+ end
+ end
+
+ describe 'when a contact has no issues' do
+ it 'returns no issues' do
+ contact3 = create(:contact, group: group)
+ params = { crm_contact_id: contact3.id }
+
+ expect(described_class.new(params: params).filter(issues)).to be_empty
+ end
+ end
+end
diff --git a/spec/finders/issuables/crm_organization_filter_spec.rb b/spec/finders/issuables/crm_organization_filter_spec.rb
new file mode 100644
index 00000000000..2a521dcf721
--- /dev/null
+++ b/spec/finders/issuables/crm_organization_filter_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issuables::CrmOrganizationFilter do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ let_it_be(:organization1) { create(:organization, group: group) }
+ let_it_be(:organization2) { create(:organization, group: group) }
+ let_it_be(:contact1) { create(:contact, group: group, organization: organization1) }
+ let_it_be(:contact2) { create(:contact, group: group, organization: organization1) }
+ let_it_be(:contact3) { create(:contact, group: group, organization: organization2) }
+
+ let_it_be(:contact1_issue) { create(:issue, project: project) }
+ let_it_be(:contact2_issue) { create(:issue, project: project) }
+ let_it_be(:contact3_issue) { create(:issue, project: project) }
+ let_it_be(:issues) { Issue.where(id: [contact1_issue.id, contact2_issue.id, contact3_issue.id]) }
+
+ before_all do
+ create(:issue_customer_relations_contact, issue: contact1_issue, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue, contact: contact2)
+ create(:issue_customer_relations_contact, issue: contact3_issue, contact: contact3)
+ end
+
+ describe 'when an organization has issues' do
+ it 'returns all organization1 issues' do
+ params = { crm_organization_id: organization1.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact1_issue, contact2_issue)
+ end
+
+ it 'returns all organization2 issues' do
+ params = { crm_organization_id: organization2.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact3_issue)
+ end
+ end
+
+ describe 'when an organization has no issues' do
+ it 'returns no issues' do
+ organization3 = create(:organization, group: group)
+ params = { crm_organization_id: organization3.id }
+
+ expect(described_class.new(params: params).filter(issues)).to be_empty
+ end
+ end
+end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 9f12308013e..31563a6326d 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -910,6 +910,45 @@ RSpec.describe IssuesFinder do
end
end
+ context 'filtering by crm contact' do
+ let_it_be(:contact1) { create(:contact, group: group) }
+ let_it_be(:contact2) { create(:contact, group: group) }
+
+ let_it_be(:contact1_issue1) { create(:issue, project: project1) }
+ let_it_be(:contact1_issue2) { create(:issue, project: project1) }
+ let_it_be(:contact2_issue1) { create(:issue, project: project1) }
+
+ let(:params) { { crm_contact_id: contact1.id } }
+
+ it 'returns for that contact' do
+ create(:issue_customer_relations_contact, issue: contact1_issue1, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact1_issue2, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue1, contact: contact2)
+
+ expect(issues).to contain_exactly(contact1_issue1, contact1_issue2)
+ end
+ end
+
+ context 'filtering by crm organization' do
+ let_it_be(:organization) { create(:organization, group: group) }
+ let_it_be(:contact1) { create(:contact, group: group, organization: organization) }
+ let_it_be(:contact2) { create(:contact, group: group, organization: organization) }
+
+ let_it_be(:contact1_issue1) { create(:issue, project: project1) }
+ let_it_be(:contact1_issue2) { create(:issue, project: project1) }
+ let_it_be(:contact2_issue1) { create(:issue, project: project1) }
+
+ let(:params) { { crm_organization_id: organization.id } }
+
+ it 'returns for that contact' do
+ create(:issue_customer_relations_contact, issue: contact1_issue1, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact1_issue2, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue1, contact: contact2)
+
+ expect(issues).to contain_exactly(contact1_issue1, contact1_issue2, contact2_issue1)
+ end
+ end
+
context 'when the user is unauthorized' do
let(:search_user) { nil }
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 42197a6b103..03639bc0b98 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -681,6 +681,18 @@ RSpec.describe MergeRequestsFinder do
expect(mrs).to eq([mr1])
end
+ it 'filters merge requests ignoring empty deployed_before' do
+ mrs = described_class.new(user, deployed_before: '').execute
+
+ expect(mrs.size).to eq(7)
+ end
+
+ it 'filters merge requests ignoring invalid deployed_before' do
+ mrs = described_class.new(user, deployed_before: '2021-99-99').execute
+
+ expect(mrs.size).to eq(7)
+ end
+
it 'filters merge requests deployed after a given date' do
mrs = described_class
.new(user, deployed_after: '2020-10-01 12:00')
@@ -688,6 +700,18 @@ RSpec.describe MergeRequestsFinder do
expect(mrs).to eq([mr2])
end
+
+ it 'filters merge requests ignoring empty deployed_after' do
+ mrs = described_class.new(user, deployed_after: '').execute
+
+ expect(mrs.size).to eq(7)
+ end
+
+ it 'filters merge requests ignoring invalid deployed_after' do
+ mrs = described_class.new(user, deployed_after: '2021-99-99').execute
+
+ expect(mrs.size).to eq(7)
+ end
end
it 'does not raise any exception with complex filters' do
diff --git a/spec/finders/packages/build_infos_finder_spec.rb b/spec/finders/packages/build_infos_finder_spec.rb
new file mode 100644
index 00000000000..23425de4316
--- /dev/null
+++ b/spec/finders/packages/build_infos_finder_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Packages::BuildInfosFinder do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:package) { create(:package) }
+ let_it_be(:build_infos) { create_list(:package_build_info, 5, :with_pipeline, package: package) }
+ let_it_be(:build_info_with_empty_pipeline) { create(:package_build_info, package: package) }
+
+ let(:finder) { described_class.new(package, params) }
+ let(:params) do
+ {
+ first: first,
+ last: last,
+ after: after,
+ before: before,
+ max_page_size: max_page_size,
+ support_next_page: support_next_page
+ }
+ end
+
+ describe '#execute' do
+ subject { finder.execute }
+
+ where(:first, :last, :after_index, :before_index, :max_page_size, :support_next_page, :expected_build_infos_indexes) do
+ # F L AI BI MPS SNP
+ nil | nil | nil | nil | nil | false | [4, 3, 2, 1, 0]
+ nil | nil | nil | nil | 10 | false | [4, 3, 2, 1, 0]
+ nil | nil | nil | nil | 2 | false | [4, 3]
+ 2 | nil | nil | nil | nil | false | [4, 3]
+ 2 | nil | nil | nil | nil | true | [4, 3, 2]
+ 2 | nil | 3 | nil | nil | false | [2, 1]
+ 2 | nil | 3 | nil | nil | true | [2, 1, 0]
+ 3 | nil | 4 | nil | 2 | false | [3, 2]
+ 3 | nil | 4 | nil | 2 | true | [3, 2, 1]
+ nil | 2 | nil | nil | nil | false | [0, 1]
+ nil | 2 | nil | nil | nil | true | [0, 1, 2]
+ nil | 2 | nil | 1 | nil | false | [2, 3]
+ nil | 2 | nil | 1 | nil | true | [2, 3, 4]
+ nil | 3 | nil | 0 | 2 | false | [1, 2]
+ nil | 3 | nil | 0 | 2 | true | [1, 2, 3]
+ end
+
+ with_them do
+ let(:expected_build_infos) do
+ expected_build_infos_indexes.map do |idx|
+ build_infos[idx]
+ end
+ end
+
+ let(:after) do
+ build_infos[after_index].pipeline_id if after_index
+ end
+
+ let(:before) do
+ build_infos[before_index].pipeline_id if before_index
+ end
+
+ it { is_expected.to eq(expected_build_infos) }
+ end
+ end
+end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index 3254c436674..c2dbfb59eb2 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -107,6 +107,28 @@ RSpec.describe Packages::GroupPackagesFinder do
end
end
+ context 'deploy tokens' do
+ let(:add_user_to_group) { false }
+
+ context 'group deploy token' do
+ let_it_be(:deploy_token_for_group) { create(:deploy_token, :group, read_package_registry: true) }
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token_for_group, group: group) }
+
+ let(:user) { deploy_token_for_group }
+
+ it { is_expected.to match_array([package1, package2, package4]) }
+ end
+
+ context 'project deploy token' do
+ let_it_be(:deploy_token_for_project) { create(:deploy_token, read_package_registry: true) }
+ let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token_for_project, project: subproject) }
+
+ let(:user) { deploy_token_for_project }
+
+ it { is_expected.to match_array([package4]) }
+ end
+ end
+
context 'avoid N+1 query' do
it 'avoids N+1 database queries' do
count = ActiveRecord::QueryRecorder.new { subject }
diff --git a/spec/finders/packages/nuget/package_finder_spec.rb b/spec/finders/packages/nuget/package_finder_spec.rb
index 4ad02ce7da8..045dba295ac 100644
--- a/spec/finders/packages/nuget/package_finder_spec.rb
+++ b/spec/finders/packages/nuget/package_finder_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Packages::Nuget::PackageFinder do
end
context 'with prefix wildcard' do
- let(:package_name) { "%#{package1.name[3..-1]}" }
+ let(:package_name) { "%#{package1.name[3..]}" }
it { is_expected.to match_array([package1, package2]) }
end
diff --git a/spec/finders/personal_projects_finder_spec.rb b/spec/finders/personal_projects_finder_spec.rb
index 493ec0e569e..af3b5bf894b 100644
--- a/spec/finders/personal_projects_finder_spec.rb
+++ b/spec/finders/personal_projects_finder_spec.rb
@@ -3,14 +3,16 @@
require 'spec_helper'
RSpec.describe PersonalProjectsFinder do
- let(:source_user) { create(:user) }
- let(:current_user) { create(:user) }
- let(:finder) { described_class.new(source_user) }
+ let_it_be(:source_user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
+
+ let(:finder) { described_class.new(source_user) }
let!(:public_project) do
- create(:project, :public, namespace: source_user.namespace, updated_at: 1.hour.ago)
+ create(:project, :public, namespace: source_user.namespace, updated_at: 1.hour.ago, path: 'pblc')
end
- let!(:private_project) do
+ let!(:private_project_shared) do
create(:project, :private, namespace: source_user.namespace, updated_at: 3.hours.ago, path: 'mepmep')
end
@@ -18,8 +20,12 @@ RSpec.describe PersonalProjectsFinder do
create(:project, :internal, namespace: source_user.namespace, updated_at: 2.hours.ago, path: 'C')
end
+ let!(:private_project_self) do
+ create(:project, :private, namespace: source_user.namespace, updated_at: 3.hours.ago, path: 'D')
+ end
+
before do
- private_project.add_developer(current_user)
+ private_project_shared.add_developer(current_user)
end
describe 'without a current user' do
@@ -29,18 +35,26 @@ RSpec.describe PersonalProjectsFinder do
end
describe 'with a current user' do
- subject { finder.execute(current_user) }
-
context 'normal user' do
- it { is_expected.to eq([public_project, internal_project, private_project]) }
+ subject { finder.execute(current_user) }
+
+ it { is_expected.to match_array([public_project, internal_project, private_project_shared]) }
end
context 'external' do
+ subject { finder.execute(current_user) }
+
before do
current_user.update!(external: true)
end
- it { is_expected.to eq([public_project, private_project]) }
+ it { is_expected.to match_array([public_project, private_project_shared]) }
+ end
+
+ context 'and searching with an admin user', :enable_admin_mode do
+ subject { finder.execute(admin) }
+
+ it { is_expected.to match_array([public_project, internal_project, private_project_self, private_project_shared]) }
end
end
end
diff --git a/spec/finders/user_group_notification_settings_finder_spec.rb b/spec/finders/user_group_notification_settings_finder_spec.rb
index b9d800d8e55..ea44688bc8d 100644
--- a/spec/finders/user_group_notification_settings_finder_spec.rb
+++ b/spec/finders/user_group_notification_settings_finder_spec.rb
@@ -11,155 +11,167 @@ RSpec.describe UserGroupNotificationSettingsFinder do
subject.map(&proc).uniq
end
- context 'when the groups have no existing notification settings' do
- context 'when the groups have no ancestors' do
- let_it_be(:groups) { create_list(:group, 3) }
-
- it 'will be a default Global notification setting', :aggregate_failures do
- expect(subject.count).to eq(3)
- expect(attributes(&:notification_email)).to eq([nil])
- expect(attributes(&:level)).to eq(['global'])
+ shared_examples 'user group notifications settings tests' do
+ context 'when the groups have no existing notification settings' do
+ context 'when the groups have no ancestors' do
+ let_it_be(:groups) { create_list(:group, 3) }
+
+ it 'will be a default Global notification setting', :aggregate_failures do
+ expect(subject.count).to eq(3)
+ expect(attributes(&:notification_email)).to match_array([nil])
+ expect(attributes(&:level)).to match_array(['global'])
+ end
end
- end
- context 'when the groups have ancestors' do
- context 'when an ancestor has a level other than Global' do
- let_it_be(:ancestor_a) { create(:group) }
- let_it_be(:group_a) { create(:group, parent: ancestor_a) }
- let_it_be(:ancestor_b) { create(:group) }
- let_it_be(:group_b) { create(:group, parent: ancestor_b) }
- let_it_be(:email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ context 'when the groups have ancestors' do
+ context 'when an ancestor has a level other than Global' do
+ let_it_be(:ancestor_a) { create(:group) }
+ let_it_be(:group_a) { create(:group, parent: ancestor_a) }
+ let_it_be(:ancestor_b) { create(:group) }
+ let_it_be(:group_b) { create(:group, parent: ancestor_b) }
+ let_it_be(:email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
- let_it_be(:groups) { [group_a, group_b] }
+ let_it_be(:groups) { [group_a, group_b] }
- before do
- create(:notification_setting, user: user, source: ancestor_a, level: 'participating', notification_email: email.email)
- create(:notification_setting, user: user, source: ancestor_b, level: 'participating', notification_email: email.email)
- end
+ before do
+ create(:notification_setting, user: user, source: ancestor_a, level: 'participating', notification_email: email.email)
+ create(:notification_setting, user: user, source: ancestor_b, level: 'participating', notification_email: email.email)
+ end
- it 'has the same level set' do
- expect(attributes(&:level)).to eq(['participating'])
- end
+ it 'has the same level set' do
+ expect(attributes(&:level)).to match_array(['participating'])
+ end
- it 'has the same email set' do
- expect(attributes(&:notification_email)).to eq(['ancestor@example.com'])
+ it 'has the same email set' do
+ expect(attributes(&:notification_email)).to match_array(['ancestor@example.com'])
+ end
+
+ it 'only returns the two queried groups' do
+ expect(subject.count).to eq(2)
+ end
end
- it 'only returns the two queried groups' do
- expect(subject.count).to eq(2)
+ context 'when an ancestor has a Global level but has an email set' do
+ let_it_be(:grand_ancestor) { create(:group) }
+ let_it_be(:ancestor) { create(:group, parent: grand_ancestor) }
+ let_it_be(:group) { create(:group, parent: ancestor) }
+ let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ let_it_be(:grand_email) { create(:email, :confirmed, email: 'grand@example.com', user: user) }
+
+ let_it_be(:groups) { [group] }
+
+ before do
+ create(:notification_setting, user: user, source: grand_ancestor, level: 'participating', notification_email: grand_email.email)
+ create(:notification_setting, user: user, source: ancestor, level: 'global', notification_email: ancestor_email.email)
+ end
+
+ it 'has the same email and level set', :aggregate_failures do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to match_array(['global'])
+ expect(attributes(&:notification_email)).to match_array(['ancestor@example.com'])
+ end
end
- end
- context 'when an ancestor has a Global level but has an email set' do
- let_it_be(:grand_ancestor) { create(:group) }
- let_it_be(:ancestor) { create(:group, parent: grand_ancestor) }
- let_it_be(:group) { create(:group, parent: ancestor) }
- let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
- let_it_be(:grand_email) { create(:email, :confirmed, email: 'grand@example.com', user: user) }
+ context 'when the group has parent_id set but that does not belong to any group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:groups) { [group] }
- let_it_be(:groups) { [group] }
+ before do
+ # Let's set a parent_id for a group that definitely doesn't exist
+ group.update_columns(parent_id: 19283746)
+ end
- before do
- create(:notification_setting, user: user, source: grand_ancestor, level: 'participating', notification_email: grand_email.email)
- create(:notification_setting, user: user, source: ancestor, level: 'global', notification_email: ancestor_email.email)
+ it 'returns a default Global notification setting' do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to match_array(['global'])
+ expect(attributes(&:notification_email)).to match_array([nil])
+ end
end
- it 'has the same email and level set', :aggregate_failures do
- expect(subject.count).to eq(1)
- expect(attributes(&:level)).to eq(['global'])
- expect(attributes(&:notification_email)).to eq(['ancestor@example.com'])
+ context 'when the group has a private parent' do
+ let_it_be(:ancestor) { create(:group, :private) }
+ let_it_be(:group) { create(:group, :private, parent: ancestor) }
+ let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ let_it_be(:groups) { [group] }
+
+ before do
+ group.add_reporter(user)
+ # Adding the user creates a NotificationSetting, so we remove it here
+ user.notification_settings.where(source: group).delete_all
+
+ create(:notification_setting, user: user, source: ancestor, level: 'participating', notification_email: ancestor_email.email)
+ end
+
+ it 'still inherits the notification settings' do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to match_array(['participating'])
+ expect(attributes(&:notification_email)).to match_array([ancestor_email.email])
+ end
end
- end
- context 'when the group has parent_id set but that does not belong to any group' do
- let_it_be(:group) { create(:group) }
- let_it_be(:groups) { [group] }
+ it 'does not cause an N+1', :aggregate_failures do
+ parent = create(:group)
+ child = create(:group, parent: parent)
- before do
- # Let's set a parent_id for a group that definitely doesn't exist
- group.update_columns(parent_id: 19283746)
- end
+ control = ActiveRecord::QueryRecorder.new do
+ described_class.new(user, Group.where(id: child.id)).execute
+ end
- it 'returns a default Global notification setting' do
- expect(subject.count).to eq(1)
- expect(attributes(&:level)).to eq(['global'])
- expect(attributes(&:notification_email)).to eq([nil])
- end
- end
+ other_parent = create(:group)
+ other_children = create_list(:group, 2, parent: other_parent)
- context 'when the group has a private parent' do
- let_it_be(:ancestor) { create(:group, :private) }
- let_it_be(:group) { create(:group, :private, parent: ancestor) }
- let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
- let_it_be(:groups) { [group] }
+ result = nil
- before do
- group.add_reporter(user)
- # Adding the user creates a NotificationSetting, so we remove it here
- user.notification_settings.where(source: group).delete_all
-
- create(:notification_setting, user: user, source: ancestor, level: 'participating', notification_email: ancestor_email.email)
- end
+ expect do
+ result = described_class.new(user, Group.where(id: other_children.append(child).map(&:id))).execute
+ end.not_to exceed_query_limit(control)
- it 'still inherits the notification settings' do
- expect(subject.count).to eq(1)
- expect(attributes(&:level)).to eq(['participating'])
- expect(attributes(&:notification_email)).to eq([ancestor_email.email])
+ expect(result.count).to eq(3)
end
end
+ end
- it 'does not cause an N+1', :aggregate_failures do
- parent = create(:group)
- child = create(:group, parent: parent)
-
- control = ActiveRecord::QueryRecorder.new do
- described_class.new(user, Group.where(id: child.id)).execute
- end
+ context 'preloading `emails_disabled`' do
+ let_it_be(:root_group) { create(:group) }
+ let_it_be(:sub_group) { create(:group, parent: root_group) }
+ let_it_be(:sub_sub_group) { create(:group, parent: sub_group) }
- other_parent = create(:group)
- other_children = create_list(:group, 2, parent: other_parent)
+ let_it_be(:another_root_group) { create(:group) }
+ let_it_be(:sub_group_with_emails_disabled) { create(:group, emails_disabled: true, parent: another_root_group) }
+ let_it_be(:another_sub_sub_group) { create(:group, parent: sub_group_with_emails_disabled) }
- result = nil
+ let_it_be(:root_group_with_emails_disabled) { create(:group, emails_disabled: true) }
+ let_it_be(:group) { create(:group, parent: root_group_with_emails_disabled) }
- expect do
- result = described_class.new(user, Group.where(id: other_children.append(child).map(&:id))).execute
- end.not_to exceed_query_limit(control)
+ let(:groups) { Group.where(id: [sub_sub_group, another_sub_sub_group, group]) }
- expect(result.count).to eq(3)
+ before do
+ described_class.new(user, groups).execute
end
- end
- end
-
- context 'preloading `emails_disabled`' do
- let_it_be(:root_group) { create(:group) }
- let_it_be(:sub_group) { create(:group, parent: root_group) }
- let_it_be(:sub_sub_group) { create(:group, parent: sub_group) }
-
- let_it_be(:another_root_group) { create(:group) }
- let_it_be(:sub_group_with_emails_disabled) { create(:group, emails_disabled: true, parent: another_root_group) }
- let_it_be(:another_sub_sub_group) { create(:group, parent: sub_group_with_emails_disabled) }
- let_it_be(:root_group_with_emails_disabled) { create(:group, emails_disabled: true) }
- let_it_be(:group) { create(:group, parent: root_group_with_emails_disabled) }
+ it 'preloads the `group.emails_disabled` method' do
+ recorder = ActiveRecord::QueryRecorder.new do
+ groups.each(&:emails_disabled?)
+ end
- let(:groups) { Group.where(id: [sub_sub_group, another_sub_sub_group, group]) }
+ expect(recorder.count).to eq(0)
+ end
- before do
- described_class.new(user, groups).execute
+ it 'preloads the `group.emails_disabled` method correctly' do
+ groups.each do |group|
+ expect(group.emails_disabled?).to eq(Group.find(group.id).emails_disabled?) # compare the memoized and the freshly loaded value
+ end
+ end
end
+ end
- it 'preloads the `group.emails_disabled` method' do
- recorder = ActiveRecord::QueryRecorder.new do
- groups.each(&:emails_disabled?)
- end
+ it_behaves_like 'user group notifications settings tests'
- expect(recorder.count).to eq(0)
+ context 'when feature flag :linear_user_group_notification_settings_finder_ancestors_scopes is disabled' do
+ before do
+ stub_feature_flags(linear_user_group_notification_settings_finder_ancestors_scopes: false)
end
- it 'preloads the `group.emails_disabled` method correctly' do
- groups.each do |group|
- expect(group.emails_disabled?).to eq(Group.find(group.id).emails_disabled?) # compare the memoized and the freshly loaded value
- end
- end
+ it_behaves_like 'user group notifications settings tests'
end
end