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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-20 17:34:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-20 17:34:42 +0300
commit9f46488805e86b1bc341ea1620b866016c2ce5ed (patch)
treef9748c7e287041e37d6da49e0a29c9511dc34768 /spec/graphql/resolvers
parentdfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff)
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'spec/graphql/resolvers')
-rw-r--r--spec/graphql/resolvers/alert_management/alert_status_counts_resolver_spec.rb24
-rw-r--r--spec/graphql/resolvers/alert_management_alert_resolver_spec.rb63
-rw-r--r--spec/graphql/resolvers/board_lists_resolver_spec.rb82
-rw-r--r--spec/graphql/resolvers/branch_commit_resolver_spec.rb26
-rw-r--r--spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb69
-rw-r--r--spec/graphql/resolvers/design_management/design_resolver_spec.rb88
-rw-r--r--spec/graphql/resolvers/design_management/designs_resolver_spec.rb93
-rw-r--r--spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb93
-rw-r--r--spec/graphql/resolvers/design_management/version/designs_at_version_resolver_spec.rb86
-rw-r--r--spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb64
-rw-r--r--spec/graphql/resolvers/design_management/version_resolver_spec.rb43
-rw-r--r--spec/graphql/resolvers/design_management/versions_resolver_spec.rb117
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb78
-rw-r--r--spec/graphql/resolvers/milestone_resolver_spec.rb28
-rw-r--r--spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/projects_resolver_spec.rb77
-rw-r--r--spec/graphql/resolvers/release_resolver_spec.rb51
-rw-r--r--spec/graphql/resolvers/releases_resolver_spec.rb42
18 files changed, 1112 insertions, 20 deletions
diff --git a/spec/graphql/resolvers/alert_management/alert_status_counts_resolver_spec.rb b/spec/graphql/resolvers/alert_management/alert_status_counts_resolver_spec.rb
new file mode 100644
index 00000000000..8eb28c8c945
--- /dev/null
+++ b/spec/graphql/resolvers/alert_management/alert_status_counts_resolver_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::AlertManagement::AlertStatusCountsResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let(:args) { {} }
+
+ subject { resolve_alert_status_counts(args) }
+
+ it { is_expected.to be_a(Gitlab::AlertManagement::AlertStatusCounts) }
+ specify { expect(subject.project).to eq(project) }
+
+ private
+
+ def resolve_alert_status_counts(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, args: args, ctx: context)
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/alert_management_alert_resolver_spec.rb b/spec/graphql/resolvers/alert_management_alert_resolver_spec.rb
new file mode 100644
index 00000000000..971a81a826d
--- /dev/null
+++ b/spec/graphql/resolvers/alert_management_alert_resolver_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::AlertManagementAlertResolver do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:alert_1) { create(:alert_management_alert, :resolved, project: project, ended_at: 1.year.ago, events: 2, severity: :high) }
+ let_it_be(:alert_2) { create(:alert_management_alert, :ignored, project: project, events: 1, severity: :critical) }
+ let_it_be(:alert_other_proj) { create(:alert_management_alert) }
+
+ let(:args) { {} }
+
+ subject { resolve_alerts(args) }
+
+ context 'user does not have permission' do
+ it { is_expected.to eq(AlertManagement::Alert.none) }
+ end
+
+ context 'user has permission' do
+ before do
+ project.add_developer(current_user)
+ end
+
+ it { is_expected.to contain_exactly(alert_1, alert_2) }
+
+ context 'finding by iid' do
+ let(:args) { { iid: alert_1.iid } }
+
+ it { is_expected.to contain_exactly(alert_1) }
+ end
+
+ context 'finding by status' do
+ let(:args) { { status: [Types::AlertManagement::StatusEnum.values['IGNORED'].value] } }
+
+ it { is_expected.to contain_exactly(alert_2) }
+ end
+
+ describe 'sorting' do
+ # Other sorting examples in spec/finders/alert_management/alerts_finder_spec.rb
+ context 'when sorting by events count' do
+ let_it_be(:alert_count_6) { create(:alert_management_alert, project: project, events: 6) }
+ let_it_be(:alert_count_3) { create(:alert_management_alert, project: project, events: 3) }
+
+ it 'sorts alerts ascending' do
+ expect(resolve_alerts(sort: :events_count_asc)).to eq [alert_2, alert_1, alert_count_3, alert_count_6]
+ end
+
+ it 'sorts alerts descending' do
+ expect(resolve_alerts(sort: :events_count_desc)).to eq [alert_count_6, alert_count_3, alert_1, alert_2]
+ end
+ end
+ end
+ end
+
+ private
+
+ def resolve_alerts(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/board_lists_resolver_spec.rb b/spec/graphql/resolvers/board_lists_resolver_spec.rb
new file mode 100644
index 00000000000..5f6c440a8ed
--- /dev/null
+++ b/spec/graphql/resolvers/board_lists_resolver_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::BoardListsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:unauth_user) { create(:user) }
+ let_it_be(:project) { create(:project, creator_id: user.id, namespace: user.namespace ) }
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:project_label) { create(:label, project: project, name: 'Development') }
+ let_it_be(:group_label) { create(:group_label, group: group, name: 'Development') }
+
+ shared_examples_for 'group and project board lists resolver' do
+ let(:board) { create(:board, resource_parent: board_parent) }
+
+ before do
+ board_parent.add_developer(user)
+ end
+
+ it 'does not create the backlog list' do
+ lists = resolve_board_lists.items
+
+ expect(lists.count).to eq 1
+ expect(lists[0].list_type).to eq 'closed'
+ end
+
+ context 'with unauthorized user' do
+ it 'raises an error' do
+ expect do
+ resolve_board_lists(current_user: unauth_user)
+ end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when authorized' do
+ let!(:label_list) { create(:list, board: board, label: label) }
+ let!(:backlog_list) { create(:backlog_list, board: board) }
+
+ it 'returns a list of board lists' do
+ lists = resolve_board_lists.items
+
+ expect(lists.count).to eq 3
+ expect(lists.map(&:list_type)).to eq %w(backlog label closed)
+ end
+
+ context 'when another user has list preferences' do
+ before do
+ board.lists.first.update_preferences_for(guest, collapsed: true)
+ end
+
+ it 'returns the complete list of board lists for this user' do
+ lists = resolve_board_lists.items
+
+ expect(lists.count).to eq 3
+ end
+ end
+ end
+ end
+
+ describe '#resolve' do
+ context 'when project boards' do
+ let(:board_parent) { project }
+ let(:label) { project_label }
+
+ it_behaves_like 'group and project board lists resolver'
+ end
+
+ context 'when group boards' do
+ let(:board_parent) { group }
+ let(:label) { group_label }
+
+ it_behaves_like 'group and project board lists resolver'
+ end
+ end
+
+ def resolve_board_lists(args: {}, current_user: user)
+ resolve(described_class, obj: board, args: args, ctx: { current_user: current_user })
+ end
+end
diff --git a/spec/graphql/resolvers/branch_commit_resolver_spec.rb b/spec/graphql/resolvers/branch_commit_resolver_spec.rb
new file mode 100644
index 00000000000..22e1de8f375
--- /dev/null
+++ b/spec/graphql/resolvers/branch_commit_resolver_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::BranchCommitResolver do
+ include GraphqlHelpers
+
+ subject(:commit) { resolve(described_class, obj: branch) }
+
+ let_it_be(:repository) { create(:project, :repository).repository }
+ let(:branch) { repository.find_branch('master') }
+
+ describe '#resolve' do
+ it 'resolves commit' do
+ is_expected.to eq(repository.commits('master', limit: 1).last)
+ end
+
+ context 'when branch does not exist' do
+ let(:branch) { nil }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb b/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb
new file mode 100644
index 00000000000..a5054ae3ebf
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::DesignAtVersionResolver do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:project) { issue.project }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:design_a) { create(:design, issue: issue) }
+ let_it_be(:version_a) { create(:design_version, issue: issue, created_designs: [design_a]) }
+
+ let(:current_user) { user }
+ let(:object) { issue.design_collection }
+ let(:global_id) { GitlabSchema.id_from_object(design_at_version).to_s }
+
+ let(:design_at_version) { ::DesignManagement::DesignAtVersion.new(design: design_a, version: version_a) }
+
+ let(:resource_not_available) { ::Gitlab::Graphql::Errors::ResourceNotAvailable }
+
+ before do
+ enable_design_management
+ project.add_developer(user)
+ end
+
+ describe '#resolve' do
+ context 'when the user cannot see designs' do
+ let(:current_user) { create(:user) }
+
+ it 'raises ResourceNotAvailable' do
+ expect { resolve_design }.to raise_error(resource_not_available)
+ end
+ end
+
+ it 'returns the specified design' do
+ expect(resolve_design).to eq(design_at_version)
+ end
+
+ context 'the ID belongs to a design on another issue' do
+ let(:other_dav) do
+ create(:design_at_version, issue: create(:issue, project: project))
+ end
+
+ let(:global_id) { global_id_of(other_dav) }
+
+ it 'raises ResourceNotAvailable' do
+ expect { resolve_design }.to raise_error(resource_not_available)
+ end
+
+ context 'the current object does not constrain the issue' do
+ let(:object) { nil }
+
+ it 'returns the object' do
+ expect(resolve_design).to eq(other_dav)
+ end
+ end
+ end
+ end
+
+ private
+
+ def resolve_design
+ args = { id: global_id }
+ ctx = { current_user: current_user }
+ eager_resolve(described_class, obj: object, args: args, ctx: ctx)
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/design_resolver_spec.rb b/spec/graphql/resolvers/design_management/design_resolver_spec.rb
new file mode 100644
index 00000000000..857acc3d371
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/design_resolver_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::DesignResolver do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ before do
+ enable_design_management
+ end
+
+ describe '#resolve' do
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:project) { issue.project }
+ let_it_be(:first_version) { create(:design_version) }
+ let_it_be(:first_design) { create(:design, issue: issue, versions: [first_version]) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:design_on_other_issue) do
+ create(:design, issue: create(:issue, project: project), versions: [create(:design_version)])
+ end
+
+ let(:args) { { id: GitlabSchema.id_from_object(first_design).to_s } }
+ let(:gql_context) { { current_user: current_user } }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ context 'when the user cannot see designs' do
+ let(:gql_context) { { current_user: create(:user) } }
+
+ it 'returns nothing' do
+ expect(resolve_design).to be_nil
+ end
+ end
+
+ context 'when no argument has been passed' do
+ let(:args) { {} }
+
+ it 'raises an error' do
+ expect { resolve_design }.to raise_error(::Gitlab::Graphql::Errors::ArgumentError, /must/)
+ end
+ end
+
+ context 'when both arguments have been passed' do
+ let(:args) { { filename: first_design.filename, id: GitlabSchema.id_from_object(first_design).to_s } }
+
+ it 'raises an error' do
+ expect { resolve_design }.to raise_error(::Gitlab::Graphql::Errors::ArgumentError, /may/)
+ end
+ end
+
+ context 'by ID' do
+ it 'returns the specified design' do
+ expect(resolve_design).to eq(first_design)
+ end
+
+ context 'the ID belongs to a design on another issue' do
+ let(:args) { { id: GitlabSchema.id_from_object(design_on_other_issue).to_s } }
+
+ it 'returns nothing' do
+ expect(resolve_design).to be_nil
+ end
+ end
+ end
+
+ context 'by filename' do
+ let(:args) { { filename: first_design.filename } }
+
+ it 'returns the specified design' do
+ expect(resolve_design).to eq(first_design)
+ end
+
+ context 'the filename belongs to a design on another issue' do
+ let(:args) { { filename: design_on_other_issue.filename } }
+
+ it 'returns nothing' do
+ expect(resolve_design).to be_nil
+ end
+ end
+ end
+ end
+
+ def resolve_design
+ resolve(described_class, obj: issue.design_collection, args: args, ctx: gql_context)
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/designs_resolver_spec.rb b/spec/graphql/resolvers/design_management/designs_resolver_spec.rb
new file mode 100644
index 00000000000..28fc9e2151d
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/designs_resolver_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::DesignsResolver do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ before do
+ enable_design_management
+ end
+
+ describe '#resolve' do
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:project) { issue.project }
+ let_it_be(:first_version) { create(:design_version) }
+ let_it_be(:first_design) { create(:design, issue: issue, versions: [first_version]) }
+ let_it_be(:current_user) { create(:user) }
+ let(:gql_context) { { current_user: current_user } }
+ let(:args) { {} }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ context 'when the user cannot see designs' do
+ let(:gql_context) { { current_user: create(:user) } }
+
+ it 'returns nothing' do
+ expect(resolve_designs).to be_empty
+ end
+ end
+
+ context 'for a design collection' do
+ context 'which contains just a single design' do
+ it 'returns just that design' do
+ expect(resolve_designs).to contain_exactly(first_design)
+ end
+ end
+
+ context 'which contains another design' do
+ it 'returns all designs' do
+ second_version = create(:design_version)
+ second_design = create(:design, issue: issue, versions: [second_version])
+
+ expect(resolve_designs).to contain_exactly(first_design, second_design)
+ end
+ end
+ end
+
+ describe 'filtering' do
+ describe 'by filename' do
+ let(:second_version) { create(:design_version) }
+ let(:second_design) { create(:design, issue: issue, versions: [second_version]) }
+ let(:args) { { filenames: [second_design.filename] } }
+
+ it 'resolves to just the relevant design, ignoring designs with the same filename on different issues' do
+ create(:design, issue: create(:issue, project: project), filename: second_design.filename)
+
+ expect(resolve_designs).to contain_exactly(second_design)
+ end
+ end
+
+ describe 'by id' do
+ let(:second_version) { create(:design_version) }
+ let(:second_design) { create(:design, issue: issue, versions: [second_version]) }
+
+ context 'the ID is on the current issue' do
+ let(:args) { { ids: [GitlabSchema.id_from_object(second_design).to_s] } }
+
+ it 'resolves to just the relevant design' do
+ expect(resolve_designs).to contain_exactly(second_design)
+ end
+ end
+
+ context 'the ID is on a different issue' do
+ let(:third_version) { create(:design_version) }
+ let(:third_design) { create(:design, issue: create(:issue, project: project), versions: [third_version]) }
+
+ let(:args) { { ids: [GitlabSchema.id_from_object(third_design).to_s] } }
+
+ it 'ignores it' do
+ expect(resolve_designs).to be_empty
+ end
+ end
+ end
+ end
+ end
+
+ def resolve_designs
+ resolve(described_class, obj: issue.design_collection, args: args, ctx: gql_context)
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb b/spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb
new file mode 100644
index 00000000000..cc9c0436885
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::Version::DesignAtVersionResolver do
+ include GraphqlHelpers
+
+ include_context 'four designs in three versions'
+
+ let(:current_user) { authorized_user }
+ let(:gql_context) { { current_user: current_user } }
+
+ let(:version) { third_version }
+ let(:design) { design_a }
+
+ let(:all_singular_args) do
+ {
+ design_at_version_id: global_id_of(dav(design)),
+ design_id: global_id_of(design),
+ filename: design.filename
+ }
+ end
+
+ shared_examples 'a bad argument' do
+ let(:err_class) { ::Gitlab::Graphql::Errors::ArgumentError }
+
+ it 'raises an appropriate error' do
+ expect { resolve_objects }.to raise_error(err_class)
+ end
+ end
+
+ describe '#resolve' do
+ describe 'passing combinations of arguments' do
+ context 'passing no arguments' do
+ let(:args) { {} }
+
+ it_behaves_like 'a bad argument'
+ end
+
+ context 'passing all arguments' do
+ let(:args) { all_singular_args }
+
+ it_behaves_like 'a bad argument'
+ end
+
+ context 'passing any two arguments' do
+ let(:args) { all_singular_args.slice(*all_singular_args.keys.sample(2)) }
+
+ it_behaves_like 'a bad argument'
+ end
+ end
+
+ %i[design_at_version_id design_id filename].each do |arg|
+ describe "passing #{arg}" do
+ let(:args) { all_singular_args.slice(arg) }
+
+ it 'finds the design' do
+ expect(resolve_objects).to eq(dav(design))
+ end
+
+ context 'when the user cannot see designs' do
+ let(:current_user) { create(:user) }
+
+ it 'returns nothing' do
+ expect(resolve_objects).to be_nil
+ end
+ end
+ end
+ end
+
+ describe 'attempting to retrieve an object not visible at this version' do
+ let(:design) { design_d }
+
+ %i[design_at_version_id design_id filename].each do |arg|
+ describe "passing #{arg}" do
+ let(:args) { all_singular_args.slice(arg) }
+
+ it 'does not find the design' do
+ expect(resolve_objects).to be_nil
+ end
+ end
+ end
+ end
+ end
+
+ def resolve_objects
+ resolve(described_class, obj: version, args: args, ctx: gql_context)
+ end
+
+ def dav(design)
+ build(:design_at_version, design: design, version: version)
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/version/designs_at_version_resolver_spec.rb b/spec/graphql/resolvers/design_management/version/designs_at_version_resolver_spec.rb
new file mode 100644
index 00000000000..123b26862d0
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/version/designs_at_version_resolver_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::Version::DesignsAtVersionResolver do
+ include GraphqlHelpers
+
+ include_context 'four designs in three versions'
+
+ let_it_be(:current_user) { authorized_user }
+ let(:gql_context) { { current_user: current_user } }
+
+ let(:version) { third_version }
+
+ describe '.single' do
+ let(:single) { ::Resolvers::DesignManagement::Version::DesignAtVersionResolver }
+
+ it 'returns the single context resolver' do
+ expect(described_class.single).to eq(single)
+ end
+ end
+
+ describe '#resolve' do
+ let(:args) { {} }
+
+ context 'when the user cannot see designs' do
+ let(:current_user) { create(:user) }
+
+ it 'returns nothing' do
+ expect(resolve_objects).to be_empty
+ end
+ end
+
+ context 'for the current version' do
+ it 'returns all designs visible at that version' do
+ expect(resolve_objects).to contain_exactly(dav(design_a), dav(design_b), dav(design_c))
+ end
+ end
+
+ context 'for a previous version with more objects' do
+ let(:version) { second_version }
+
+ it 'returns objects that were later deleted' do
+ expect(resolve_objects).to contain_exactly(dav(design_a), dav(design_b), dav(design_c), dav(design_d))
+ end
+ end
+
+ context 'for a previous version with fewer objects' do
+ let(:version) { first_version }
+
+ it 'does not return objects that were later created' do
+ expect(resolve_objects).to contain_exactly(dav(design_a))
+ end
+ end
+
+ describe 'filtering' do
+ describe 'by filename' do
+ let(:red_herring) { create(:design, issue: create(:issue, project: project)) }
+ let(:args) { { filenames: [design_b.filename, red_herring.filename] } }
+
+ it 'resolves to just the relevant design' do
+ create(:design, issue: create(:issue, project: project), filename: design_b.filename)
+
+ expect(resolve_objects).to contain_exactly(dav(design_b))
+ end
+ end
+
+ describe 'by id' do
+ let(:red_herring) { create(:design, issue: create(:issue, project: project)) }
+ let(:args) { { ids: [design_a, red_herring].map { |x| global_id_of(x) } } }
+
+ it 'resolves to just the relevant design, ignoring objects on other issues' do
+ expect(resolve_objects).to contain_exactly(dav(design_a))
+ end
+ end
+ end
+ end
+
+ def resolve_objects
+ resolve(described_class, obj: version, args: args, ctx: gql_context)
+ end
+
+ def dav(design)
+ build(:design_at_version, design: design, version: version)
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
new file mode 100644
index 00000000000..ef50598d241
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::VersionInCollectionResolver do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ let(:resolver) { described_class }
+
+ describe '#resolve' do
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:first_version) { create(:design_version, issue: issue) }
+
+ let(:project) { issue.project }
+ let(:params) { {} }
+
+ before do
+ enable_design_management
+ project.add_developer(current_user)
+ end
+
+ let(:appropriate_error) { ::Gitlab::Graphql::Errors::ArgumentError }
+
+ subject(:result) { resolve_version(issue.design_collection) }
+
+ context 'Neither id nor sha is passed as parameters' do
+ it 'raises an appropriate error' do
+ expect { result }.to raise_error(appropriate_error)
+ end
+ end
+
+ context 'we pass an id' do
+ let(:params) { { id: global_id_of(first_version) } }
+
+ it { is_expected.to eq(first_version) }
+ end
+
+ context 'we pass a sha' do
+ let(:params) { { sha: first_version.sha } }
+
+ it { is_expected.to eq(first_version) }
+ end
+
+ context 'we pass an inconsistent mixture of sha and version id' do
+ let(:params) { { sha: first_version.sha, id: global_id_of(create(:design_version)) } }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'we pass the id of something that is not a design_version' do
+ let(:params) { { id: global_id_of(project) } }
+
+ it 'raises an appropriate error' do
+ expect { result }.to raise_error(appropriate_error)
+ end
+ end
+ end
+
+ def resolve_version(obj, context = { current_user: current_user })
+ resolve(resolver, obj: obj, args: params, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/version_resolver_spec.rb b/spec/graphql/resolvers/design_management/version_resolver_spec.rb
new file mode 100644
index 00000000000..e7c09351204
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/version_resolver_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::VersionResolver do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:version) { create(:design_version, issue: issue) }
+ let_it_be(:developer) { create(:user) }
+
+ let(:project) { issue.project }
+ let(:params) { { id: global_id_of(version) } }
+
+ before do
+ enable_design_management
+ project.add_developer(developer)
+ end
+
+ context 'the current user is not authorized' do
+ let(:current_user) { create(:user) }
+
+ it 'raises an error on resolution' do
+ expect { resolve_version }.to raise_error(::Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'the current user is authorized' do
+ let(:current_user) { developer }
+
+ context 'the id parameter is provided' do
+ it 'returns the specified version' do
+ expect(resolve_version).to eq(version)
+ end
+ end
+ end
+
+ def resolve_version
+ resolve(described_class, obj: nil, args: params, ctx: { current_user: current_user })
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/versions_resolver_spec.rb b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
new file mode 100644
index 00000000000..d5bab025e45
--- /dev/null
+++ b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::DesignManagement::VersionsResolver do
+ include GraphqlHelpers
+ include DesignManagementTestHelpers
+
+ describe '#resolve' do
+ let(:resolver) { described_class }
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:authorized_user) { create(:user) }
+ let_it_be(:first_version) { create(:design_version, issue: issue) }
+ let_it_be(:other_version) { create(:design_version, issue: issue) }
+ let_it_be(:first_design) { create(:design, issue: issue, versions: [first_version, other_version]) }
+ let_it_be(:other_design) { create(:design, :with_versions, issue: issue) }
+
+ let(:project) { issue.project }
+ let(:params) { {} }
+ let(:current_user) { authorized_user }
+ let(:parent_args) { { irrelevant: 1.2 } }
+ let(:parent) { double('Parent', parent: nil, irep_node: double(arguments: parent_args)) }
+
+ before do
+ enable_design_management
+ project.add_developer(authorized_user)
+ end
+
+ shared_examples 'a source of versions' do
+ subject(:result) { resolve_versions(object) }
+
+ let_it_be(:all_versions) { object.versions.ordered }
+
+ context 'when the user is not authorized' do
+ let(:current_user) { create(:user) }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'without constraints' do
+ it 'returns the ordered versions' do
+ expect(result).to eq(all_versions)
+ end
+ end
+
+ context 'when constrained' do
+ let_it_be(:matching) { all_versions.earlier_or_equal_to(first_version) }
+
+ shared_examples 'a query for all_versions up to the first_version' do
+ it { is_expected.to eq(matching) }
+ end
+
+ context 'by earlier_or_equal_to_id' do
+ let(:params) { { id: global_id_of(first_version) } }
+
+ it_behaves_like 'a query for all_versions up to the first_version'
+ end
+
+ context 'by earlier_or_equal_to_sha' do
+ let(:params) { { sha: first_version.sha } }
+
+ it_behaves_like 'a query for all_versions up to the first_version'
+ end
+
+ context 'by earlier_or_equal_to_sha AND earlier_or_equal_to_id' do
+ context 'and they match' do
+ # This usage is rather dumb, but so long as they match, this will
+ # return successfully
+ let(:params) do
+ {
+ sha: first_version.sha,
+ id: global_id_of(first_version)
+ }
+ end
+
+ it_behaves_like 'a query for all_versions up to the first_version'
+ end
+
+ context 'and they do not match' do
+ let(:params) do
+ {
+ sha: first_version.sha,
+ id: global_id_of(other_version)
+ }
+ end
+
+ it 'raises a suitable error' do
+ expect { result }.to raise_error(GraphQL::ExecutionError)
+ end
+ end
+ end
+
+ context 'by at_version in parent' do
+ let(:parent_args) { { atVersion: global_id_of(first_version) } }
+
+ it_behaves_like 'a query for all_versions up to the first_version'
+ end
+ end
+ end
+
+ describe 'a design collection' do
+ let_it_be(:object) { DesignManagement::DesignCollection.new(issue) }
+
+ it_behaves_like 'a source of versions'
+ end
+
+ describe 'a design' do
+ let_it_be(:object) { first_design }
+
+ it_behaves_like 'a source of versions'
+ end
+
+ def resolve_versions(obj, context = { current_user: current_user })
+ eager_resolve(resolver, obj: obj, args: params.merge(parent: parent), ctx: context)
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index 53e0a9e3724..b7cc9bc6d71 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -125,12 +125,11 @@ describe Resolvers::IssuesResolver do
end
context 'when sorting by due date' do
- let(:project) { create(:project) }
-
- let!(:due_issue1) { create(:issue, project: project, due_date: 3.days.from_now) }
- let!(:due_issue2) { create(:issue, project: project, due_date: nil) }
- let!(:due_issue3) { create(:issue, project: project, due_date: 2.days.ago) }
- let!(:due_issue4) { create(:issue, project: project, due_date: nil) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:due_issue1) { create(:issue, project: project, due_date: 3.days.from_now) }
+ let_it_be(:due_issue2) { create(:issue, project: project, due_date: nil) }
+ let_it_be(:due_issue3) { create(:issue, project: project, due_date: 2.days.ago) }
+ let_it_be(:due_issue4) { create(:issue, project: project, due_date: nil) }
it 'sorts issues ascending' do
expect(resolve_issues(sort: :due_date_asc)).to eq [due_issue3, due_issue1, due_issue4, due_issue2]
@@ -142,17 +141,72 @@ describe Resolvers::IssuesResolver do
end
context 'when sorting by relative position' do
- let(:project) { create(:project) }
-
- let!(:relative_issue1) { create(:issue, project: project, relative_position: 2000) }
- let!(:relative_issue2) { create(:issue, project: project, relative_position: nil) }
- let!(:relative_issue3) { create(:issue, project: project, relative_position: 1000) }
- let!(:relative_issue4) { create(:issue, project: project, relative_position: nil) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:relative_issue1) { create(:issue, project: project, relative_position: 2000) }
+ let_it_be(:relative_issue2) { create(:issue, project: project, relative_position: nil) }
+ let_it_be(:relative_issue3) { create(:issue, project: project, relative_position: 1000) }
+ let_it_be(:relative_issue4) { create(:issue, project: project, relative_position: nil) }
it 'sorts issues ascending' do
expect(resolve_issues(sort: :relative_position_asc)).to eq [relative_issue3, relative_issue1, relative_issue4, relative_issue2]
end
end
+
+ context 'when sorting by priority' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:early_milestone) { create(:milestone, project: project, due_date: 10.days.from_now) }
+ let_it_be(:late_milestone) { create(:milestone, project: project, due_date: 30.days.from_now) }
+ let_it_be(:priority_label1) { create(:label, project: project, priority: 1) }
+ let_it_be(:priority_label2) { create(:label, project: project, priority: 5) }
+ let_it_be(:priority_issue1) { create(:issue, project: project, labels: [priority_label1], milestone: late_milestone) }
+ let_it_be(:priority_issue2) { create(:issue, project: project, labels: [priority_label2]) }
+ let_it_be(:priority_issue3) { create(:issue, project: project, milestone: early_milestone) }
+ let_it_be(:priority_issue4) { create(:issue, project: project) }
+
+ it 'sorts issues ascending' do
+ expect(resolve_issues(sort: :priority_asc).items).to eq([priority_issue3, priority_issue1, priority_issue2, priority_issue4])
+ end
+
+ it 'sorts issues descending' do
+ expect(resolve_issues(sort: :priority_desc).items).to eq([priority_issue1, priority_issue3, priority_issue2, priority_issue4])
+ end
+ end
+
+ context 'when sorting by label priority' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:label1) { create(:label, project: project, priority: 1) }
+ let_it_be(:label2) { create(:label, project: project, priority: 5) }
+ let_it_be(:label3) { create(:label, project: project, priority: 10) }
+ let_it_be(:label_issue1) { create(:issue, project: project, labels: [label1]) }
+ let_it_be(:label_issue2) { create(:issue, project: project, labels: [label2]) }
+ let_it_be(:label_issue3) { create(:issue, project: project, labels: [label1, label3]) }
+ let_it_be(:label_issue4) { create(:issue, project: project) }
+
+ it 'sorts issues ascending' do
+ expect(resolve_issues(sort: :label_priority_asc).items).to eq([label_issue3, label_issue1, label_issue2, label_issue4])
+ end
+
+ it 'sorts issues descending' do
+ expect(resolve_issues(sort: :label_priority_desc).items).to eq([label_issue2, label_issue3, label_issue1, label_issue4])
+ end
+ end
+
+ context 'when sorting by milestone due date' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:early_milestone) { create(:milestone, project: project, due_date: 10.days.from_now) }
+ let_it_be(:late_milestone) { create(:milestone, project: project, due_date: 30.days.from_now) }
+ let_it_be(:milestone_issue1) { create(:issue, project: project) }
+ let_it_be(:milestone_issue2) { create(:issue, project: project, milestone: early_milestone) }
+ let_it_be(:milestone_issue3) { create(:issue, project: project, milestone: late_milestone) }
+
+ it 'sorts issues ascending' do
+ expect(resolve_issues(sort: :milestone_due_asc).items).to eq([milestone_issue2, milestone_issue3, milestone_issue1])
+ end
+
+ it 'sorts issues descending' do
+ expect(resolve_issues(sort: :milestone_due_desc).items).to eq([milestone_issue3, milestone_issue2, milestone_issue1])
+ end
+ end
end
it 'returns issues user can see' do
diff --git a/spec/graphql/resolvers/milestone_resolver_spec.rb b/spec/graphql/resolvers/milestone_resolver_spec.rb
index 297130c2027..8e2c67fdc03 100644
--- a/spec/graphql/resolvers/milestone_resolver_spec.rb
+++ b/spec/graphql/resolvers/milestone_resolver_spec.rb
@@ -8,14 +8,14 @@ describe Resolvers::MilestoneResolver do
describe '#resolve' do
let_it_be(:current_user) { create(:user) }
+ def resolve_group_milestones(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: group, args: args, ctx: context)
+ end
+
context 'for group milestones' do
let_it_be(:now) { Time.now }
let_it_be(:group) { create(:group, :private) }
- def resolve_group_milestones(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: group, args: args, ctx: context)
- end
-
before do
group.add_developer(current_user)
end
@@ -89,5 +89,25 @@ describe Resolvers::MilestoneResolver do
end
end
end
+
+ context 'when including descendant milestones in a public group' do
+ let_it_be(:group) { create(:group, :public) }
+ let(:args) { { include_descendants: true } }
+
+ it 'finds milestones only in accessible projects and groups' do
+ accessible_group = create(:group, :private, parent: group)
+ accessible_project = create(:project, group: accessible_group)
+ accessible_group.add_developer(current_user)
+ inaccessible_group = create(:group, :private, parent: group)
+ inaccessible_project = create(:project, :private, group: group)
+ milestone1 = create(:milestone, group: group)
+ milestone2 = create(:milestone, group: accessible_group)
+ milestone3 = create(:milestone, project: accessible_project)
+ create(:milestone, group: inaccessible_group)
+ create(:milestone, project: inaccessible_project)
+
+ expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
+ end
+ end
end
end
diff --git a/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb b/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb
index 47889126531..7146bfb441b 100644
--- a/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/jira_imports_resolver_spec.rb
@@ -16,7 +16,7 @@ describe Resolvers::Projects::JiraImportsResolver do
context 'when anonymous user' do
let(:current_user) { nil }
- it_behaves_like 'no jira import access'
+ it_behaves_like 'no Jira import access'
end
end
@@ -25,7 +25,7 @@ describe Resolvers::Projects::JiraImportsResolver do
project.add_guest(user)
end
- it_behaves_like 'no jira import data present'
+ it_behaves_like 'no Jira import data present'
it 'does not raise access error' do
expect do
@@ -47,14 +47,14 @@ describe Resolvers::Projects::JiraImportsResolver do
stub_feature_flags(jira_issue_import: false)
end
- it_behaves_like 'no jira import access'
+ it_behaves_like 'no Jira import access'
end
context 'when user cannot read Jira imports' do
context 'when anonymous user' do
let(:current_user) { nil }
- it_behaves_like 'no jira import access'
+ it_behaves_like 'no Jira import access'
end
end
diff --git a/spec/graphql/resolvers/projects_resolver_spec.rb b/spec/graphql/resolvers/projects_resolver_spec.rb
new file mode 100644
index 00000000000..73ff99a2520
--- /dev/null
+++ b/spec/graphql/resolvers/projects_resolver_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::ProjectsResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ subject { resolve(described_class, obj: nil, args: filters, ctx: { current_user: current_user }) }
+
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:other_project) { create(:project, :public) }
+ let_it_be(:private_project) { create(:project, :private) }
+ let_it_be(:other_private_project) { create(:project, :private) }
+
+ let_it_be(:user) { create(:user) }
+
+ let(:filters) { {} }
+
+ before_all do
+ project.add_developer(user)
+ private_project.add_developer(user)
+ end
+
+ context 'when user is not logged in' do
+ let(:current_user) { nil }
+
+ context 'when no filters are applied' do
+ it 'returns all public projects' do
+ is_expected.to contain_exactly(project, other_project)
+ end
+
+ context 'when search filter is provided' do
+ let(:filters) { { search: project.name } }
+
+ it 'returns matching project' do
+ is_expected.to contain_exactly(project)
+ end
+ end
+
+ context 'when membership filter is provided' do
+ let(:filters) { { membership: true } }
+
+ it 'returns empty list' do
+ is_expected.to be_empty
+ end
+ end
+ end
+ end
+
+ context 'when user is logged in' do
+ let(:current_user) { user }
+
+ context 'when no filters are applied' do
+ it 'returns all visible projects for the user' do
+ is_expected.to contain_exactly(project, other_project, private_project)
+ end
+
+ context 'when search filter is provided' do
+ let(:filters) { { search: project.name } }
+
+ it 'returns matching project' do
+ is_expected.to contain_exactly(project)
+ end
+ end
+
+ context 'when membership filter is provided' do
+ let(:filters) { { membership: true } }
+
+ it 'returns projects that user is member of' do
+ is_expected.to contain_exactly(project, private_project)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/release_resolver_spec.rb b/spec/graphql/resolvers/release_resolver_spec.rb
new file mode 100644
index 00000000000..71aa4bbb439
--- /dev/null
+++ b/spec/graphql/resolvers/release_resolver_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::ReleaseResolver do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:release) { create(:release, project: project) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:public_user) { create(:user) }
+
+ let(:args) { { tag_name: release.tag } }
+
+ before do
+ project.add_developer(developer)
+ end
+
+ describe '#resolve' do
+ context 'when the user does not have access to the project' do
+ let(:current_user) { public_user }
+
+ it 'returns nil' do
+ expect(resolve_release).to be_nil
+ end
+ end
+
+ context "when the user has full access to the project's releases" do
+ let(:current_user) { developer }
+
+ it 'returns the release associated with the specified tag' do
+ expect(resolve_release).to eq(release)
+ end
+
+ context 'when no tag_name argument was passed' do
+ let(:args) { {} }
+
+ it 'raises an error' do
+ expect { resolve_release }.to raise_error(ArgumentError, "missing keyword: tag_name")
+ end
+ end
+ end
+ end
+
+ private
+
+ def resolve_release
+ context = { current_user: current_user }
+ resolve(described_class, obj: project, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/releases_resolver_spec.rb b/spec/graphql/resolvers/releases_resolver_spec.rb
new file mode 100644
index 00000000000..9de539b417a
--- /dev/null
+++ b/spec/graphql/resolvers/releases_resolver_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::ReleasesResolver do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:release_v1) { create(:release, project: project, tag: 'v1.0.0') }
+ let_it_be(:release_v2) { create(:release, project: project, tag: 'v2.0.0') }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:public_user) { create(:user) }
+
+ before do
+ project.add_developer(developer)
+ end
+
+ describe '#resolve' do
+ context 'when the user does not have access to the project' do
+ let(:current_user) { public_user }
+
+ it 'returns an empty array' do
+ expect(resolve_releases).to eq([])
+ end
+ end
+
+ context "when the user has full access to the project's releases" do
+ let(:current_user) { developer }
+
+ it 'returns all releases associated to the project' do
+ expect(resolve_releases).to eq([release_v1, release_v2])
+ end
+ end
+ end
+
+ private
+
+ def resolve_releases
+ context = { current_user: current_user }
+ resolve(described_class, obj: project, args: {}, ctx: context)
+ end
+end