diff options
Diffstat (limited to 'spec/services/issues')
-rw-r--r-- | spec/services/issues/build_service_spec.rb | 2 | ||||
-rw-r--r-- | spec/services/issues/close_service_spec.rb | 2 | ||||
-rw-r--r-- | spec/services/issues/create_service_spec.rb | 102 | ||||
-rw-r--r-- | spec/services/issues/resolve_discussions_spec.rb | 26 | ||||
-rw-r--r-- | spec/services/issues/update_service_spec.rb | 77 |
5 files changed, 176 insertions, 33 deletions
diff --git a/spec/services/issues/build_service_spec.rb b/spec/services/issues/build_service_spec.rb index 55d635235b0..bed25fe7ccf 100644 --- a/spec/services/issues/build_service_spec.rb +++ b/spec/services/issues/build_service_spec.rb @@ -136,7 +136,7 @@ describe Issues::BuildService, services: true do user, title: 'Issue #1', description: 'Issue description', - milestone_id: milestone.id, + milestone_id: milestone.id ).execute expect(issue.title).to eq('Issue #1') diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb index 7a54373963e..51840531711 100644 --- a/spec/services/issues/close_service_spec.rb +++ b/spec/services/issues/close_service_spec.rb @@ -4,7 +4,7 @@ describe Issues::CloseService, services: true do let(:user) { create(:user) } let(:user2) { create(:user) } let(:guest) { create(:user) } - let(:issue) { create(:issue, assignee: user2) } + let(:issue) { create(:issue, assignees: [user2]) } let(:project) { issue.project } let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 80bfb731550..dab1a3469f7 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -6,10 +6,10 @@ describe Issues::CreateService, services: true do describe '#execute' do let(:issue) { described_class.new(project, user, opts).execute } + let(:assignee) { create(:user) } + let(:milestone) { create(:milestone, project: project) } context 'when params are valid' do - let(:assignee) { create(:user) } - let(:milestone) { create(:milestone, project: project) } let(:labels) { create_pair(:label, project: project) } before do @@ -20,7 +20,7 @@ describe Issues::CreateService, services: true do let(:opts) do { title: 'Awesome issue', description: 'please fix', - assignee_id: assignee.id, + assignee_ids: [assignee.id], label_ids: labels.map(&:id), milestone_id: milestone.id, due_date: Date.tomorrow } @@ -29,7 +29,7 @@ describe Issues::CreateService, services: true do it 'creates the issue with the given params' do expect(issue).to be_persisted expect(issue.title).to eq('Awesome issue') - expect(issue.assignee).to eq assignee + expect(issue.assignees).to eq [assignee] expect(issue.labels).to match_array labels expect(issue.milestone).to eq milestone expect(issue.due_date).to eq Date.tomorrow @@ -37,6 +37,7 @@ describe Issues::CreateService, services: true do context 'when current user cannot admin issues in the project' do let(:guest) { create(:user) } + before do project.team << [guest, :guest] end @@ -47,7 +48,7 @@ describe Issues::CreateService, services: true do expect(issue).to be_persisted expect(issue.title).to eq('Awesome issue') expect(issue.description).to eq('please fix') - expect(issue.assignee).to be_nil + expect(issue.assignees).to be_empty expect(issue.labels).to be_empty expect(issue.milestone).to be_nil expect(issue.due_date).to be_nil @@ -117,6 +118,22 @@ describe Issues::CreateService, services: true do end end + context 'when assignee is set' do + let(:opts) do + { title: 'Title', + description: 'Description', + assignees: [assignee] } + end + + it 'invalidates open issues counter for assignees when issue is assigned' do + project.team << [assignee, :master] + + described_class.new(project, user, opts).execute + + expect(assignee.assigned_open_issues_count).to eq 1 + end + end + it 'executes issue hooks when issue is not confidential' do opts = { title: 'Title', description: 'Description', confidential: false } @@ -136,10 +153,83 @@ describe Issues::CreateService, services: true do end end - it_behaves_like 'issuable create service' + context 'issue create service' do + context 'assignees' do + before { project.team << [user, :master] } + + it 'removes assignee when user id is invalid' do + opts = { title: 'Title', description: 'Description', assignee_ids: [-1] } + + issue = described_class.new(project, user, opts).execute + + expect(issue.assignees).to be_empty + end + + it 'removes assignee when user id is 0' do + opts = { title: 'Title', description: 'Description', assignee_ids: [0] } + + issue = described_class.new(project, user, opts).execute + + expect(issue.assignees).to be_empty + end + + it 'saves assignee when user id is valid' do + project.team << [assignee, :master] + opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] } + + issue = described_class.new(project, user, opts).execute + + expect(issue.assignees).to eq([assignee]) + end + + context "when issuable feature is private" do + before do + project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE, + merge_requests_access_level: ProjectFeature::PRIVATE) + end + + levels = [Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC] + + levels.each do |level| + it "removes not authorized assignee when project is #{Gitlab::VisibilityLevel.level_name(level)}" do + project.update(visibility_level: level) + opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] } + + issue = described_class.new(project, user, opts).execute + + expect(issue.assignees).to be_empty + end + end + end + end + end it_behaves_like 'new issuable record that supports slash commands' + context 'Slash commands' do + context 'with assignee and milestone in params and command' do + let(:opts) do + { + assignee_ids: [create(:user).id], + milestone_id: 1, + title: 'Title', + description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}") + } + end + + before do + project.team << [user, :master] + project.team << [assignee, :master] + end + + it 'assigns and sets milestone to issuable from command' do + expect(issue).to be_persisted + expect(issue.assignees).to eq([assignee]) + expect(issue.milestone).to eq(milestone) + end + end + end + context 'resolving discussions' do let(:discussion) { create(:diff_note_on_merge_request).to_discussion } let(:merge_request) { discussion.noteable } diff --git a/spec/services/issues/resolve_discussions_spec.rb b/spec/services/issues/resolve_discussions_spec.rb index 4a4929daefc..86f218dec12 100644 --- a/spec/services/issues/resolve_discussions_spec.rb +++ b/spec/services/issues/resolve_discussions_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper.rb' -class DummyService < Issues::BaseService - include ::Issues::ResolveDiscussions +describe Issues::ResolveDiscussions, services: true do + class DummyService < Issues::BaseService + include ::Issues::ResolveDiscussions - def initialize(*args) - super - filter_resolve_discussion_params + def initialize(*args) + super + filter_resolve_discussion_params + end end -end -describe DummyService, services: true do let(:project) { create(:project, :repository) } let(:user) { create(:user) } @@ -23,7 +23,7 @@ describe DummyService, services: true do let(:other_merge_request) { create(:merge_request, source_project: project, source_branch: "other") } describe "#merge_request_for_resolving_discussion" do - let(:service) { described_class.new(project, user, merge_request_to_resolve_discussions_of: merge_request.iid) } + let(:service) { DummyService.new(project, user, merge_request_to_resolve_discussions_of: merge_request.iid) } it "finds the merge request" do expect(service.merge_request_to_resolve_discussions_of).to eq(merge_request) @@ -43,7 +43,7 @@ describe DummyService, services: true do describe "#discussions_to_resolve" do it "contains a single discussion when matching merge request and discussion are passed" do - service = described_class.new( + service = DummyService.new( project, user, discussion_to_resolve: discussion.id, @@ -61,7 +61,7 @@ describe DummyService, services: true do noteable: merge_request, project: merge_request.target_project, line_number: 15)]) - service = described_class.new( + service = DummyService.new( project, user, merge_request_to_resolve_discussions_of: merge_request.iid @@ -77,9 +77,9 @@ describe DummyService, services: true do _second_discussion = Discussion.new([create(:diff_note_on_merge_request, :resolved, noteable: merge_request, project: merge_request.target_project, - line_number: 15, + line_number: 15 )]) - service = described_class.new( + service = DummyService.new( project, user, merge_request_to_resolve_discussions_of: merge_request.iid @@ -92,7 +92,7 @@ describe DummyService, services: true do end it "is empty when a discussion and another merge request are passed" do - service = described_class.new( + service = DummyService.new( project, user, discussion_to_resolve: discussion.id, diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 5b324f3c706..5184c1d5f19 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -14,7 +14,7 @@ describe Issues::UpdateService, services: true do let(:issue) do create(:issue, title: 'Old title', description: "for #{user2.to_reference}", - assignee_id: user3.id, + assignee_ids: [user3.id], project: project) end @@ -40,7 +40,7 @@ describe Issues::UpdateService, services: true do { title: 'New title', description: 'Also please fix', - assignee_id: user2.id, + assignee_ids: [user2.id], state_event: 'close', label_ids: [label.id], due_date: Date.tomorrow @@ -53,15 +53,22 @@ describe Issues::UpdateService, services: true do expect(issue).to be_valid expect(issue.title).to eq 'New title' expect(issue.description).to eq 'Also please fix' - expect(issue.assignee).to eq user2 + expect(issue.assignees).to match_array([user2]) expect(issue).to be_closed expect(issue.labels).to match_array [label] expect(issue.due_date).to eq Date.tomorrow end + it 'updates open issue counter for assignees when issue is reassigned' do + update_issue(assignee_ids: [user2.id]) + + expect(user3.assigned_open_issues_count).to eq 0 + expect(user2.assigned_open_issues_count).to eq 1 + end + it 'sorts issues as specified by parameters' do - issue1 = create(:issue, project: project, assignee_id: user3.id) - issue2 = create(:issue, project: project, assignee_id: user3.id) + issue1 = create(:issue, project: project, assignees: [user3]) + issue2 = create(:issue, project: project, assignees: [user3]) [issue, issue1, issue2].each do |issue| issue.move_to_end @@ -87,7 +94,7 @@ describe Issues::UpdateService, services: true do expect(issue).to be_valid expect(issue.title).to eq 'New title' expect(issue.description).to eq 'Also please fix' - expect(issue.assignee).to eq user3 + expect(issue.assignees).to match_array [user3] expect(issue.labels).to be_empty expect(issue.milestone).to be_nil expect(issue.due_date).to be_nil @@ -132,12 +139,23 @@ describe Issues::UpdateService, services: true do end end + context 'when description changed' do + it 'creates system note about description change' do + update_issue(description: 'Changed description') + + note = find_note('changed the description') + + expect(note).not_to be_nil + expect(note.note).to eq('changed the description') + end + end + context 'when issue turns confidential' do let(:opts) do { title: 'New title', description: 'Also please fix', - assignee_id: user2.id, + assignee_ids: [user2], state_event: 'close', label_ids: [label.id], confidential: true @@ -163,12 +181,12 @@ describe Issues::UpdateService, services: true do it 'does not update assignee_id with unauthorized users' do project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC) update_issue(confidential: true) - non_member = create(:user) - original_assignee = issue.assignee + non_member = create(:user) + original_assignees = issue.assignees - update_issue(assignee_id: non_member.id) + update_issue(assignee_ids: [non_member.id]) - expect(issue.reload.assignee_id).to eq(original_assignee.id) + expect(issue.reload.assignees).to eq(original_assignees) end end @@ -205,7 +223,7 @@ describe Issues::UpdateService, services: true do context 'when is reassigned' do before do - update_issue(assignee: user2) + update_issue(assignees: [user2]) end it 'marks previous assignee todos as done' do @@ -408,6 +426,41 @@ describe Issues::UpdateService, services: true do end end + context 'updating asssignee_id' do + it 'does not update assignee when assignee_id is invalid' do + update_issue(assignee_ids: [-1]) + + expect(issue.reload.assignees).to eq([user3]) + end + + it 'unassigns assignee when user id is 0' do + update_issue(assignee_ids: [0]) + + expect(issue.reload.assignees).to be_empty + end + + it 'does not update assignee_id when user cannot read issue' do + update_issue(assignee_ids: [create(:user).id]) + + expect(issue.reload.assignees).to eq([user3]) + end + + context "when issuable feature is private" do + levels = [Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC] + + levels.each do |level| + it "does not update with unauthorized assignee when project is #{Gitlab::VisibilityLevel.level_name(level)}" do + assignee = create(:user) + project.update(visibility_level: level) + feature_visibility_attr = :"#{issue.model_name.plural}_access_level" + project.project_feature.update_attribute(feature_visibility_attr, ProjectFeature::PRIVATE) + + expect{ update_issue(assignee_ids: [assignee.id]) }.not_to change{ issue.assignees } + end + end + end + end + context 'updating mentions' do let(:mentionable) { issue } include_examples 'updating mentions', Issues::UpdateService |