diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-20 18:42:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-20 18:42:06 +0000 |
commit | 6e4e1050d9dba2b7b2523fdd1768823ab85feef4 (patch) | |
tree | 78be5963ec075d80116a932011d695dd33910b4e /spec/graphql/mutations | |
parent | 1ce776de4ae122aba3f349c02c17cebeaa8ecf07 (diff) | |
download | gitlab-ce-6e4e1050d9dba2b7b2523fdd1768823ab85feef4.tar.gz |
Add latest changes from gitlab-org/gitlab@13-3-stable-ee
Diffstat (limited to 'spec/graphql/mutations')
11 files changed, 416 insertions, 149 deletions
diff --git a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb new file mode 100644 index 00000000000..71c43ed826c --- /dev/null +++ b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Boards::Issues::IssueMoveList do + let_it_be(:group) { create(:group, :public) } + let_it_be(:project) { create(:project, group: group) } + let_it_be(:board) { create(:board, group: group) } + let_it_be(:user) { create(:user) } + let_it_be(:guest) { create(:user) } + let_it_be(:development) { create(:label, project: project, name: 'Development') } + let_it_be(:testing) { create(:label, project: project, name: 'Testing') } + let_it_be(:list1) { create(:list, board: board, label: development, position: 0) } + let_it_be(:list2) { create(:list, board: board, label: testing, position: 1) } + let_it_be(:issue1) { create(:labeled_issue, project: project, labels: [development]) } + let_it_be(:existing_issue1) { create(:labeled_issue, project: project, labels: [testing], relative_position: 10) } + let_it_be(:existing_issue2) { create(:labeled_issue, project: project, labels: [testing], relative_position: 50) } + + let(:current_user) { user } + let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) } + let(:params) { { board: board, project_path: project.full_path, iid: issue1.iid } } + let(:move_params) do + { + from_list_id: list1.id, + to_list_id: list2.id, + move_before_id: existing_issue2.id, + move_after_id: existing_issue1.id + } + end + + before_all do + group.add_maintainer(user) + group.add_guest(guest) + end + + subject do + mutation.resolve(params.merge(move_params)) + end + + describe '#ready?' do + it 'raises an error if required arguments are missing' do + expect { mutation.ready?(params) } + .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "At least one of the arguments " \ + "fromListId, toListId, afterId or beforeId is required") + end + + it 'raises an error if only one of fromListId and toListId is present' do + expect { mutation.ready?(params.merge(from_list_id: list1.id)) } + .to raise_error(Gitlab::Graphql::Errors::ArgumentError, + 'Both fromListId and toListId must be present' + ) + end + end + + describe '#resolve' do + context 'when user have access to resources' do + it 'moves and repositions issue' do + subject + + expect(issue1.reload.labels).to eq([testing]) + expect(issue1.relative_position).to be < existing_issue2.relative_position + expect(issue1.relative_position).to be > existing_issue1.relative_position + end + end + + context 'when user have no access to resources' do + shared_examples 'raises a resource not available error' do + it { expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) } + end + + context 'when user cannot update issue' do + let(:current_user) { guest } + + it_behaves_like 'raises a resource not available error' + end + + context 'when user cannot access board' do + let(:board) { create(:board, group: create(:group, :private)) } + + it_behaves_like 'raises a resource not available error' + end + + context 'when passing board_id as nil' do + let(:board) { nil } + + it_behaves_like 'raises a resource not available error' + end + end + end +end diff --git a/spec/graphql/mutations/boards/lists/create_spec.rb b/spec/graphql/mutations/boards/lists/create_spec.rb new file mode 100644 index 00000000000..1a881ac81e8 --- /dev/null +++ b/spec/graphql/mutations/boards/lists/create_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Boards::Lists::Create do + include GraphqlHelpers + + let_it_be(:group) { create(:group, :private) } + let_it_be(:board) { create(:board, group: group) } + let_it_be(:user) { create(:user) } + let_it_be(:guest) { create(:user) } + + let(:current_user) { user } + let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) } + let(:list_create_params) { {} } + + before_all do + group.add_reporter(user) + group.add_guest(guest) + end + + subject { mutation.resolve(board_id: board.to_global_id.to_s, **list_create_params) } + + describe '#ready?' do + it 'raises an error if required arguments are missing' do + expect { mutation.ready?({ board_id: 'some id' }) } + .to raise_error(Gitlab::Graphql::Errors::ArgumentError, + 'one and only one of backlog or labelId is required') + end + + it 'raises an error if too many required arguments are specified' do + expect { mutation.ready?({ board_id: 'some id', backlog: true, label_id: 'some label' }) } + .to raise_error(Gitlab::Graphql::Errors::ArgumentError, + 'one and only one of backlog or labelId is required') + end + end + + describe '#resolve' do + context 'with proper permissions' do + describe 'backlog list' do + let(:list_create_params) { { backlog: true } } + + it 'creates one and only one backlog' do + expect { subject }.to change { board.lists.backlog.count }.from(0).to(1) + expect(board.lists.backlog.first.list_type).to eq 'backlog' + + backlog_id = board.lists.backlog.first.id + + expect { subject }.not_to change { board.lists.backlog.count } + expect(board.lists.backlog.last.id).to eq backlog_id + end + end + + describe 'label list' do + let_it_be(:dev_label) do + create(:group_label, title: 'Development', color: '#FFAABB', group: group) + end + + let(:list_create_params) { { label_id: dev_label.to_global_id.to_s } } + + it 'creates a new issue board list for labels' do + expect { subject }.to change { board.lists.count }.from(1).to(2) + + new_list = subject[:list] + + expect(new_list.title).to eq dev_label.title + expect(new_list.position).to eq 0 + end + end + end + + context 'without proper permissions' do + let(:current_user) { guest } + + it 'raises an error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end + end + end +end diff --git a/spec/graphql/mutations/boards/lists/update_spec.rb b/spec/graphql/mutations/boards/lists/update_spec.rb new file mode 100644 index 00000000000..d5d8a2af6bf --- /dev/null +++ b/spec/graphql/mutations/boards/lists/update_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Boards::Lists::Update do + let_it_be(:group) { create(:group, :private) } + let_it_be(:board) { create(:board, group: group) } + let_it_be(:reporter) { create(:user) } + let_it_be(:guest) { create(:user) } + let_it_be(:list) { create(:list, board: board, position: 0) } + let_it_be(:list2) { create(:list, board: board) } + let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) } + let(:list_update_params) { { position: 1, collapsed: true } } + + before_all do + group.add_reporter(reporter) + group.add_guest(guest) + list.update_preferences_for(reporter, collapsed: false) + end + + subject { mutation.resolve(list: list, **list_update_params) } + + describe '#resolve' do + context 'with permission to admin board lists' do + let(:current_user) { reporter } + + it 'updates the list position and collapsed state as expected' do + subject + + reloaded_list = list.reload + expect(reloaded_list.position).to eq(1) + expect(reloaded_list.collapsed?(current_user)).to eq(true) + end + end + + context 'with permission to read board lists' do + let(:current_user) { guest } + + it 'updates the list collapsed state but not the list position' do + subject + + reloaded_list = list.reload + expect(reloaded_list.position).to eq(0) + expect(reloaded_list.collapsed?(current_user)).to eq(true) + end + end + + context 'without permission to read board lists' do + let(:current_user) { create(:user) } + + it 'raises Resource Not Found error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end + end + end +end diff --git a/spec/graphql/mutations/commits/create_spec.rb b/spec/graphql/mutations/commits/create_spec.rb index bb0b8c577b0..fb1baafe7bd 100644 --- a/spec/graphql/mutations/commits/create_spec.rb +++ b/spec/graphql/mutations/commits/create_spec.rb @@ -147,7 +147,7 @@ RSpec.describe Mutations::Commits::Create do it 'returns errors' do expect(mutated_commit).to be_nil - expect(subject[:errors]).to eq(['3:UserCommitFiles: empty CommitMessage']) + expect(subject[:errors].to_s).to match(/3:UserCommitFiles: empty CommitMessage/) end end diff --git a/spec/graphql/mutations/design_management/move_spec.rb b/spec/graphql/mutations/design_management/move_spec.rb new file mode 100644 index 00000000000..7519347d07c --- /dev/null +++ b/spec/graphql/mutations/design_management/move_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::DesignManagement::Move do + include DesignManagementTestHelpers + + let_it_be(:issue) { create(:issue) } + let_it_be(:designs) { create_list(:design, 3, issue: issue) } + let_it_be(:developer) { create(:user, developer_projects: [issue.project]) } + + let(:user) { developer } + + let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) } + + let(:current_design) { designs.first } + let(:previous_design) { designs.second } + let(:next_design) { designs.third } + + before do + enable_design_management + end + + describe "#resolve" do + subject(:resolve) do + args = { + current_design: current_design.to_global_id, + previous_design: previous_design&.to_global_id, + next_design: next_design&.to_global_id + }.compact + + mutation.resolve(args) + end + + shared_examples "resource not available" do + it "raises an error" do + expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end + end + + context 'when the feature is not available' do + before do + enable_design_management(false) + end + + it_behaves_like 'resource not available' + end + + %i[current_design previous_design next_design].each do |binding| + context "When #{binding} cannot be found" do + let(binding) { build_stubbed(:design) } + + it_behaves_like 'resource not available' + end + end + + context 'the service runs' do + before do + expect_next_instance_of(::DesignManagement::MoveDesignsService) do |service| + expect(service).to receive(:execute).and_return(service_result) + end + end + + context 'raising an error' do + let(:service_result) { ServiceResponse.error(message: 'bang!') } + + it 'reports the service-level error' do + expect(resolve).to include(errors: ['bang!'], design_collection: eq(issue.design_collection)) + end + end + + context 'successfully' do + let(:service_result) { ServiceResponse.success } + + it 'reports the service-level error' do + expect(resolve).to include(errors: be_empty, design_collection: eq(issue.design_collection)) + end + end + end + end +end diff --git a/spec/graphql/mutations/issues/set_assignees_spec.rb b/spec/graphql/mutations/issues/set_assignees_spec.rb new file mode 100644 index 00000000000..77ba511b715 --- /dev/null +++ b/spec/graphql/mutations/issues/set_assignees_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Issues::SetAssignees do + it_behaves_like 'an assignable resource' do + let_it_be(:resource, reload: true) { create(:issue) } + end +end diff --git a/spec/graphql/mutations/issues/set_subscription_spec.rb b/spec/graphql/mutations/issues/set_subscription_spec.rb new file mode 100644 index 00000000000..9e05a136c0b --- /dev/null +++ b/spec/graphql/mutations/issues/set_subscription_spec.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Mutations::Issues::SetSubscription do + it_behaves_like 'a subscribeable graphql resource' do + let_it_be(:resource) { create(:issue) } + let(:permission_name) { :update_issue } + end +end diff --git a/spec/graphql/mutations/issues/update_spec.rb b/spec/graphql/mutations/issues/update_spec.rb index 9a847476e2e..15c15afd9b7 100644 --- a/spec/graphql/mutations/issues/update_spec.rb +++ b/spec/graphql/mutations/issues/update_spec.rb @@ -3,16 +3,23 @@ require 'spec_helper' RSpec.describe Mutations::Issues::Update do - let(:issue) { create(:issue) } - let(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + let_it_be(:project_label) { create(:label, project: project) } + let_it_be(:issue) { create(:issue, project: project, labels: [project_label]) } + let_it_be(:milestone) { create(:milestone, project: project) } + let(:expected_attributes) do { title: 'new title', description: 'new description', confidential: true, - due_date: Date.tomorrow + due_date: Date.tomorrow, + discussion_locked: true, + milestone_id: milestone.id } end + let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) } let(:mutated_issue) { subject[:issue] } @@ -21,20 +28,22 @@ RSpec.describe Mutations::Issues::Update do describe '#resolve' do let(:mutation_params) do { - project_path: issue.project.full_path, + project_path: project.full_path, iid: issue.iid }.merge(expected_attributes) end subject { mutation.resolve(mutation_params) } - it 'raises an error if the resource is not accessible to the user' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + context 'when the user cannot access the issue' do + it 'raises an error' do + expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) + end end context 'when the user can update the issue' do before do - issue.project.add_developer(user) + project.add_developer(user) end it 'updates issue with correct values' do @@ -50,6 +59,62 @@ RSpec.describe Mutations::Issues::Update do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) end end + + context 'when setting milestone to nil' do + let(:expected_attributes) { { milestone_id: nil } } + + it 'changes the milestone corrrectly' do + issue.update_column(:milestone_id, milestone.id) + + expect { subject }.to change { issue.reload.milestone }.from(milestone).to(nil) + end + end + + context 'when changing labels' do + let_it_be(:label_1) { create(:label, project: project) } + let_it_be(:label_2) { create(:label, project: project) } + let_it_be(:external_label) { create(:label, project: create(:project)) } + + it 'adds and removes labels correctly' do + mutation_params[:add_label_ids] = [label_1.id, label_2.id] + mutation_params[:remove_label_ids] = [project_label.id] + + subject + + expect(issue.reload.labels).to match_array([label_1, label_2]) + end + + it 'does not add label if label id is nil' do + mutation_params[:add_label_ids] = [nil, label_2.id] + + subject + + expect(issue.reload.labels).to match_array([project_label, label_2]) + end + + it 'does not add label if label is not found' do + mutation_params[:add_label_ids] = [external_label.id, label_2.id] + + subject + + expect(issue.reload.labels).to match_array([project_label, label_2]) + end + + it 'does not modify labels if label is already present' do + mutation_params[:add_label_ids] = [project_label.id] + + expect(issue.reload.labels).to match_array([project_label]) + end + + it 'does not modify labels if label is addded and removed in the same request' do + mutation_params[:add_label_ids] = [label_1.id, label_2.id] + mutation_params[:remove_label_ids] = [label_1.id] + + subject + + expect(issue.reload.labels).to match_array([project_label, label_2]) + end + end end end end diff --git a/spec/graphql/mutations/merge_requests/create_spec.rb b/spec/graphql/mutations/merge_requests/create_spec.rb index ae31790f1f9..ba0ac3cbe66 100644 --- a/spec/graphql/mutations/merge_requests/create_spec.rb +++ b/spec/graphql/mutations/merge_requests/create_spec.rb @@ -22,7 +22,8 @@ RSpec.describe Mutations::MergeRequests::Create do title: title, source_branch: source_branch, target_branch: target_branch, - description: description + description: description, + labels: labels ) end @@ -30,6 +31,7 @@ RSpec.describe Mutations::MergeRequests::Create do let(:source_branch) { 'feature' } let(:target_branch) { 'master' } let(:description) { nil } + let(:labels) { nil } let(:mutated_merge_request) { subject[:merge_request] } @@ -70,6 +72,15 @@ RSpec.describe Mutations::MergeRequests::Create do end end + context 'when optional labels field is set' do + let(:labels) { %w[label-1 label-2] } + + it 'returns a new merge request with labels' do + expect(mutated_merge_request.labels.map(&:title)).to eq(labels) + expect(subject[:errors]).to be_empty + end + end + context 'when service cannot create a merge request' do let(:title) { nil } diff --git a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb index 0e7abb849c4..4ac40fc09c6 100644 --- a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb +++ b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb @@ -3,106 +3,7 @@ require 'spec_helper' RSpec.describe Mutations::MergeRequests::SetAssignees do - let(:merge_request) { create(:merge_request) } - let(:user) { create(:user) } - - subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) } - - describe '#resolve' do - let(:assignee) { create(:user) } - let(:assignee2) { create(:user) } - let(:assignee_usernames) { [assignee.username] } - let(:mutated_merge_request) { subject[:merge_request] } - - subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, assignee_usernames: assignee_usernames) } - - before do - merge_request.project.add_developer(assignee) - merge_request.project.add_developer(assignee2) - end - - it 'raises an error if the resource is not accessible to the user' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) - end - - context 'when the user can update the merge request' do - before do - merge_request.project.add_developer(user) - end - - it 'replaces the assignee' do - merge_request.assignees = [assignee2] - merge_request.save! - - expect(mutated_merge_request).to eq(merge_request) - expect(mutated_merge_request.assignees).to contain_exactly(assignee) - expect(subject[:errors]).to be_empty - end - - it 'returns errors merge request could not be updated' do - # Make the merge request invalid - merge_request.allow_broken = true - merge_request.update!(source_project: nil) - - expect(subject[:errors]).not_to be_empty - end - - context 'when passing an empty assignee list' do - let(:assignee_usernames) { [] } - - before do - merge_request.assignees = [assignee] - merge_request.save! - end - - it 'removes all assignees' do - expect(mutated_merge_request).to eq(merge_request) - expect(mutated_merge_request.assignees).to eq([]) - expect(subject[:errors]).to be_empty - end - end - - context 'when passing "append" as true' do - subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, assignee_usernames: assignee_usernames, operation_mode: Types::MutationOperationModeEnum.enum[:append]) } - - before do - merge_request.assignees = [assignee2] - merge_request.save! - - # In CE, APPEND is a NOOP as you can't have multiple assignees - # We test multiple assignment in EE specs - stub_licensed_features(multiple_merge_request_assignees: false) - end - - it 'is a NO-OP in FOSS' do - expect(mutated_merge_request).to eq(merge_request) - expect(mutated_merge_request.assignees).to contain_exactly(assignee2) - expect(subject[:errors]).to be_empty - end - end - - context 'when passing "remove" as true' do - before do - merge_request.assignees = [assignee] - merge_request.save! - end - - it 'removes named assignee' do - mutated_merge_request = mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, assignee_usernames: assignee_usernames, operation_mode: Types::MutationOperationModeEnum.enum[:remove])[:merge_request] - - expect(mutated_merge_request).to eq(merge_request) - expect(mutated_merge_request.assignees).to eq([]) - expect(subject[:errors]).to be_empty - end - - it 'does not remove unnamed assignee' do - mutated_merge_request = mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, assignee_usernames: [assignee2.username], operation_mode: Types::MutationOperationModeEnum.enum[:remove])[:merge_request] - - expect(mutated_merge_request).to eq(merge_request) - expect(mutated_merge_request.assignees).to contain_exactly(assignee) - expect(subject[:errors]).to be_empty - end - end - end + it_behaves_like 'an assignable resource' do + let_it_be(:resource, reload: true) { create(:merge_request) } end end diff --git a/spec/graphql/mutations/merge_requests/set_subscription_spec.rb b/spec/graphql/mutations/merge_requests/set_subscription_spec.rb index 20cfed9dd3d..600053637c9 100644 --- a/spec/graphql/mutations/merge_requests/set_subscription_spec.rb +++ b/spec/graphql/mutations/merge_requests/set_subscription_spec.rb @@ -3,44 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::MergeRequests::SetSubscription do - let(:merge_request) { create(:merge_request) } - let(:project) { merge_request.project } - let(:user) { create(:user) } - - subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) } - - specify { expect(described_class).to require_graphql_authorizations(:update_merge_request) } - - describe '#resolve' do - let(:subscribe) { true } - let(:mutated_merge_request) { subject[:merge_request] } - - subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, subscribed_state: subscribe) } - - it 'raises an error if the resource is not accessible to the user' do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) - end - - context 'when the user can update the merge request' do - before do - merge_request.project.add_developer(user) - end - - it 'returns the merge request as discussion locked' do - expect(mutated_merge_request).to eq(merge_request) - expect(mutated_merge_request.subscribed?(user, project)).to eq(true) - expect(subject[:errors]).to be_empty - end - - context 'when passing subscribe as false' do - let(:subscribe) { false } - - it 'unsubscribes from the discussion' do - merge_request.subscribe(user, project) - - expect(mutated_merge_request.subscribed?(user, project)).to eq(false) - end - end - end + it_behaves_like 'a subscribeable graphql resource' do + let_it_be(:resource) { create(:merge_request) } + let(:permission_name) { :update_merge_request } end end |